⏱️ Lectura: 10 min

htmx has just confirmed the release of version 4.0.0 of its library: the project’s first major rewrite since it began, with the internal engine migrated from XMLHttpRequest to the fetch() API and attribute inheritance, previously implicit, now declared by hand with the :inherited suffix.

📑 En este artículo
  1. TL;DR
  2. What Happened with htmx 4.0.0
  3. Context and History
  4. Technical Details and Performance
    1. Explicit Attribute Inheritance
    2. Standardized Events
    3. History Without localStorage by Default
  5. How to Try It Today
  6. Impact and Analysis
  7. What’s Next
  8. Frequently Asked Questions
    1. Does htmx 4.0.0 replace htmx 2 immediately?
    2. Do I have to rewrite my hx-get, hx-post, or hx-target attributes?
    3. Why did they remove localStorage history caching?
    4. What happens to my htmx:beforeRequest or htmx:afterSwap listeners?
    5. Does htmx 4.0.0 still work with Alpine.js or hyperscript?
    6. How do I know which version of htmx I have loaded?
  9. References

The team, made up of the original creator along with Christian, Michael, and Alex, took eight months to finish it (with a game jam in between) and decided not to mark 4.0.0 as latest on npm, so as not to force an update on sites that load htmx from a CDN without pinning a version.

TL;DR

  • htmx 4.0.0 was announced on August 28, 2026 after 8 months of development (and a game jam along the way).
  • The internal engine moves from XMLHttpRequest to the fetch() API, transparently for most users.
  • Attribute inheritance is now explicit: you have to add the :inherited suffix (it used to be implicit).
  • Events are renamed to the htmx:phase:action pattern; for example htmx:beforeRequest becomes htmx:before:request.
  • History no longer uses localStorage by default: htmx requests the page again when navigating back.
  • On npm, 2.x remains latest; 4.0 stays under the next tag until early 2027.
  • The htmx:xhr:* and htmx:validation:* events are removed with the move to fetch() and native browser validation.
  • The team released a command-line tool to detect attributes missing :inherited and events with old names.

What Happened with htmx 4.0.0

The announcement was published on August 28, 2026 on the project’s official blog and marks the close of a development cycle that began when its creator started working on fixi, a minimalist library that forced him to get deeply familiar with fetch() and modern asynchronous JavaScript programming. htmx, since its origins as intercooler.js, had used XMLHttpRequest for backward compatibility reasons.

A contributor named Christian, interested in HTML streaming, ended up convincing the team to move the internal engine to fetch(). With Michael and Alex joining the project, development moved fast: they started from a port of fixi combined with htmx’s historical test suite, and as they progressed they rediscovered why htmx 2 had made many of its original design decisions, so they ended up bringing the new implementation closer to the previous one in most cases.

htmx logo over a code background representing the htmx 4.0.0 release
htmx 4.0.0 changes its internal engine from XMLHttpRequest to fetch(). Foto de BoliviaInteligente en Unsplash

Context and History

htmx 4.0.0 arrives with an explicit promise: keeping the applications that use it running as “100-year web services.” It’s the same minimalist philosophy that drove htmx 2 since its days as intercooler.js, but now applied to concrete decisions about what to break and what to preserve.

That’s why the team chose an unusual coexistence strategy: on npm, the latest tag will keep pointing to the 2.x line, while 4.0 is distributed under the next tag until early 2027. This prevents the thousands of sites that load htmx from a CDN without pinning a numeric version from suddenly updating to a version with behavioral changes. The official htmx site, however, already documents 4.0 as the reference version.

Technical Details and Performance

Explicit Attribute Inheritance

In htmx 2, many attributes were inherited implicitly: if you set hx-confirm on a parent div, the behavior also applied to child buttons. That inheritance, inspired by the CSS cascade model, was powerful but hard to trace in large applications.

htmx 4.0.0 reverses that default rule: no attribute is inherited unless you explicitly declare it by adding the :inherited suffix to the attribute name. According to the announcement itself, it’s the change that demands the most migration work, which is why the team published a command-line tool that scans your code and flags where :inherited needs to be added.

<!-- htmx 2: the attribute is inherited implicitly -->
<div hx-confirm="Are you sure?">
  <button hx-delete="/item/1">Delete</button>
</div>

<!-- htmx 4: inheritance must be declared explicitly -->
<div hx-confirm:inherited="Are you sure?">
  <button hx-delete="/item/1">Delete</button>
</div>

This change also makes attributes like hx-disinherit obsolete, which were designed precisely to cut off implicit inheritance: in htmx 4 they’re no longer necessary and can be removed from the markup.

Standardized Events

htmx 2 accumulated event names organically over the years, without a single criterion: knowing exactly when htmx:beforeRequest fired versus htmx:configRequest required memorization or documentation on hand. htmx 4.0.0 organizes everything under a single pattern: htmx:phase:action[:sub-action].

Event in htmx 2Event in htmx 4When it fires
htmx:beforeRequesthtmx:before:requestRight before sending the fetch() request
htmx:afterRequesthtmx:after:requestWhen the server response arrives
htmx:beforeSwaphtmx:before:swapBefore replacing content in the DOM
htmx:afterSwaphtmx:after:swapAfter replacing content in the DOM
htmx:configRequesthtmx:config:requestWhen configuring the request parameters

Additionally, most error events are consolidated into a single htmx:error, while HTTP responses with an error code specifically trigger htmx:response:error. The htmx:xhr:* events disappear because htmx 4 no longer uses XMLHttpRequest, and htmx:validation:* events are removed in favor of the browser’s native form validation. The same command-line tool that detects attributes missing :inherited also flags old event names inside your hx-on attributes and your JavaScript code.

sequenceDiagram
    participant B as "Button"
    participant H as "htmx runtime"
    participant S as "Server"
    B->>H: "click on hx-get"
    H->>S: "fetch GET /saludo"
    Note over H: "fires htmx:before:request"
    S-->>H: "responds with HTML"
    Note over H: "fires htmx:after:request"
    Note over H: "fires htmx:before:swap"
    H->>B: "replaces the target DOM"
    Note over H: "fires htmx:after:swap"
Conceptual diagram of renamed events in htmx 4.0.0
The new event pattern follows the phase:action format. Foto de BoliviaInteligente en Unsplash

History Without localStorage by Default

History support (navigating back and forward with htmx-aware behavior) has been a feature present since the project’s origins. In htmx 2, the implementation saved a snapshot of each page in localStorage to restore it when going back. The problem: that snapshot could include DOM mutations made by third-party libraries, which stayed frozen in the snapshot but without the JavaScript logic that sustained them.

htmx 4.0.0 removes the localStorage cache. Now, when navigating back, htmx requests the page from the server again and swaps it inside body, or inside the element marked with [hx-history-elt] if one exists. This lets third-party scripts work without surprises in most cases and, with good HTTP request caching, it stays fast. For those who prefer local caching, the team maintains the hx-history-cache extension, which restores history from sessionStorage and is designed to integrate with Alpine.js and similar scripting solutions.

How to Try It Today

Trying htmx 4.0.0 today requires nothing more than changing the script version. Since the package isn’t latest on npm yet, you have to request it explicitly:

<!-- Windows, macOS, and Linux: the script works the same everywhere, it's just HTML -->
<script src="https://unpkg.com/[email protected]"></script>

<button hx-get="/saludo" hx-target="#resultado">
  Greet
</button>
<div id="resultado"></div>

On click, htmx fires a GET request to /saludo using fetch() internally and replaces the content of #resultado with the server’s HTML response. Via npm, on Windows, macOS, or Linux, the installation is the same: npm install htmx.org@next.

Once loaded, you can confirm which version is running from the browser console with htmx.version, and check in the browser’s network panel that requests that used to appear as XHR are now listed as fetch.

Impact and Analysis

For the vast majority of developers who use htmx only with hx-get, hx-post, hx-target, and hx-swap attributes placed directly on the element that triggers the action, htmx 4.0.0 behaves exactly like htmx 2. The engine change to fetch() is internal and shouldn’t require touching a single line of HTML.

💡 Tip: before jumping to htmx 4.0.0 in a large project, run the team’s command-line tool: it flags every attribute that needs the :inherited suffix and every old event name inside your hx-on attributes.

The real impact falls on large applications that built their architecture on implicit attribute inheritance, something common in dashboards with many layers of containers sharing hx-confirm, hx-indicator, or hx-swap. There, explicit migration work is required, though it’s bounded by the command-line tool.

⚠️ Heads up: if your application relies on implicitly inherited attributes (hx-confirm, hx-indicator, hx-swap placed on a parent container), they’ll stop working once you move to htmx 4.0.0 until you add :inherited.

The decision not to mark 4.0 as latest on npm is, in itself, an editorial signal: the htmx team prioritizes the stability of existing sites over rapid adoption of the new version, something unusual in a JavaScript ecosystem accustomed to breaking compatibility between minor versions.

What’s Next

The announced plan is to keep 2.x as latest on npm and 4.0 under the next tag until sometime in early 2027, when the team will evaluate the final switch. The official htmx site, meanwhile, already documents version 4.0 as the main reference.

Among the new features arriving with this version, htmx 4.0.0 adds Morph Swaps, a new type of content swap designed to update the existing DOM instead of replacing it entirely; the official announcement promises more detail on this and other new features in future posts.

📖 Summary on Telegram: View summary

Try it yourself: add the htmx 4.0.0 script from unpkg (unpkg.com/[email protected]) to a test HTML file and compare in the network panel how requests change versus your current htmx 2 version.

Frequently Asked Questions

Does htmx 4.0.0 replace htmx 2 immediately?

No. On npm, the latest tag still points to the 2.x line; htmx 4.0.0 is distributed under the next tag until early 2027, so you have to request it explicitly.

Do I have to rewrite my hx-get, hx-post, or hx-target attributes?

No, those attributes work the same. The change only affects attributes you were inheriting implicitly from a parent element; they now need the :inherited suffix.

Why did they remove localStorage history caching?

Because the saved snapshot could include DOM mutations made by third-party scripts that stayed frozen without their original logic when the page was restored. htmx 4.0.0 prefers re-fetching the page from the server.

What happens to my htmx:beforeRequest or htmx:afterSwap listeners?

You need to rename them according to the new pattern: htmx:beforeRequest becomes htmx:before:request and htmx:afterSwap becomes htmx:after:swap, among other changes documented in the release notes.

Does htmx 4.0.0 still work with Alpine.js or hyperscript?

Yes. The hx-history-cache extension, designed to restore history from sessionStorage, is built specifically to integrate well with Alpine.js and similar scripting solutions.

How do I know which version of htmx I have loaded?

From the browser console, with htmx.version once the library is loaded on the page.

References

📱 Enjoying this content? Follow @programacion on Telegram for daily tech content in Spanish: quick summaries, fresh content every day.

Imagen destacada: Foto de Danial Igdery en Unsplash

Categories: Noticias Tech

Andrés Morales

Developer and AI researcher. Writes about language models, frameworks, developer tooling, and open source releases. Covers ML papers, the tech startup ecosystem, and programming trends.

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.