-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Problem statement
For the admin interface we need to decide on a tech stack/architecture.
The main constraints are:
- rich interface: need to display graphs and interact with elements on the page.
- reduce development impact: features for the admin should not take too much energy
- secure: ensure a secure login since we will be exposing information and affordances that should be available to a malicious actor
- maintenance: project should be easy to maintain, otherwise it will be tech dept from the get-go.
Solutions
There are a few solutions that we could use. In the next section we highlight their advantages and flaws to help us decide on a solution.
Classic Backend + SPA frontend
This is the classic structure. We are quite familiar with it.
The backend is nodeJS, could be our current backend with an admin plugin that only allows admin users in.
The frontend is a React SPA.
Pro:
- React SPA allows for rich content and we already know the patterns
- backend already exists and auth for admins is nearly done feat: add GitHub OAuth for admin #1929
- stack is already known and developers are proficient with it
Cons:
- splits the development in 2 projects, need to sync the api routes with the client compoenents. This already a burden for the client facing application, do we really want to deal with it for our internal tool ?
- react SPA is maybe overkill for an admin interface, cost of development for a page would be very high
- With the current architecture, the cookie set by the backend is set on a large domain, we potentially want to restrict to only the admin paths, this is currently not possible and could clash with the user cookie and provide less secure access.
- admin is on the same server as the main application, if the application is down, we do not have an admin
Required steps if we choose this option
- create a frontend project or add pages to an existing one (client for example)
- ensure cookie is available to the frontend
- ensure CORS are correctly set
SSR application
We recently finished migrating the library to be a tanstack start project, it is a server-side rendered application written in ReactJS. This allows for most of the interface to be computed on the server and only little JS is sent to the client. This also allows to develop the api route/ fetching of data and the rendering in a single repo.
Pro:
- single repo for developing admin features
- modern stack, provides fast load times and minimal JS
Cons:
- more subject to changes in the API and framework, so more maintenance
- less familiar with the patterns used in SSR, testing is still not easy as it requires to have mocking at the server level (client mocking is not enough)
- Currently we do not leverage the db directly in the library ssr, we rely on api calls to the backend. We would need to add drizzle schemas, and auth to make it complete
- There is an argument to be made about putting the admin panel inside the library project. This is indeed not the first place we would think, but the library already provides the setup for the ssr with the deployment in place.
Required steps if we choose this option
- add authentication middlewares to our current SSR
- add a connection to the database with drizzle schemas (copy current one from the BE)
A new framework, Phoenix (Elixir)
There is an opportunity to implement this admin panel in another language and tech stack.
Phoenix with Elixir could be a good option. Phoenix is a mature framework for developing web applications in the Elixir language.
Pro:
- there are a lot of things included in Phoenix by default, it requires a lot less guess-work and ad-hoc decisions.
- concurrency model is top notch, with fault tolerance it handles crash very well, app stays available even in the event of a localized issue.
- very good debugging capabilities, it is possible to debug issues in a running environment
- With LiveView, there is options for rich and interactive interfaces on par with client side application created with react.
Cons:
- new language to learn, not all developers are familiar with it
- one more project, this increases the maintenance surface. we can reduce this by eventually migrating more logic to this new project if we find that it is faster and simpler to develop in this new stack
- perform worst on spotty network, such as slow mobile internet, since it relies on a persistent WebSockets connection for interaction updates.
Required steps if we choose this option
- Setup a project
- migrate the DB schemas to Ecto and elixir definitions
- setup a deployment
There is obviously more unknown in this option but there are also some motivations to discover a new thing.