How to Use htmx Without a JavaScript Framework: The Complete Guide

htmx is a dependency-free library that enables AJAX, CSS transitions, and real-time updates directly in HTML via hx-* attributes, eliminating the need for React, Vue, or Angular.

You can build dynamic web applications using htmx without installing a JavaScript framework or configuring a complex build pipeline. The bigskysoftware/htmx repository provides a single-file library that attaches behavior to HTML elements through declarative attributes, keeping your frontend lightweight while delivering interactive features typically associated with heavyweight SPA frameworks.

How htmx Eliminates Framework Dependencies

htmx operates as a self-contained script that exposes a global htmx object. In src/htmx.js lines 4-31, the library initializes its public API including methods like onLoad, process, ajax, find, and swap. This global object serves as the single entry point for all functionality, removing the need for component hierarchies or virtual DOM management systems.

Attribute-Driven Event Processing

The library scans the DOM for elements bearing hx-* attributes immediately after page load. The core scanning mechanism resides in processNode, referenced at line 302 of src/htmx.js. When htmx detects attributes like hx-post or hx-get, it attaches native DOM event listeners to handle user interactions without requiring imperative JavaScript handlers.

Request Creation and Configuration

When a user triggers an action, htmx constructs XMLHttpRequest or fetch calls using ajaxHelper (exposed at line 18). This helper reads configuration values from htmx.config, which you can override through meta tags in your HTML head. The request logic respects attributes such as hx-params for data serialization and automatically handles CSRF tokens and headers.

Response Handling Without Virtual DOM

After receiving server responses, htmx processes HTML through makeFragment at line 603, parsing content into a DocumentFragment. The swap engine then executes the appropriate insertion strategy—swapOuterHTML, swapInnerHTML, or morphing operations—based on the hx-swap attribute value. This dispatcher lives at line 444, replacing targeted DOM elements directly without diffing algorithms or component reconciliation cycles.

Extension Architecture for Advanced Features

While the core remains minimal, htmx supports third-party enhancements through its extension API defined by defineExtension and removeExtension. The getExtensions function manages these plugins, invoking them during swap operations via isInlineSwap (lines 444-456). This design allows you to add WebSocket support, Server-Sent Events, or custom behaviors by loading additional scripts from dist/ext/ rather than importing framework-specific modules.

Implementation Example

To use htmx without any build tools or frameworks, include the minified distribution and add declarative attributes to your markup:

<!-- Load htmx from CDN (no npm install required) -->
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.10/dist/htmx.min.js"
        integrity="sha384-H5SrcfygHmAuTDZphMHqBJLc3FhssKjG7w/CeCpFReSfwBWDTKpkzPP8c+cLsK+V"
        crossorigin="anonymous"></script>

<!-- AJAX button that replaces itself with server response -->
<button hx-post="/clicked" hx-swap="outerHTML">
  Click Me
</button>

<!-- Load-more pattern appending content -->
<div id="list">
  <div>Item 1</div>
  <div>Item 2</div>
</div>
<button hx-get="/more-items" hx-target="#list" hx-swap="afterend">
  Load More
</button>

<!-- Form with validation targetting result div -->
<form hx-post="/submit" hx-target="#result" hx-swap="innerHTML" hx-validate="true">
  <input name="name" required>
  <button type="submit">Send</button>
</form>
<div id="result"></div>

Each attribute drives specific behavior: hx-post and hx-get define endpoints, hx-target selects insertion points, and hx-swap determines positioning strategies like outerHTML, innerHTML, or afterend.

Key Source Files

  • src/htmx.js: Contains the core implementation including the global API definition, attribute parsing logic, ajaxHelper, and swap mechanisms.
  • dist/htmx.min.js: The minified production build referenced directly in HTML pages via CDN or local hosting.
  • dist/ext/: Directory housing optional extensions for WebSocket and Server-Sent Event functionality that plug into the core without framework dependencies.
  • test/attributes/: Comprehensive test suite demonstrating attribute behaviors and edge cases for reference implementations.

Summary

  • htmx requires no build step or package manager—load dist/htmx.min.js via CDN to begin development immediately.
  • All interaction logic resides in HTML attributes (hx-post, hx-swap, etc.) processed by the processNode function in src/htmx.js.
  • The global htmx object provides imperative methods like ajax and swap while maintaining zero external dependencies.
  • Server responses integrate directly through the makeFragment parser and swap engine without virtual DOM overhead.
  • Extensions enable advanced features through defineExtension without requiring migration to a full framework.

Frequently Asked Questions

Can I use htmx with plain HTML files without Node.js or npm?

Yes. htmx functions entirely within the browser. Download dist/htmx.min.js from the bigskysoftware/htmx releases page or link to the CDN, then reference it in your HTML with a standard <script> tag. No build tools, bundlers, or Node.js installation are necessary for production deployment.

How does htmx handle browser events without a framework's event system?

htmx attaches native DOM event listeners during initialization via processNode in src/htmx.js line 302. When elements contain attributes like hx-post or hx-get, the library binds to standard events (click, submit, change) and manages cleanup automatically when elements are removed from the DOM, eliminating memory leaks without framework abstractions.

What is the performance impact of using htmx compared to React or Vue?

htmx typically delivers smaller bundle sizes and faster initial page loads because it avoids virtual DOM diffing and component hydration. The library performs direct DOM manipulation through swapOuterHTML and related functions at line 444, updating only the specific elements targeted by server responses rather than re-rendering entire component trees.

How do I add WebSocket or Server-Sent Event support without a framework?

Load extensions from the dist/ext/ directory after including the core htmx script. These extensions use the defineExtension API to register themselves with the internal getExtensions system, enabling real-time communication protocols while maintaining htmx's attribute-driven, framework-free architecture.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →