I built a fairly large SaaS app using HTMX and Alpine. It has worked wonderfully.
HTMX really shines in a few areas for me.
1. Async loading of things (ex: render a dashboard and THEN load the chart data) to prevent blocking page loads.
2. Lazy loading of things (ex: Instead of rendering a modal for every row in a table, fetch and display the modal when the row edit button is clicked).
3. HX-Boost is nice. I have always been a fan of Turbolinks (classic) and preventing full page loads and allow permanent page elements. Boost makes it possible out of the box.
4. It leaves wiggle room for progressive enhancement. For example, if you are lazily loading a modal but JS is disabled, you could open a separate page for the modal/form instead of lazily fetching and displaying in-page. It's more work, but at least it's _possible_.
Alpine on the other hand is nice for different things. I mainly use Alpine for things like handling a dropdown, slideout, animating things, etc.
All of this is done without writing any JavaScript. I am able to stay in my HTML templates or backend (in Golang) without ever touching JavaScript. I also adopted Tailwind for the same reason. I essentially write the CSS in the HTML (with classes) and let tailwind compile and generate the CSS for me... no more unused CSS. No more CSS clashes, naming conventions, etc.
It's a great workflow.
edit:
I just wanted to say I use HTMX with the head-support plugin bundled together. @recursivedoubts, hoping for 2.0 soon to come with support built in :)
i'm the author and I think this article holds up pretty well, particularly the "Javascript: The Resistance" part
one thing that I didn't note in that section regarding edge computing is that if the data store isn't edge, then putting compute on the edge doesn't help that much, which vercel has started to admit (https://twitter.com/t3dotgg/status/1781881405397442947).
i'll state my position again: htmx makes hypermedia a more competitive approach for many web applications, but it isn't right for everything. i'm not puritanical about approaches and agree strongly w/ Rich's take on "transitional apps" where you use the right tool for the given job.
where i'd probably disagree w/ Rich is where the line is: i think w/ things like htmx (or unpoly or hotwire or datastar, etc.) the total space of problems that can be effectively addressed with hypermedia expands significantly
I really dislike the discourse around htmx. I think the closest words I can use to describe it is glib, insincere and reductive (and yes I get that it's supposed to be meme:y).
It pretends to not be a JS library/framework while it is. It tilts at windmills that are badly structured/built apps.
I agree that most webapps are built on too large libraries. I agree that the dependency chains are crazy. etc. etc.
But the solution proposed by htmx is IMO bad and the self-righteous tone is even worse.
I enjoy the somewhat irreverent takes. They seem appropriate when directed at the often entirely inappropriate use of some modern frontend frameworks.
I've worked with some newish developers that know of no other way than to bring in a frontend framework for the simplest of things. E.g. adding a carousel (don't ask) to an existing site that has no need for a build step and the first thing they want to do is bring in node and react.
I always see these takes and I find them completely at odds with my experience. I have rarely seen a non-trivial frontend project that wouldn't benefit from a build step.
Going without a buildstep meant remembering the last 2-5 versions of JS and then having to write in the lowest common subset for your browser compatibility requirements. Speaking for myself: being able to keep up with the language evolution and transpile to that compatible subset automatically saved way more pain than configuring a build step cost me.
I don't think it's unreasonable to only want to have to write and read a single dialect of JS across projects. Nevermind all the polyfilling we had to do to get common compatible APIs.
Nowadays, the most recent crop of browser versions are a lot more similar to each other than they used to be.
Maybe your colleagues don't know the DOM APIs or are less comfortable with finding some random jQuery plugin to do a carousel but I can't really begrudge anyone for wanting to have the full capabilities of a modern frontend stack.
Neither does htmx. They have said repeatedly that htmx is just an implementation, those can come and go. What's important is the concept of hypermedia and the way it enables designing web applications.
i understand people who dislike the htmx meme-driven vibe and there are certainly times when i go over the line (i'm a one man shop trying to compete w/ libraries from Facebook/Vercel & Google) but i try to be balanced about when hypermedia is and when it is not a good approach:
I don't mind memes, I often like them. One part I dislike is that you seem to say you are apart from js libraries/frameworks when you are a part of them.
Seems to me like htmx tries really hard to market as "just hypermedia" and it's not. Besides things like 'hx-ws' or 'hx-on' we've already talked about the normal cases where you need custom scripting like normal error-handling.
Just hypermedia (as both the UI and API) has been around for 3+ decades. htmx isn't that and should not claim to be that.
> you seem to say you are apart from js libraries/frameworks
Besides memes I don't see this at all. The htmx project doesn't shy away from what it is: javascript.
Hypermedia has stagnated for 2+ decades. Asserting that hypermedia cannot be more than what current implementations have delivered is stolid and myopic.
htmx represents a vision of: 1. What is the core idea of hypermedia? 2. What would hypermedia look like if the core idea was logically extended to be more useful than the original implementations? and 3. How can you use javascript to fill the gap between the html+http that we have, and this expanded idea of what hypermedia could be?
Obviously it has to do this as a javascript library because that's the only possible path. And it's great that existing web technologies are flexible enough to explore interesting ideas like this. But it's silly to discount a project because it's based on a particular vision of how to add life back to older technology.
htmx is hypermedia oriented in that, when it makes network exchanges, those are in terms of hypermedia, which differentiates it from most js libraries. Not all, there is unpoly, Hotwire, etc as well.
Sse and web sockets are extensions. Hx-on is to address the fact that standard on* attributes can only handle fixed events, but I agree it is wandering away from the core hypermedia functionality of htmx. I was on the fence on adding it, but relented when we found a good mechanism for supporting it (xpath) and some long time users expressed that they wanted to avoid needing something like alpine for the simple scripting use cases of their apps.
Htmx also fires a lot of events and I don’t make a secret of the fact that scripting is part of fieldings description of the web and perfectly acceptable in a hypermedia driven application:
I would like to shitcan our front end team, and replace the app with a stupid-simple MPA with some sprinklings of HTMX that even a “backend” dev won’t have too much trouble with, but I can’t - we’re in too deep at this point.
We had a 2 two-week sprints where they couldn’t decide on a date selector and had to build our own. Then there’s this huge GraphQL monstrosity we have to support the front end - but it’s better than REST, I think?? Ah I could rant..
How does all the "executed once on the first request" and video keeps running work in htmx? Is it an SPA, from the browser's perspective, just an SPA that follows the MPA model, in its interactions with the server, basically applying a diff to the SPA state? Not saying that's a bad thing, just trying to understand. Could be an awesome migration path to get some SPA benefits into an existing MPA.
in plain htmx, you can target an area that doesn't disrupt a playing video (e.g. the comments box appending to the comments) or you can use a morphing algorithm that disrupts the DOM less.
i have my own morphing algorithm (and a corresponding htmx plugin that allows you to use it) called idiomorph:
With htmx, you plan and prepare partial page updates yourself and htmx swaps them in for you.
With React, you get to maintain the entire npm toolchain that your app depends on, including fun things like 'React 19 will no longer patch the fetch() function, so you have to handle double-fetch manually'.
Yeah, it doesn't really read like it matches much with the claim of the article that htmx is the rebirth of the MPA.
But then on the other hand, the picture that builds in my mind turns more and more into "SPA, but everything is declarative" (except for extensions to the declarative toolkit that are easy to keep separated from domain code), and that could really be quite awesome. More so when you come from an MPA background anyways. (or when your codebase comes from an MPA background!)
No, it's old.
HTMX is just intercooler.js which has been getting shilled here by the author for the last twelve years and no one wanted anything to do with it then and many want nothing to do with it now.
HTMX is one of those things that I love the idea of, but I haven’t yet used it in a way that I really enjoy. Go’s HTML templating made it fairly good but it still didn’t feel great to use.
There is some truth to this. Imho the next level of htmx is unlocked when you componentize everything like a React app...but with nested routes corresponding to nested components like a Remix app...and using an HTML generation DSL embedded directly in your language, so HTML becomes a first-class citizen of your language's constructs, rather than a templated afterthought. I have a demo of this: https://github.com/yawaramin/dream-html/tree/todoapp/app
Controversial prediction: the web/applications will largely calcify around TypeScript/React/Node.js/Electron.
Reasons:
1. It's...already happening. (See: job listings, big web platforms, popular desktop apps.)
2. Deploying one unified codebase on the web, mobile, and all major desktops is a phenomenal value. Nobody cares that HN people hate the lack of native controls, slower performance, memory usage, whatever. Good enough is good enough.
3. Vastly less friction hiring from the world's largest dev pool and onboarding them to codebases written with familiar tech.
4. TypeScript's system blow away most other type systems, and sharing them between front/backends is a big deal.
5. Node.js can do nearly anything, is fast (enough), and pulls tools from the largest community of packages on Earth.
6. UI frameworks often heft around piles of heavy abstractions. Nobody wants to learn yet another awkward, shitty programming language that you invented with your templating system. Or the heap of classes needed to do basic things "properly." React avoids this junk and stays simple -- write everything in pure TypeScript (no templates!), declaratively, with a minimal lib. KISS.
To save time replying to common misconceptions: No, JSX is not templating; Yes, tech/tool competitor ABC exists -- TS/Node/React's momentum will slowly kill it; If you like kitchen-sink frameworks, plenty of extremely popular/polished/active ones exist for making SPAs, MPAs, and mixtures between using React; Yes, programming problem space XYZ won't adopt this stack due to particular constraints, you're missing the point;
There, hopefully I pissed off everyone with my overly snarky and opinionated position. I deserve the hate. (I'm still right, tho.)
An actual controversial opinion: a big project will successfully use a Rust web framework like Dioxus rather than JS. People will take note that they can build their entire stack in a single language, and deploy it to any device that supports webview as a tiny binary. No electron. Slowly, the economics of this simplicity chips away at JS until one day rust can interact with the DOM directly and JS is relegated to legacy.
I'm liking the standardization in web. I think it's possible that you'll see something in web like you see with C/C++. D is better than C++, but it isn't compelling enough to jump. You need a very compelling set of features to leave the very comfortable, though dangerous, home of C/C++ for the domain that it excels in. With web, you'll need compelling features to leave the comfortable home of Typescript + React.
You're right about D, but Rust is drawing some people away from C and C++. Something may emerge that will do the same on the JS front-end. In fact, I'd say that the TypeScript/React combo is more susceptible to being replaced than C and C++ are. There are many large C/C++ codebases that represent many man-years of work and won't be rewritten or thrown away any time soon. JS front-ends don't have that kind of longevity. Think about how many web startups just fizzle out, and their code just goes away.
This is not a controversial take, it is just the status quo.
> Deploying one unified codebase on the web, mobile, and all major desktops is a phenomenal value.
Yeah, except when it doesn't work because of fun cross-platform incompatibilities like 'React Native Toast library doesn't support web'.
> Vastly less friction hiring from the world's largest dev pool and onboarding them to codebases written with familiar tech.
Sure, if you don't have to think about legacy codebases full of class components, hooks, Flow.js, and other technologies, and only have to care about the latest and greatest React version, it's all good.
> TypeScript's system blow away most other type systems,
In complexity, and compile times, sure. There are simpler and more powerful type systems out there, eg ReScript.
> Nobody wants to learn yet another awkward, shitty programming language that you invented with your templating system
Agreed, and it's my opinion that everyone should use HTML rendering libraries in their chosen programming language.
> React avoids this junk and stays simple -- write everything in pure TypeScript (no templates!)
Sure, if you don't count JSX as a 'template' with some 'awkward' syntax, like `className` etc.
HTMX really shines in a few areas for me.
1. Async loading of things (ex: render a dashboard and THEN load the chart data) to prevent blocking page loads.
2. Lazy loading of things (ex: Instead of rendering a modal for every row in a table, fetch and display the modal when the row edit button is clicked).
3. HX-Boost is nice. I have always been a fan of Turbolinks (classic) and preventing full page loads and allow permanent page elements. Boost makes it possible out of the box.
4. It leaves wiggle room for progressive enhancement. For example, if you are lazily loading a modal but JS is disabled, you could open a separate page for the modal/form instead of lazily fetching and displaying in-page. It's more work, but at least it's _possible_.
Alpine on the other hand is nice for different things. I mainly use Alpine for things like handling a dropdown, slideout, animating things, etc.
All of this is done without writing any JavaScript. I am able to stay in my HTML templates or backend (in Golang) without ever touching JavaScript. I also adopted Tailwind for the same reason. I essentially write the CSS in the HTML (with classes) and let tailwind compile and generate the CSS for me... no more unused CSS. No more CSS clashes, naming conventions, etc.
It's a great workflow.
edit:
I just wanted to say I use HTMX with the head-support plugin bundled together. @recursivedoubts, hoping for 2.0 soon to come with support built in :)