HTMX lets a plain server-rendered page behave like a single-page app by putting AJAX behavior directly in HTML attributes — no build step, no client-side router, no state management library. You add hx-get, hx-post, or hx-trigger to a normal tag, the server responds with an HTML fragment instead of JSON, and htmx swaps it into the page. Carson Gross created it as a generalization of his earlier Intercooler.js library, and it now anchors a broader revival of hypermedia-driven design alongside Turbo and Datastar. The library itself is about 14KB; the application logic stays where it always lived, on the server, in whatever language you already use.
How it works
The core idea is hypermedia as the engine of application state: instead of a client fetching JSON and re-rendering it into DOM with JavaScript, the browser requests HTML and htmx swaps it in directly.
- A button with
hx-post="/todos" sends a request when clicked.
- The server renders the updated list, or just the new row, as an HTML fragment, using the same templates as the full page.
hx-target says where to put the response; hx-swap says how — replace, append, before, or after.
hx-trigger controls when the request fires: click, a keyup with a debounce, page load, or a custom event.
There is no client-side model to keep in sync with the server; the DOM the server just sent you is the source of truth. This is why htmx apps tend to carry far less client-side code than an equivalent SPA — most of what used to be a reducer or a store is just a server-side template.
What changed in 2026
- htmx 2.x dropped legacy browser support and shrank further, with the extension system (SSE, WebSockets, idiomorph swapping) now cleanly separated from core.
- The htmx plus Alpine.js combo became a default "no build step" stack for teams that want small islands of client-only interactivity, like dropdowns and modals, alongside server-driven swaps.
- Backend framework support matured everywhere — Django, Rails, Laravel, and Go's
html/template all have first-class partial-rendering helpers built for htmx specifically.
- Idiomorph became the default swap algorithm in many setups, morphing the DOM instead of replacing it wholesale, which preserves focus and scroll position automatically.
- Adoption spread beyond side projects into regulated industries, where teams valued the smaller audit surface of server-rendered HTML over a large, fast-moving client-side JavaScript bundle.
Core attributes
| Attribute |
Purpose |
hx-get / hx-post |
Issue a GET or POST request from any element |
hx-trigger |
Choose the triggering event: click, keyup, load, revealed |
hx-target |
Choose which element receives the response |
hx-swap |
Choose how the response is inserted: innerHTML, outerHTML, beforeend |
hx-boost |
Progressively enhance normal links and forms into AJAX requests |
hx-indicator |
Show a loading state during the request |
Common mistakes
Returning JSON instead of HTML from htmx endpoints. htmx swaps markup, not data — every endpoint it calls needs to render a fragment, which means duplicating or sharing templates between full pages and partials.
Skipping server-side validation because "it's just a fragment." htmx requests hit real endpoints; they need the same auth, validation, and rate limiting as any other route.
Fighting htmx with heavy client state anyway. If a screen genuinely needs complex client-side state, like a drag-and-drop board or a canvas editor, htmx is the wrong tool — pair it with Alpine for small islands or reach for a real framework.
Forgetting hx-indicator and hx-disabled-elt. Without them, users double-submit forms during slow requests because there is no visual feedback.
FAQ
Does htmx replace React?
For content-heavy, form-driven, CRUD-style apps, often yes. For highly stateful client interfaces, no — see HTMX vs React in 2026.
Can htmx do real-time updates?
Yes, via the SSE and WebSocket extensions, which swap in server-pushed fragments the same way as a normal request.
Does htmx work with any backend language?
Yes — it only cares that the server returns HTML. Django, Rails, Laravel, Spring, Go, and plain PHP all work identically well.
Is htmx good for SEO?
Very good by default, since the initial page load is full server-rendered HTML, not a client-side hydration step.
How big is a typical htmx application's JavaScript bundle?
Usually just the ~14KB htmx core plus a small library like Alpine.js for local interactivity — a fraction of a typical React or Vue production bundle.
Where to go next
For the comparison that matters most before adopting it, read HTMX vs React in 2026 and SolidJS vs React in 2026 for the client-framework alternative. If you are building the backend that serves the fragments, how to build a REST API in Node in 2026 covers the same routing and validation concerns.