HTMX & Hypermedia Expert (HTMX 2.0 / HDA Edition)
English | Bahasa Indonesia
<a name="english"></a>
English
Orchestration & Integration
Connects with: brainstorming, zero-to-prod-orchestrator, js-backend-expert, python-programming-expert, go-programming-expert, rust-programming-expert, tailwind-expert, design-system-architect, authentication-identity-expert, database-orm-expert, session-memory-manager.
Description
Expert guide for building Hypermedia-Driven Applications (HDA) using HTMX 2.0+. Covers htmx core attributes (hx-get, hx-post, hx-swap, hx-trigger), server-side rendering patterns, partial page updates, WebSocket/SSE integration, Alpine.js companion patterns, and transitioning from SPA frameworks to lightweight hypermedia architecture.
Trigger Conditions
- Building server-rendered applications with dynamic interactivity without heavy JS frameworks.
- Using HTMX for partial page updates and HTML-over-the-wire patterns.
- Combining HTMX with Alpine.js for client-side micro-interactions.
- Implementing infinite scroll, live search, form validation via htmx.
- Building with any backend (Express, FastAPI, Go, Rails, Django, Laravel, Hono) and wanting SPA-like UX without React/Vue.
- Migrating from a heavy SPA to a simpler hypermedia architecture.
What's New in 2026
HTMX 2.0 — Key Updates
- Stable WebSocket Extension: First-class
hx-ws support for real-time bidirectional communication.
- SSE Extension (Stable): Server-Sent Events via
hx-ext="sse" for live data streams.
- View Transitions API: Native browser view transitions with
hx-swap="transition:true".
- Enhanced History: Better back/forward navigation with
hx-push-url and hx-replace-url.
- Improved Extensions API: Cleaner extension authoring for custom behaviors.
- Response Targets:
hx-target-error, hx-target-4xx, hx-target-5xx for error-specific rendering.
The Hypermedia Renaissance
HTMX has become one of the most starred JavaScript libraries on GitHub, driving a movement back to server-rendered applications with sprinkles of interactivity. Key ecosystem:
- Alpine.js 3.14+: Lightweight reactive framework for client-side state that pairs with HTMX.
- _hyperscript: Event-driven scripting language from the HTMX team.
- Tailwind CSS v4: CSS-first configuration pairs naturally with server-rendered HTML.
- Template Engines: Jinja2, Go templates, Handlebars, EJS, Pug — all work natively.
Core Architecture Patterns
1. HTMX Setup
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTMX App</title>
<!-- HTMX 2.0 -->
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
<!-- Alpine.js for client-side micro-interactions -->
<script defer src="https://unpkg.com/alpinejs@3.14.9/dist/cdn.min.js"></script>
<!-- Tailwind CSS -->
<link href="/styles.css" rel="stylesheet">
</head>
<body>
<!-- Application content -->
</body>
</html>
2. Partial Page Updates (Core Pattern)
<!-- Clicking this button fetches HTML from server and swaps into #results -->
<button
hx-get="/api/search?q=flutter"
hx-target="#results"
hx-swap="innerHTML"
hx-indicator="#loading"
>
Search
</button>
<div id="loading" class="htmx-indicator">Loading...</div>
<div id="results">
<!-- Server returns HTML fragment, not JSON -->
</div>
Server response (returns HTML, not JSON):
<!-- /api/search returns this HTML fragment -->
<div class="result-item">
<h3>Flutter Expert Skill</h3>
<p>Cross-platform mobile development guide.</p>
</div>
<div class="result-item">
<h3>Dart Programming</h3>
<p>Type-safe language for Flutter apps.</p>
</div>
3. Live Search with Debounce
<input
type="search"
name="q"
placeholder="Search products..."
hx-get="/api/products/search"
hx-trigger="input changed delay:300ms, search"
hx-target="#search-results"
hx-swap="innerHTML"
hx-indicator="#search-spinner"
/>
<span id="search-spinner" class="htmx-indicator">⏳</span>
<div id="search-results"></div>
4. Inline Editing
<!-- Display mode -->
<div id="user-name-1" hx-get="/users/1/edit" hx-trigger="dblclick" hx-swap="outerHTML">
<span>John Doe</span>
</div>
<!-- Server returns edit form on double-click -->
<form id="user-name-1" hx-put="/users/1/name" hx-swap="outerHTML">
<input type="text" name="name" value="John Doe" autofocus>
<button type="submit">Save</button>
<button hx-get="/users/1/display" hx-swap="outerHTML" hx-target="#user-name-1">Cancel</button>
</form>
5. Infinite Scroll
<div id="product-list">
<!-- Products rendered server-side -->
<div class="product">Product 1</div>
<div class="product">Product 2</div>
<!-- Sentinel element — triggers load when visible -->
<div
hx-get="/api/products?page=2"
hx-trigger="revealed"
hx-swap="outerHTML"
hx-indicator="#load-more-spinner"
>
<span id="load-more-spinner" class="htmx-indicator">Loading more...</span>
</div>
</div>
6. Form Validation (Server-Side)
<form hx-post="/api/register" hx-target="#form-container" hx-swap="outerHTML">
<div>
<label for="email">Email</label>
<input
type="email"
name="email"
hx-post="/api/validate/email"
hx-trigger="blur changed"
hx-target="next .error"
hx-swap="innerHTML"
/>
<span class="error"></span>
</div>
<div>
<label for="password">Password</label>
<input type="password" name="password" />
</div>
<button type="submit">Register</button>
</form>
7. WebSocket Real-Time Updates
<div hx-ext="ws" ws-connect="/ws/notifications">
<div id="notifications">
<!-- Server pushes HTML fragments via WebSocket -->
</div>
</div>
8. Server-Sent Events (SSE)
<div hx-ext="sse" sse-connect="/events/stream">
<div sse-swap="message" hx-swap="beforeend">
<!-- Each SSE event appends HTML fragment -->
</div>
</div>
9. Alpine.js + HTMX Companion Pattern
<!-- Alpine.js handles client-side state, HTMX handles server communication -->
<div x-data="{ open: false }">
<button @click="open = !open">Toggle Menu</button>
<nav x-show="open" x-transition>
<a hx-get="/dashboard" hx-target="#main" hx-push-url="true">Dashboard</a>
<a hx-get="/settings" hx-target="#main" hx-push-url="true">Settings</a>
</nav>
</div>
<main id="main">
<!-- Page content swapped by HTMX -->
</main>
10. Backend Integration (Multi-Language)
Express.js (Node.js):
app.get('/api/products/search', (req, res) => {
const { q } = req.query;
const products = searchProducts(q);
// Return HTML fragment — NOT JSON
res.send(products.map(p => `
<div class="product-card">
<h3>${p.name}</h3>
<p>$${p.price}</p>
</div>
`).join(''));
});
FastAPI (Python):
from fastapi.responses import HTMLResponse
@app.get("/api/products/search", response_class=HTMLResponse)
async def search_products(q: str):
products = await product_repo.search(q)
html = "".join(
f'<div class="product-card"><h3>{p.name}</h3><p>${p.price}</p></div>'
for p in products
)
return HTMLResponse(content=html)
Go (net/http + html/template):
func searchHandler(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query().Get("q")
products := searchProducts(q)
tmpl := template.Must(template.ParseFiles("templates/product-list.html"))
tmpl.Execute(w, products)
}
When HTMX Is the Right Choice
| Use Case | HTMX | React/Vue SPA |
|---|
| Content sites with dynamic sections | ✅ Ideal | ⚠️ Overkill |
| Admin dashboards | ✅ Ideal | ✅ Also good |
| E-commerce product listings | ✅ Ideal | ✅ Also good |
| Real-time collaborative editors | ❌ Use SPA | ✅ Ideal |
| Complex client-side state (drag-drop, canvas) | ❌ Use SPA | ✅ Ideal |
| SEO-critical pages with interactivity | ✅ Ideal | ⚠️ Requires SSR |
Anti-Patterns to Avoid
- Returning JSON from HTMX endpoints — HTMX expects HTML fragments. The server renders HTML.
- Over-using
hx-swap="outerHTML" — Prefer innerHTML to avoid losing event listeners on the target element.
- Not using
hx-indicator — Users need loading feedback. Always show a spinner.
- Duplicating client-side state — If you need complex client state, use Alpine.js, not a full SPA framework alongside HTMX.
- Ignoring
hx-push-url — Enable URL updates for browser history and shareable links.
<a name="bahasa-indonesia"></a>
Bahasa Indonesia
Integrasi Orkestrasi
Terhubung dengan: brainstorming, zero-to-prod-orchestrator, js-backend-expert, python-programming-expert, go-programming-expert, rust-programming-expert, tailwind-expert, design-system-architect, authentication-identity-expert, database-orm-expert, session-memory-manager.
Deskripsi
Panduan ahli untuk membangun Hypermedia-Driven Applications (HDA) menggunakan HTMX 2.0+. Mencakup atribut inti htmx (hx-get, hx-post, hx-swap, hx-trigger), pola rendering server-side, pembaruan halaman parsial, integrasi WebSocket/SSE, pola pendamping Alpine.js, dan transisi dari framework SPA ke arsitektur hypermedia ringan.
Kondisi Pemicu
- Membangun aplikasi server-rendered dengan interaktivitas dinamis tanpa framework JS berat.
- Menggunakan HTMX untuk pembaruan halaman parsial dan pola HTML-over-the-wire.
- Menggabungkan HTMX dengan Alpine.js untuk interaksi mikro sisi klien.
- Mengimplementasikan infinite scroll, live search, validasi form melalui htmx.
- Membangun dengan backend apapun dan menginginkan UX layaknya SPA tanpa React/Vue.
Pola Arsitektur Inti
1. Konsep Kunci HTMX
HTMX bekerja dengan mengirim request HTTP dan menerima fragmen HTML (bukan JSON). Server bertanggung jawab merender UI. Browser hanya mengganti (swap) bagian halaman yang berubah.
Atribut inti:
hx-get / hx-post / hx-put / hx-delete: Mengirim request HTTP.
hx-target: Element mana yang akan di-update dengan respons.
hx-swap: Cara memasukkan respons (innerHTML, outerHTML, beforeend, afterend).
hx-trigger: Event yang memicu request (click, input changed delay:300ms, revealed).
hx-indicator: Element yang ditampilkan sebagai loading indicator.
hx-push-url: Update URL browser untuk navigasi history.
2. Kapan Menggunakan HTMX
- Website konten dengan interaktivitas dinamis.
- Dashboard admin.
- E-commerce dengan daftar produk, filter, dan pencarian.
- Formulir multi-langkah.
- Aplikasi yang memprioritaskan kesederhanaan dan kecepatan pengembangan.
3. Kapan TIDAK Menggunakan HTMX
- Editor kolaboratif real-time (gunakan SPA + CRDT).
- Aplikasi dengan state klien kompleks (drag-drop, canvas, grafik interaktif).
- Aplikasi offline-first yang butuh service worker berat.