DEV Community

Alex Spinov
Alex Spinov

Posted on

htmx Has a Free API That Replaces React for 90% of Web Apps

htmx lets you build modern, interactive web apps using HTML attributes instead of JavaScript frameworks. Its API surface is tiny but incredibly powerful.

Core: AJAX via HTML Attributes

<!-- GET request on click -->
<button hx-get="/api/data" hx-target="#results" hx-swap="innerHTML">
  Load Data
</button>
<div id="results"></div>

<!-- POST form without page reload -->
<form hx-post="/api/items" hx-target="#item-list" hx-swap="afterbegin">
  <input name="title" placeholder="New item">
  <button type="submit">Add</button>
</form>

<!-- DELETE with confirmation -->
<button hx-delete="/api/items/42" hx-confirm="Are you sure?" hx-target="closest tr" hx-swap="outerHTML">
  Delete
</button>
Enter fullscreen mode Exit fullscreen mode

Triggers: Any Event

<!-- Search on keyup with debounce -->
<input type="search" name="q"
  hx-get="/api/search"
  hx-trigger="keyup changed delay:300ms"
  hx-target="#results"
  hx-indicator="#spinner">

<!-- Load on scroll (infinite scroll) -->
<div hx-get="/api/items?page=2"
  hx-trigger="revealed"
  hx-swap="afterend">
  Loading...
</div>

<!-- Poll every 5 seconds -->
<div hx-get="/api/status"
  hx-trigger="every 5s"
  hx-swap="innerHTML">
</div>

<!-- Intersection observer -->
<img hx-get="/api/image/lazy" hx-trigger="intersect once" hx-swap="outerHTML">
Enter fullscreen mode Exit fullscreen mode

Swap Strategies

<!-- Replace inner content -->
<div hx-get="/data" hx-swap="innerHTML">old content</div>

<!-- Replace entire element -->
<div hx-get="/data" hx-swap="outerHTML">replaces this div</div>

<!-- Append/Prepend -->
<ul hx-get="/items" hx-swap="afterbegin">new items go first</ul>

<!-- Out-of-band swaps (update multiple elements) -->
<!-- Server response: -->
<div id="notification" hx-swap-oob="true">New notification!</div>
<tr>...main response row...</tr>
Enter fullscreen mode Exit fullscreen mode

CSS Transitions

<style>
  .htmx-swapping { opacity: 0; transition: opacity 0.5s; }
  .htmx-settling { opacity: 1; transition: opacity 0.5s; }
  .htmx-added { opacity: 0; }
</style>

<div hx-get="/content" hx-swap="innerHTML swap:500ms settle:500ms">
  Content fades out, new content fades in
</div>
Enter fullscreen mode Exit fullscreen mode

Extensions

<!-- Server-Sent Events -->
<div hx-ext="sse" sse-connect="/api/events" sse-swap="message">
  Live updates appear here
</div>

<!-- WebSocket -->
<div hx-ext="ws" ws-connect="/chat">
  <form ws-send>
    <input name="message">
    <button>Send</button>
  </form>
  <div id="messages"></div>
</div>

<!-- JSON encoding -->
<form hx-ext="json-enc" hx-post="/api/data">
  Sends JSON instead of form-encoded
</form>
Enter fullscreen mode Exit fullscreen mode

htmx Events API

document.body.addEventListener("htmx:afterSwap", (e) => {
  console.log("Swapped:", e.detail.target);
});

document.body.addEventListener("htmx:beforeRequest", (e) => {
  e.detail.headers["X-Custom-Header"] = "value";
});

document.body.addEventListener("htmx:responseError", (e) => {
  showToast("Request failed: " + e.detail.xhr.status);
});
Enter fullscreen mode Exit fullscreen mode

Build server-rendered data apps? My Apify tools deliver data for your htmx-powered server.

Custom solution? Email spinov001@gmail.com

Top comments (0)