Posted by Ralfp 10 hours ago
The problem I had was that the entire experience became really slow when I had it all working together as one "response". Sending back all that HTML for an entire form with some large select lists as well as the response of results became noticeable laggy when there was more than a half dozen results.
I ended up switching to Alpine Ajax (https://alpine-ajax.js.org/) and pulled the form out of the response and just used a local x-data on it to track the state. This greatly reduced the HTML I needed to send back to just the list of results. I did make the form a bit more complicated but the experience felt a lot snappier. Both versions just synced the form state from the URL and kept the initial render as full HTML from the server.
I found that Alpine + Alpine Ajax was SMALLER than HTMX 4 even though (in my opinion) it offers a lot more features in a more approachable and intuitive way if you need to do interactivity and don’t want to trigger a request just to toggle some classes or attributes. Of course you can use both together (I started down that road) but you are mixing worlds and making the bundle size bigger at the same time.
I still like HTMX and will probably use it again. I just found that with an interactive experience like a product listing page, where the HTML response was quite large/expensive to fetch, it wasn’t the best choice for that.
https://github.com/dsego/ssr-playground/blob/main/src/server...
It was only the right side results of the experience that needed to be refetched when the form changed.
But in HTMX, you are expected to just send the whole dang thing back for every change. Makes sense for a like-button, a dialog, or even a classic form submission.
My refactor cut the HTML response by about 70kb and that made a big difference. The form became fully static and I had a simple Alpine data component that would just sync that state with the URL. Still used a GET on the form and still used the same partial endpoint. Just way less HTML to wait for.
I think dynamically fetching results (ala infinite scroll) would have been more complicated to build. I would have had to add an intersection detection (HTMX 4 has that) to trigger the form/request again, but with an ever increasing chunk offset slice. I also need a way to track that state as well. Considering I had one big HTML response, I don’t think I could have done that efficiently without splitting it anyway. Even if I could "pluck" the results I needed from the HTML response, the penalty of waiting for the response was the factor.
If you have any links to some demos where there is something like that, I would appreciate it.
All that being said, the count of items actually isn't the most relevant part. The most relevant part is the amount of HTML per single result. If you have a sophisticated card component (a title, a description, images, a table of information inside of it or complicated layout) just loading six cards could end up being hundreds of HTML elements.
So even if you lazy loaded elements in chunks, those chunks are still gonna take a while to fetch given the size of the HTML. You also break CTRL-F-ing since those results don’t exist in the DOM until you trigger their fetching code. Same problem as classic pagination.
I would have to completely refactor my entire experience regardless because if I want to lazily load the cards/results gradually, I would have to split up the layout to make it more efficient.
So my approach to shrink the HTML response was to break it up the "live" section to just the right half.
With HTMX you can do partial rendering and live updates via server-sent events. This gets you most of the way to the "client side" feel where things load dynamically based on user actions.
The only properly dynamic SPA-like feature in a forum I can think of is a WYSIWYG editor, but that you can build as a web component. Maybe a flexible highlight and quote system would be a bit difficult in pure HTMX (think of the comment functionality in Medium posts). So you'd want to build a few things in client side JS. But the main experience could very well be built with HTMX.
I'd extend this to "web apps that revolve around forms, views, filters and pagination" when it comes to "Ajax" stuff (yes, I'm old).
The part of htmx that's relevant to these topics being discussed here, I once wrote an inferior clone of, some years ago.
It was "isomorphic", tailored to our PHP-based CMS, and could handle filters, search forms, and pagination.
Suitable for forums definitely, and current PHP-based forum software vendors that are still on the market follow the same paradigm.
I'd say that "Endless Scroll" is a good example of something that is... well maybe not interactive but still breaks the "just an HTML document" page metaphor that plays nice with such things.
Now, personally I find the UI compromises it takes to make endless scrolling happen are abhorrent (like not being able to ctrl-F or export the page content). But other people obviously like them.
Is that the kind of thing you'd be giving up as you move to a platform like HTMX?
Maintaining a code path with a snippet for each possible viewing experience, back when REST was all the rage, was a bit obnoxious though.
If you want basic interactivity, HTMX is fine.
If you want something more (like sortable) I'd reach for lit instead of adding the Sortable.js dependency, something the HTMX docs suggest ( https://htmx.org/examples/sortable/ )
And yes there are also some scenarios that you want to control the whole routing and rendering stuff, then go for Solid, React, Angular, Vue, whatever.
There is no golden rule to all of this but finding out what makes sense is a fun exercise.
But interactivity in largely content-driven sites doesn't necessarily preclude HTMX. You can do a bunch of fancy interactive stuff with HTMX and some minimal JS. Drag and drop sort is a tiny drop-in JS snippet. Skeleton loaders and spinners are supported out of the box in HTMX as is infinite scroll as others pointed out.
I'm not saying Next.js, Solid Start, Remix, Nuxt or some other hybrid server and client rendered model doesn't work for forum software. Or that even client only rendering can be a valid approach if you accept the trade-offs (no curl-ability). People should use whatever they feel productive building with.
But if your backend is already a non-JavaScript server rendered framework like Django then HTMX makes a ton of sense to add some interactivity.
Otherwise, I'd recommend HMTX even if you have a super flexible JS backend.
That said, this is all baseless thinking without seeing any requirements and as I said before, trying to choose the right abstraction is the hard but fun part.
"Fun" as in you're years into a project before you fully accept that you made the bad call.
I get lazy-loading for pages that contain a ton of media of which the user will likely only see a fraction. But some people seem to think infinite scroll is a good idea with text based content as well..
That's how interactivity has always worked.
Server-side render everything + ship interactivity via js on top of it.
I feel like most of the web developers forgot that React/Vue/etc solve a specific problem: single-page application.
This is a very narrow and specific problem: navigating from page to page not causing full page reloads.
But the web has changed since SPAs were needed in major ways:
1. the average device and connection is insanely faster than 10-15 years ago. Receiving and rendering content is not the problem it once was in the age of 2g connections and limited hardware mobile devices. Even the very low end phone from few years ago has nowadays 0 problems loading and parsing few hundred kbs of html and js.
2. Web technologies moved at all levels. Server technologies, cloud ones, browser ones. React and company are solving problems that barely belong to the modern web.
In short: today you can have an app-like, spa-like experience even out of fully server-side rendered applications. While also benefitting from shipping much less code to the client.
There's a very minimal amount of websites and applications out there that benefit, and aren't crippled by these rendering libraries: those that vastly leverage offline capabilities of the platform and want to keep working regardless of internet being available. I'm talking the notions and linears.
But bar from those, still working with this React slop is just not good for the user. Even multi billion companies hiring leetcode ninjas can't get acceptable user experience and performance out of those libraries, and it's not a coincidence: they keep forcing the wrong tool for the wrong problem.
They keep living in 2018 and at the end of the day the only excuse for those react/angular+tailwind slop is that there's an entire generation of developers that doesn't know anything else and has long lost any proper engineering skill (if there is any) in finding the right tool for the problem. This is a familiarity issue, not sound technical decisions. It's the "you can't go wrong with oracle/mysql/ibm", but actually you can, and it shows.
What's worse: it's incredibly cheap to experiment different solutions and approaches via LLMs in 2026, but people keep slopping the same monstrosities.
Using the same reasoning, I’d come to the opposite conclusion. Devices are much faster than they were 10-15 years ago, but network latency is still roughly the same because physics limits how much it can improve. So reducing network round trips matters more than ever, which favors SPAs over MPAs.
SPA’s tend to require more network round trips, sometimes significantly more based on the architecture.
The UX for an SPA can indeed be excellent, but the average SPA is worse than the average MPA, in my opinion. It’s just much easier to break things in many subtle ways in an SPA.
The creator of HTMX would disagree with you (as the person who described and coined the term REST)
https://htmx.org/essays/how-did-rest-come-to-mean-the-opposi...
That's not true. They solve the problem of requiring separate code paths for interactive elements - one for initial render and another for updates.
Previously the server rendered the initial HTML and then client JS updated it after e.g. user clicks a button, but with React/Vue/etc., it's merged into one code path because HTML is derived from the current state.
> Even multi billion companies hiring leetcode ninjas can't get acceptable user experience
Modern UX is bad because many front-end programmers fundamentally just do not care about the UX, it's not about the specific tech they use.
This is untrue and is weird misunderstanding on your part. Most of modern UX and UI is designed to fit the needs of the customer for the frontend team/dev: the product or marketing or sales department. The user of the website is very rarely the customer for the dev.
That's the definition, I didn't made it up.
And those libraries solve that.
Your other definition, can be fully implemented server side, Elixir's Phoenix does that. But it's not the only one.
Your prior claim was that they only solve one problem, not about a definition. They solve several problems:
- less data can move over the wire compared to sending a full page every time (this is in your definition, and is definitely not always true, as sometimes REST APIs can return far more data than what's needed to render the screen)
- the same REST/data API can serve your website and other consumers, e.g. any native mobile apps or third party API consumers
- you can write tests for your frontend, e.g. you can unit test components' behaviour and style in isolation
- the frontend can also work, or at least respond usefully to the user, when the network or the backend are not working
In a reasonably complex application, each interface ends up needing its own shape of optimized APIs. Otherwise the clients become very complex munging/reshaping data or making too many API calls, throwing away a lot of data etc.
According to what you said, CSS also solves the problem of making an SPA because you could "switch pages" by changing CSS class names on `body`. But if someone asked what CSS is you're not gonna answer "you use CSS to make an SPA", even though _technically_ you can use it to make an SPA.
After initial page load, a service worker could intercept all the HTMX app's AJAX requests, but it could only work with what's already cached. Using a lot of tooling like workbox the developer could pre-cache the entire app. (Would that mean no dynamic responses?)
Alternatively, implement the entire HTMX app in JS, build the app once for the NodeJS/Deno backend and once for the front-end. After page load, the frontend could take over.
Or something like that. It's a bit convoluted as PWA solutions often are.
Have you found nice workarounds for that?
If you'd like to find out how I build Mobile-first apps with Go, HTML and HTMX hit me up.
Example: Render a scrollable list and you need to change contents of the li items mid scroll - it resets the scroll position to the top because of how it replaced the entire HTML on render. There are workarounds you can do, DOM hacks, but they aren’t ideal.
React is designed around that kind of thing. They do some funny magic under the hood to support seamless DOM reconciliation and things like prop drilling of entire components on the prop of another, and so-on. This gives them a more granular way to manipulate the DOM without total page re-rendering.
Next.js SSR works because it’s designed around React. So they’re giving you all the SSR stuff you want but you still get client-side React for rich interaction design and other SPA niceties.
So if someone releases an SSR-like thing like htmx it feels like something is missing.
Maybe htmx needs an opinionated framework that gets more into high performance rendering and state management.
Or maybe they hone in on the “basic web pages” market. Who knows, maybe those make a comeback somewhere. PDF gets replaced with standalone HTML or something, and people use HTMX, or maybe it’s used in a dev environment for HTML email design in some future where email can have events (who knows). Couple of ideas.
Right now it feel incomplete or has nowhere for me to plug it in. Love the concepts though, HTML/JS should have been like that.
This issue is reporting the same kind of thing - text selection is lost on re-render
Because you can always just put a mini residential building inside a parking garage if you need tenants.
Need an office? Just put a mini office in the parking garage. It's perfect.
Parking garage construction is so clean and simple. Other buildings are too complex! From now on, I'll only build parking garages.
(Then I guess you have the opposite example of the residence without the parking garage! It's a great place to live, but there's nowhere to store my things and park my car!)
However for some really complex mini apps, that's another story. But for the rest of those CRUD pages, you can go simple server side rendered.
Again, the issue with htmx is that it pretends like it is not a framework, when in fact, it is just a second attempt at angular 1.0, with even more naive assumptions about web apps.
If it's a sub-function of a bigger ensemble that mostly dies something else then it's fine to call them “mini apps”.
For instance a bank app may contain a text editor for the internal messaging feature of the app, that would count as a min-app in that context.
In fact, the complexity of Chat Messages and Notifications synchronisation is one of the prime reasons why React exists.
Which makes it even more ironic that in the 10 years since React was announced in 2013 and when I quit Facebook, they never managed to fix the original state synchronization bug that they demonstrated in the original React announcement for more than a few months at a time at best.
I'm sure technically it wasn't a singular bug over the years and the causes were complex, but React did fuck all in relation to the unread message counter being correct.
SSE is perfect for chat/notifications and is a lot simpler than syncing. The server pushes updates to the client doesn't require a sync. SSE is also more performant since it can keep the connection open. The example below is on a $10 vps last I heard.
It works quite well, and saves me an awful lot of tedious mucking about with other stuff.
Hono + WebComponents + HTMX + serverless is the backend for my apps now.
although i wonder if LLM changes things
i am interested in moving away from React but its also what LLMs know infinitely more of than HTMX