Tell me about it, same thing happened to me! Having 10 OpenAPI specs to read may help a bit, but I would prefer organizations to rethink whether microservice is the right fit for them, instead of blindly buying into the hype.
But to answer your question, the best solution will depend on the complexity/flashiness of your UI and whether you want to implement the web UI components yourself.
Here is my experience with various ways to implement the web frontend:
- Plain JavaScript/Typescript:
Easy access to vast ecosystem of UI components. But sometimes it’s hard to find a set of components that have similar level of quality.
- JavaScript/Typescript frameworks:
Easy access to quality, premade UI components for the big players like React, Vue, and Angular, but adds complexity to the project, and there will be times that you have to fight against the whole browser/DOM behavior if you have something that is complex/specific enough.
- Haskell and Haskell-like frontend frameworks:
Extremely ergonomic to stay in the Haskell functional paradigm, but you lose access to the vast ecosystem of UI components made by the community. So you will have to be willing to implement the UI components yourself, this may require a fair amount of DOM behavior knowledge.
Generally, the more you rely on premade UI components, the further up the list you go. On the other hand, if your UI components are more custom and rather unique, then you might as well move closer to the Haskell stack (unless it is out-of-scope of the framework, then you fall back on JavaScript).
I usually don’t find myself using made-from-scratch UI components, but I also don’t like the add complexity of frameworks like Angular and React, so I find myself gravitating towards the more lightweight AlpineJS and combining that with TailwindCSS.
Another thing to think about is do you need to maintain user session state?
And a related question is are you okay with state and business logic leaking out on the frontend? Which can easily happen if you use frameworks/libraries like Angular and React, as they tend to encourage that by being so featureful.
If you’d rather track user session state on the server-side, then you can simplify the frontend by using more lightweight solutions.
As a general rule of thumb for managing application states, if your requirements allows for this, it’s much simpler and robust to manage state in either the server or client side, and not both. So for stateful frontends, I have a stateless backend; and for stateful backends, I use very simple frontends to display whatever the server sends.
On the spectrum of server-side and client-side web applications, I’ve been from the server-side, to full JavaScript-based frontend applications that only use backends for database operations, and now I am back leaning on server-side again (unless I need the distributed properties of a client-side app). I feel many hyped “modern” properties of a JavaScript-based clients can be replicated on a server-side solution with just a sprinkle of JavaScript and, like others have mentioned, HTMX. And it’s much easier to debug when your backend is a statically typed language like Haskell.
I hope this is helpful and I have not confused you further, as sometimes the way web technologies work is rather convoluted.