Back to Blog
3 min readGuide

HTMX: Building Modern Web Apps Without JavaScript Frameworks

Discover HTMX - the hypermedia approach to building modern, interactive web applications without complex JavaScript frameworks

HTMX: Building Modern Web Apps Without JavaScript Frameworks

HTMX lets you build modern, interactive web applications using HTML attributes instead of JavaScript. It's simpler, faster, and surprisingly powerful.

What is HTMX?

HTMX extends HTML with attributes that enable AJAX, CSS transitions, WebSockets, and Server Sent Events directly in markup.

<!-- Simple AJAX request -->
<button hx-get="/api/data" hx-target="#result">
  Load Data
</button>
<div id="result"></div>

<!-- That's it! No JavaScript needed -->

Core Concepts

1. HTTP Attributes

<!-- GET request -->
<button hx-get="/users">Get Users</button>

<!-- POST request -->
<form hx-post="/users" hx-target="#result">
  <input name="name" />
  <button>Submit</button>
</form>

<!-- PUT/PATCH/DELETE -->
<button hx-put="/users/1">Update</button>
<button hx-delete="/users/1">Delete</button>

2. Targeting

<!-- Replace specific element -->
<button hx-get="/data" hx-target="#output">
  Get Data
</button>
<div id="output"></div>

<!-- Replace clicked element -->
<button hx-get="/data" hx-target="this">
  Replace Me
</button>

<!-- Insert at different positions -->
<button hx-get="/data" hx-target="#list" hx-swap="beforeend">
  Append to List
</button>

3. Swap Strategies

<!-- innerHTML (default) -->
<div hx-get="/data" hx-swap="innerHTML"></div>

<!-- outerHTML (replace element) -->
<div hx-get="/data" hx-swap="outerHTML"></div>

<!-- beforebegin, afterbegin, beforeend, afterend -->
<ul id="list">
  <button hx-get="/item" hx-target="#list" hx-swap="beforeend">
    Add Item
  </button>
</ul>

Real-World Example: Todo App

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/htmx.org@1.9.10"></script>
</head>
<body>
  <h1>Todos</h1>

  <!-- Add form -->
  <form hx-post="/todos" hx-target="#todo-list" hx-swap="beforeend">
    <input name="title" placeholder="New todo" required />
    <button>Add</button>
  </form>

  <!-- Todo list -->
  <ul id="todo-list" hx-get="/todos" hx-trigger="load"></ul>
</body>
</html>
# server.py (Flask)
from flask import Flask, request, render_template_string

app = Flask(__name__)
todos = []

@app.route('/todos', methods=['GET'])
def get_todos():
    html = ""
    for i, todo in enumerate(todos):
        html += f"""
        <li>
          <span>{todo}</span>
          <button hx-delete="/todos/{i}" hx-target="closest li" hx-swap="outerHTML">
            Delete
          </button>
        </li>
        """
    return html

@app.route('/todos', methods=['POST'])
def add_todo():
    title = request.form['title']
    todos.append(title)
    i = len(todos) - 1
    return f"""
    <li>
      <span>{title}</span>
      <button hx-delete="/todos/{i}" hx-target="closest li" hx-swap="outerHTML">
        Delete
      </button>
    </li>
    """

@app.route('/todos/<int:id>', methods=['DELETE'])
def delete_todo(id):
    if 0 <= id < len(todos):
        todos.pop(id)
    return ""

Advanced Features

Polling

<!-- Poll every 2 seconds -->
<div hx-get="/status" hx-trigger="every 2s">
  Checking status...
</div>

Loading States

<button hx-get="/data">
  <span class="htmx-indicator">Loading...</span>
  <span>Load Data</span>
</button>

<style>
  .htmx-indicator { display: none; }
  .htmx-request .htmx-indicator { display: inline; }
  .htmx-request > span:not(.htmx-indicator) { display: none; }
</style>

Form Validation

<form hx-post="/submit">
  <input name="email"
         type="email"
         required
         hx-get="/validate/email"
         hx-trigger="blur"
         hx-target="next .error" />
  <span class="error"></span>

  <button>Submit</button>
</form>

Infinite Scroll

<div id="items">
  <!-- Items loaded here -->
</div>

<div hx-get="/items?page=2"
     hx-trigger="revealed"
     hx-swap="afterend">
  Loading more...
</div>

Benefits

  1. Simplicity - HTML attributes instead of JavaScript
  2. Server-side rendering - Simpler architecture
  3. Progressive enhancement - Works without JS
  4. Smaller bundles - ~14KB vs hundreds of KBs
  5. Easy to learn - Familiar HTML patterns

When to Use HTMX

✅ Good fit:

  • Content-heavy applications
  • CRUD applications
  • Dashboards
  • Admin panels
  • Forms and data entry

❌ Not ideal for:

  • Highly interactive UIs (games, drawing apps)
  • Complex client-side state
  • Offline-first applications
  • Real-time collaborative editing

Conclusion

HTMX brings simplicity back to web development. Build modern, interactive applications with HTML and server-side code. No complex build tools, no massive JavaScript bundles, no framework fatigue.

Try HTMX for your next project - you might be surprised how much you can build with so little complexity.

👨‍💻

Jordan Patel

Web Developer & Technology Enthusiast