Introduction to HTMX
Building Modern Web Applications with Minimal JavaScript
HTMX is a lightweight JavaScript library that enables you to access modern browser features directly from HTML attributes, rather than writing complex JavaScript code. It lets you build dynamic, interactive web applications with the simplicity of hypertext, making it an excellent choice for developers who want to maintain clean separation between markup and interactivity without sacrificing user experience.
What is HTMX?
HTMX stands for "HTML + X," where the X represents the extended capabilities it adds to standard HTML. At its core, HTMX allows you to make HTTP requests directly from HTML elements using custom attributes like hx-get, hx-post, and hx-trigger. Instead of writing JavaScript event handlers and fetch calls, you declare what should happen directly in your HTML.
This approach aligns with the principles of HATEOAS (Hypermedia As The Engine Of Application State), a REST architectural constraint where the server provides hypermedia controls that guide clients through application workflows. HTMX brings this concept back to the web, proving that you don't need a complex single-page application framework to build responsive, interactive user interfaces.
Why Use HTMX?
Reduced Complexity: Write less JavaScript. Your backend renders HTML fragments, and HTMX handles the client-side wiring.
Familiar Developer Experience: If you know HTML, CSS, and a backend language, you can build modern UIs without learning a heavy JavaScript framework.
Progressive Enhancement: HTMX works alongside traditional HTML forms. Add interactivity without breaking core functionality.
Server-Centric Architecture: Your backend remains the source of truth. Logic stays where it belongs, and the server controls what gets rendered.
Smaller Bundle Sizes: HTMX is just 14KB (minified and gzipped), compared to megabytes for modern SPA frameworks.
Getting Started
Including HTMX in your project is simple. Add a single script tag to your HTML head:
<script src="https://unpkg.com/htmx.org@2.0.8"></script>
That's it. You now have access to all HTMX functionality. Let's explore practical examples.
Practical Code Examples
1. Live Search with Debouncing
Create a responsive search that queries your backend as the user types, with built-in debouncing to reduce unnecessary requests:
<input type="text"
name="q"
hx-get="/api/search"
hx-trigger="keyup changed delay:500ms"
hx-target="#results"
placeholder="Search users...">
<div id="results"></div>
The delay:500ms modifier waits 500 milliseconds after the user stops typing before making the request. Your backend responds with HTML fragments that replace the contents of the #results div.
2. Form Submission with Validation
Build forms that provide instant feedback without page reloads:
<form hx-post="/api/users" hx-target="#response">
<input type="email" name="email" required>
<input type="text" name="username" required>
<button type="submit">Create User</button>
</form>
<div id="response"></div>
When the form is submitted, HTMX intercepts it and sends the data via AJAX. Your backend validates the input and returns either the form again (with error messages) or a success message.
3. Inline Editing
Enable users to edit content directly without navigating away:
<div id="user-name" hx-target="this" hx-swap="outerHTML swap:1s">
<span>John Doe</span>
<button hx-get="/api/users/1/edit">Edit</button>
</div>
When the Edit button is clicked, HTMX fetches a form from the server. The user makes changes and submits, which triggers a PUT request:
<div id="user-name">
<form hx-put="/api/users/1" hx-target="this" hx-swap="outerHTML">
<input type="text" name="name" value="John Doe">
<button type="submit">Save</button>
<button type="button" hx-get="/api/users/1">Cancel</button>
</form>
</div>
4. Cascading Dropdowns
Build dependent select fields where the second dropdown updates based on the first:
<form>
<select name="country" hx-get="/api/regions" hx-target="#regions">
<option value="">Select Country</option>
<option value="uk">United Kingdom</option>
<option value="us">United States</option>
</select>
<select id="regions" name="region">
<option>Choose a country first</option>
</select>
</form>
When the user selects a country, HTMX sends that value to /api/regions, and the server returns just the option elements for the regions dropdown.
5. Pagination with Load More
Implement infinite scroll pagination without complex JavaScript:
<div id="items">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<!-- more items -->
</div>
<button hx-get="/api/items?page=2"
hx-target="#items"
hx-swap="beforeend"
hx-indicator=".spinner">
Load More
<span class="spinner htmx-request" style="display:none">Loading...</span>
</button>
The hx-swap="beforeend" attribute appends new items to the bottom of the list instead of replacing it. The hx-indicator shows a loading spinner during the request.
6. Out-of-Band Swaps (Update Multiple Elements)
Sometimes you need to update multiple parts of your page from a single request. HTMX supports this with out-of-band swaps:
<button hx-get="/api/action" hx-select-oob="#notification:#toast">
Do Something
</button>
<!-- This will be updated even though it's not the target -->
<div id="toast" hx-swap="innerHTML"></div>
Return multiple elements from the server:
<!-- Primary response -->
<div>Main content updated</div>
<!-- Out-of-band swap -->
<div id="toast" hx-swap="outerHTML">Notification message</div>
7. Real-Time Polling
Update content at regular intervals without user interaction:
<div hx-get="/api/status" hx-trigger="every 3s" hx-swap="innerHTML">
Status will update every 3 seconds...
</div>
8. DELETE with Confirmation
<button hx-delete="/api/users/1"
hx-confirm="Are you sure you want to delete this user?"
hx-target="closest tr"
hx-swap="swap:0.2s then remove">
Delete
</button>
The hx-confirm attribute shows a browser confirmation dialog. If the user confirms, the request proceeds. The then remove swap strategy deletes the element after the swap completes.
9. Swap Strategies
HTMX offers several ways to swap content into the DOM:
<!-- Replace entire element -->
<div hx-get="/content" hx-swap="outerHTML">Original</div>
<!-- Replace inner HTML -->
<div hx-get="/content" hx-swap="innerHTML">Original</div>
<!-- Insert before -->
<div hx-get="/content" hx-swap="beforebegin">Original</div>
<!-- Insert after -->
<div hx-get="/content" hx-swap="afterend">Original</div>
<!-- With transition and timing -->
<div hx-get="/content" hx-swap="innerHTML swap:1s transition:true">Original</div>
10. Conditional Requests (Only Update if Data Changed)
<div hx-get="/api/data"
hx-trigger="every 2s"
hx-select="this"
hx-swap="innerHTML"
hx-headers='{"If-None-Match": "value"}'>
Data here
</div>
Return 304 Not Modified from your server when data hasn't changed. HTMX will skip the swap, reducing unnecessary DOM updates.
Building Effective Backends for HTMX
The key to using HTMX effectively is designing your backend to return HTML fragments rather than JSON. Here are some best practices:
Return Only What Changed: When responding to an HTMX request, return just the HTML fragment that needs to be swapped, not the entire page. This keeps responses small and fast.
Use Semantic HTML: HTMX works best with well-structured, semantic HTML. This makes your markup meaningful and easier to work with.
Handle Validation Gracefully: On validation failure, return the form again with error messages displayed. HTMX will swap it back into place, allowing the user to correct their input.
Leverage HTTP Status Codes: Use appropriate status codes (200 for success, 422 for validation errors, etc.). HTMX can respond differently based on status codes.
Server-Side Rendering: Your backend should handle all rendering. HTMX is a connector, not a template engine. Let your server do the heavy lifting.
HTMX with Modern Tooling
HTMX pairs beautifully with modern development practices. If you're using TypeScript/Node.js and frameworks like Express, Fastify, or Nest.js, you can build interactive applications without touching a single line of client-side JavaScript (aside from HTMX itself).
For styling, combine HTMX with Tailwind CSS or similar utility-first frameworks. Your HTML becomes declarative and self-documenting, making it easy for others to understand what's happening.
For your projects like Datingular, HTMX enables you to build feature-rich interfaces while keeping your codebase manageable. The API endpoints you've already built can now serve HTML fragments instead of (or in addition to) JSON responses.
The Bottom Line
HTMX challenges the modern trend of offloading everything to JavaScript. It proves that with the right tools and architectural choices, you can build sophisticated, responsive web applications with HTML at the center. You keep your backend logic where it belongs, reduce your JavaScript bundle size, and write less code overall.
Whether you're building a simple dashboard, a complex admin panel, or a full-featured platform like a dating app, HTMX gives you a pragmatic alternative to the heavyweight SPA frameworks. Give it a try on your next project—you might be surprised how much you enjoy building web applications the hypermedia way.
