React, Vue, Svelte — they all assume you need a JavaScript framework to build interactive web applications. htmx disagrees. It extends HTML with attributes that let you make AJAX requests, swap content, and build reactive UIs — all without writing a single line of JavaScript.
What htmx Gives You for Free
- AJAX from HTML — any element can make HTTP requests via attributes
- Content swapping — replace any part of the page with server HTML
- CSS transitions — smooth animations on content swap
- WebSocket/SSE — real-time updates via HTML attributes
- History API — browser back/forward works automatically
-
14KB gzipped — no build step, no bundler, just a
<script>tag
Quick Start
<script src="https://unpkg.com/htmx.org@2"></script>
That's it. No npm install, no webpack, no node_modules.
AJAX in HTML (The Core Idea)
<!-- Click button → GET /api/users → replace #user-list -->
<button hx-get="/api/users" hx-target="#user-list" hx-swap="innerHTML">
Load Users
</button>
<div id="user-list">
<!-- Server HTML appears here -->
</div>
The server returns HTML, not JSON. No client-side rendering needed.
Form Submission Without Page Reload
<form hx-post="/api/contacts" hx-target="#contact-list" hx-swap="beforeend">
<input name="name" placeholder="Name" />
<input name="email" placeholder="Email" />
<button type="submit">Add Contact</button>
</form>
<div id="contact-list">
<!-- New contacts appear here without page reload -->
</div>
Server returns an HTML fragment like <div class="contact">John (john@test.com)</div> — htmx appends it.
Active Search (Live Filtering)
<input type="search"
name="q"
hx-get="/api/search"
hx-trigger="keyup changed delay:300ms"
hx-target="#results">
<div id="results">
<!-- Search results update as you type -->
</div>
Infinite Scroll
<div id="feed">
<!-- Existing posts -->
<div hx-get="/api/posts?page=2"
hx-trigger="revealed"
hx-swap="afterend">
Loading more...
</div>
</div>
When the element scrolls into view (revealed), htmx loads the next page.
Delete With Confirmation
<button hx-delete="/api/users/42"
hx-target="closest tr"
hx-swap="outerHTML"
hx-confirm="Are you sure?">
Delete
</button>
Server-Side Framework Compatibility
htmx works with ANY backend that returns HTML:
- Python: Django, Flask, FastAPI
- Ruby: Rails, Sinatra
- Go: Gin, Echo, Fiber
- Node.js: Express, Fastify
- PHP: Laravel, Symfony
- Java: Spring Boot
- Rust: Actix, Axum
htmx + Django Example
# views.py
def search_contacts(request):
q = request.GET.get('q', '')
contacts = Contact.objects.filter(name__icontains=q)[:20]
return render(request, 'partials/contact_list.html', {'contacts': contacts})
<!-- partials/contact_list.html -->
{% for contact in contacts %}
<tr>
<td>{{ contact.name }}</td>
<td>{{ contact.email }}</td>
<td>
<button hx-delete="/contacts/{{ contact.id }}/" hx-target="closest tr" hx-swap="outerHTML">
Delete
</button>
</td>
</tr>
{% endfor %}
htmx vs React/Vue/Svelte
| Aspect | htmx | React |
|---|---|---|
| Bundle size | 14KB | 85KB+ |
| Build step | None | Required |
| State management | Server | Client (Redux, Zustand) |
| SEO | Built-in (server HTML) | Needs SSR |
| Learning curve | Know HTML → ready | JSX, hooks, state, effects |
| Backend agnostic | Yes (any language) | Needs JSON API |
| Complexity | O(features) | O(features²) |
Who's Using htmx
- Trending #1 on GitHub multiple times
- Used by companies frustrated with SPA complexity
- Growing fastest in Django, Go, and Rails communities
The Verdict
htmx is for developers who realize that most web apps don't need a JavaScript framework. If your server can render HTML, htmx makes it interactive with zero client-side complexity. It's not a step backward — it's a shortcut to simplicity.
Need help building production web scrapers or data pipelines? I build custom solutions. Reach out: spinov001@gmail.com
Check out my awesome-web-scraping collection — 400+ tools for extracting web data.
Top comments (0)