HTMX and the Hypermedia-Driven Application Approach

Photo by Florian Olivo on Unsplash
HTMX is a small, dependency-free JavaScript library (about 14 KB minified and gzipped) that lets any HTML element issue AJAX requests using attributes like hx-get and hx-post. The server responds with HTML fragments that HTMX swaps into the page, so you build interactive apps with far less client-side JavaScript than a typical SPA.
hx-get (and hx-post/put/patch/delete) sets the HTTP verb and URL for the request. hx-trigger picks the event that fires it, hx-target is a CSS selector for where the response goes, and hx-swap controls how it is inserted, for example innerHTML to replace contents or outerHTML to replace the whole element.
A React SPA keeps application state in the browser and exchanges JSON with the server, rendering the UI on the client. A hypermedia-driven app keeps state on the server and sends ready-to-display HTML, following HATEOAS. That means less client code and simpler data flow, at the cost of a network round trip per interaction.
HTMX struggles when a feature needs a UI update on every interaction without a round trip, such as real-time drag or spreadsheet-style interdependent cells, or when the app must work fully offline. It also does not integrate framework-specific component libraries like React-only design systems. For those, a client-side framework fits better.
htmx 2.0.0 was released on 17 June 2024 without rewriting the core API, so most 1.x code keeps working. It drops Internet Explorer support, moves official extensions to their own repo, and tightens defaults: instant scrolling, DELETE sends query parameters, and selfRequestsOnly defaults to true for same-origin safety.

Photo by Florian Olivo on Unsplash
Key Takeaway
HTMX is a small dependency-free JavaScript library that lets any HTML element issue AJAX requests through attributes like hx-get, hx-post, hx-target, and hx-swap, then swaps the returned HTML fragment into the page. It revives the hypermedia model, keeping state on the server and shrinking client-side code compared with an SPA talking to a JSON API.
For fifteen years the default answer to make this page interactive has been the same: ship a JavaScript framework, build a client-side application, and have it talk to the server over a JSON API. HTMX proposes something quieter. It asks whether most of that machinery is necessary when the browser already knows how to fetch a URL and render HTML.
HTMX is a small, dependency-free JavaScript library, about fourteen kilobytes minified and gzipped, that extends HTML so any element can do what only anchors and forms could before. Instead of writing fetch calls and reconciling a virtual DOM, you add a few attributes to your markup and let the library handle the request, the response, and the swap. I have used it to replace whole React screens with a handful of server templates, and the result was less code that broke in fewer ways.
The mental model is a generalisation of the plain hyperlink. A normal anchor issues a GET request when you click it and replaces the entire window with the response. HTMX removes each of those restrictions. Any element can issue a request, using any HTTP verb, triggered by any event, targeting any part of the page, and replacing only that part. The official docs describe it as accessing modern browser features directly from HTML rather than using JavaScript.
Four attributes carry most of the weight. hx-get, hx-post, hx-put, hx-patch, and hx-delete name the verb and the URL. hx-trigger picks the event that fires the request, be it a click, an input, a keyboard event, or a custom one, with modifiers like a debounce delay. hx-target is a CSS selector that says where the response should land. hx-swap decides how it lands: innerHTML replaces the contents, outerHTML replaces the whole element, and there are positional options like beforebegin and afterend.
<!-- Live search: fire a GET as the user types, swap the matching
rows into #results. The server returns HTML, not JSON. -->
<input type="search" name="q"
hx-get="/search"
hx-trigger="input changed delay:300ms, search"
hx-target="#results"
hx-swap="innerHTML" />
<table>
<tbody id="results">
<!-- server responds with just these <tr> rows as an HTML fragment -->
</tbody>
</table>
<!-- Delete a contact: issue DELETE, then remove the whole row -->
<button hx-delete="/contacts/42"
hx-target="closest tr"
hx-swap="outerHTML swap:200ms">
Delete
</button>The example above wires a search box and a delete button with no bespoke JavaScript at all. As the user types, HTMX debounces the input, fires a GET to the search endpoint, and drops the returned rows into the results table. The delete button issues a DELETE and removes its own table row. Crucially, the server sends back HTML fragments, not JSON, so there is no client-side template doing the rendering.
That last point is the whole philosophy, not an implementation detail. A single-page application typically abandons REST: the server sends JSON, and the client holds the application state and decides how to render it. A hypermedia-driven application keeps state on the server and sends HTML that already encodes what the user can do next, because the links and forms are the available actions. This is the original web idea Roy Fielding named HATEOAS, Hypertext As The Engine Of Application State.
The htmx essays call this pattern a Hypermedia-Driven Application, and define it by two constraints: it uses declarative, HTML-embedded attributes rather than imperative scripting for interactivity, and it talks to the server in hypermedia, meaning HTML, rather than a non-hypermedia format like JSON. Scripting can still enhance the page, but it sits on top of an HTML foundation instead of replacing it.
A useful gut check: if you can describe a feature as when this event happens, ask the server for some HTML and put it here, it is probably a good HTMX feature. Reach for custom scripting only for genuinely client-only behaviour like animations, drag-and-drop, or optimistic UI.
HTMX is not a universal replacement for front-end frameworks, and its own documentation is refreshingly honest about that. The essay on when to use hypermedia lists the sweet spots clearly, and they map onto a large share of the software most teams actually build: CRUD screens, content sites, and dashboards rather than design-canvas applications.
The same essay is equally clear about where hypermedia struggles, and ignoring that list is how teams end up fighting the tool. Anything that needs a network round trip per interaction will feel wrong, because inserting an HTTP request between a mouse move and a UI update does not work well. Offline-first apps are out, since the approach assumes a reachable server. Interfaces with many interdependent cells, where a spreadsheet is the canonical example, do not decompose into clean fragments. And you cannot drop in a component library built for a specific framework, like a React-only design system.
Do not treat HTMX as a way to avoid learning the server. The complexity does not vanish; it moves. Your endpoints now return HTML fragments, which means clear template composition, disciplined URL design, and careful handling of partial-versus-full-page responses matter more than ever. Teams that skip that end up with a tangle of one-off fragment routes.
htmx 2.0.0 shipped on 17 June 2024, and notably it did not rewrite the core API, so code written for 1.x mostly keeps working. The headline changes are housekeeping: support for Internet Explorer is dropped, and all official extensions moved out of the core repository into their own repo so they can version independently. A few defaults were tightened, as smooth scrolling became instant, DELETE requests now send query parameters, and selfRequestsOnly defaults to true so requests stay same-origin unless you opt out. The old hx-on attribute gained a cleaner hx-on colon syntax. To avoid force-upgrading anyone on an unversioned CDN link, the team kept 1.x as the npm latest tag for a transition period.
| Concern | HTMX (hypermedia) | SPA + JSON API |
|---|---|---|
| Where UI is rendered | On the server, sent as HTML | In the browser, from JSON |
| Where state lives | Mostly on the server | Split across client and server |
| Payload format | HTML fragments | JSON data |
| Client-side JavaScript | Minimal, declarative attributes | A full framework and build step |
| Best fit | CRUD, content, dashboards | Highly interactive, offline, real-time |
My rule of thumb after shipping both: reach for HTMX first for anything server-driven, and only add a heavier front end where a feature genuinely needs client-side state you cannot round-trip. If you want the full argument, the authors of htmx wrote a free book, Hypermedia Systems, that lays out the approach end to end. It is the clearest case I have read for taking the browser own model seriously again.