HTMX makes a genuinely contrarian bet in a JavaScript-framework-dominated landscape: what if you didn't need a JavaScript framework at all, and instead extended HTML itself to make any element capable of triggering an AJAX request and swapping in server-rendered HTML in response?
HTMX is a small JavaScript library that extends HTML with attributes enabling AJAX requests, WebSockets, and server-sent events directly from any element, without writing JavaScript or building a client-side application. Interactions are declared as HTML attributes (hx-get, hx-post, hx-target), and the server responds with HTML fragments that HTMX swaps into the page — no client-side state management or JSON API layer required.
Why HTMX Matters (and When to Skip It)
For applications that don't need complex client-side state (most CRUD-heavy business applications, admin panels, content-driven sites with interactive pieces), HTMX lets you build interactive UI using your existing server-rendered templates and backend, without introducing a separate frontend framework, build pipeline, or client-server API contract to maintain.
Skip HTMX for applications with genuinely complex client-side state and interaction patterns — a rich, highly stateful UI (a design tool, a real-time collaborative editor) is better served by a proper client-side framework's state management than HTMX's server-round-trip-per-interaction model.
Getting Started with HTMX
Including HTMX via a script tag (no build step required):
<script src="https://unpkg.com/htmx.org@2.0.0"></script>
A basic interaction — clicking a button fetches and swaps in server-rendered HTML:
<button hx-get="/api/latest-comments" hx-target="#comments" hx-swap="innerHTML">
Load Comments
</button>
<div id="comments"></div>
A form that submits via AJAX and swaps the result in, without a full page reload:
<form hx-post="/api/comments" hx-target="#comments" hx-swap="beforeend">
<input name="text" />
<button type="submit">Post</button>
</form>
The server just returns an HTML fragment for the new comment, not JSON:
<!-- server response -->
<div class="comment">New comment text</div>
Core HTMX Concepts Every Developer Should Know
The server returns HTML, not JSON. This is the fundamental difference from a typical SPA architecture — your backend renders fragments directly (using whatever templating you already use), and HTMX swaps them into the DOM, eliminating the need for a separate JSON API layer and client-side rendering logic entirely for HTMX-driven interactions.
hx-target and hx-swap control where and how the response gets inserted. Target specifies which element receives the response; swap specifies the insertion strategy (innerHTML, outerHTML, beforeend, afterbegin, and others) — together they give fine control over the DOM update without writing any JavaScript.
HTMX composes with server-side frameworks in any language, since the only contract is "respond with HTML" — it works equally well with Express, Django, Rails, Laravel, or any backend capable of rendering HTML fragments, making it a genuinely backend-agnostic approach to adding interactivity.
Triggers can be based on more than clicks — hx-trigger supports events like keyup, revealed (element entering viewport), polling intervals, and more, enabling patterns like live search or infinite scroll declaratively:
<input hx-get="/search" hx-trigger="keyup changed delay:300ms" hx-target="#results" />
Common HTMX Mistakes and How to Fix Them
Mistake 1: reaching for HTMX on an application that genuinely needs complex client-side state management. Every interaction requiring a server round-trip doesn't fit well for highly interactive, stateful UI. Fix: recognize when the application's actual interaction complexity exceeds what a server-round-trip model comfortably supports, and use a client-side framework instead for that case.
Mistake 2: not handling loading and error states for HTMX-driven requests, leaving users without feedback during a slow or failed request. Fix: use HTMX's built-in indicator classes and error event hooks to provide loading and error feedback, the same UX consideration any async interaction needs.
Mistake 3: building an inconsistent mix of full JSON API endpoints and HTML-fragment endpoints without a clear convention, confusing the backend's responsibilities. Fix: be deliberate about which endpoints serve HTMX (returning HTML) versus which serve other clients (returning JSON) if both exist in the same application.
When Should You Use HTMX Instead of a JavaScript Framework?
Use HTMX when your application is primarily server-rendered with pockets of interactivity — most business applications, content sites, and admin tools fit this well, and HTMX lets you add that interactivity without adopting a full frontend framework and build pipeline. Use a JavaScript framework (React, Vue, Svelte) when your application genuinely needs complex client-side state, offline capability, or interaction patterns that don't map well onto a server-round-trip-per-interaction model.
HTMX in Production
Provide clear loading and error states for every HTMX-driven interaction, since network round trips are inherent to the model and users need feedback during them. Also keep your server-side fragment-rendering logic organized and testable the same way you would any other server-rendered view, since HTMX shifts UI logic back toward the server rather than eliminating the need for it to be well-structured.
If your application is mostly server-rendered CRUD with a handful of places that currently require a full page reload for a small interaction, that's exactly the case HTMX is built to improve without a larger framework migration.