I played with HTMX and I think it just pushes complexity into the back end that now needs to render full and partial pages. Granted on the back end you get to do traditional programming and pick your language
Not sure I agree. Yes, it requires more work on the back end: rendering templates for whole pages and parts of pages, then integrating them. I've done it with Python (FastAPI/Jinja2 & htmx). My only SPA experience is with dotnet on the back end and Angular on the front. Based on that experience:
1. Python with htmx has less accidental complexity. It doesn't get rid of intrinsic complexity of the domain, but it does reduce technology-induced overhead.
2. Dotnet/Angular tech split has organisational implications, tending to encourage a division between front end and back end developers. Communication and coordination overhad goes up correspondingly (Conway's law).
3. htmx is stable. There's a lot less churn than with Angular. I haven't measured this, but subjectively, there's less time spent updating packages and re-testing. Keeping FastAPI/Django/Python update is approximately equivalent keeping the dotnet back end up to date.
4. State management is simpler. There's no front end caching to deal with, and so no corresponding cache invalidation questions.
I'm not building tech unicorn sites, so can't comment on whether the technical overhead is justified at that scale. I _have_ been pleasantly surprised at the level of UI sophistication that can be achieved with server side rendering and htmx.
I'm not a big javascript fan generally, so definitely have bias. I also have an increasingly allergic reaction to accidental complexity, so am constantly looking for ways to minimise it.
Based on those biases and experiences, my default starting point is SSR+htmx. In my experience the accidental complexity is lower, productivity higher, and intra-team communication better. YMMV obviously.
I imagine that by moving this to the backend you could guarantee (at compile time) that all Ajax calls on the client have an associated backend endpoint. This eliminates dead urls, and gives you more opportunities for code generation or IDE-style autocomplete when creating Htmx views.
Do this in a static functional language and your whole app will more “deterministically pure”.
So yes, it causes more work on backend but, given more tooling, it can provide more opportunities for less code written overall via code-generation (like how creating a model in Rails generates lots of helpers).
In a lot of cases you can go a long way without having to adapt the backend at all - just request the full page at the existing url and pick which part you want to replace. Works well enough with a page that presents paginated items for example.