· via Hacker News – Front Page (native)
htmx 4.0 ships after eight months: fetch() core, explicit inheritance, morph swaps
htmx 4.0.0 lands after eight months of work, swapping XMLHttpRequest for fetch(), making attribute inheritance opt-in, renaming events and dropping localStorage history, while staying close to htmx 2 for most apps.

The htmx team has released version 4.0.0 of its HTML-first JavaScript library, wrapping up about eight months of development. According to the release announcement, published on August 28 and featured on the Hacker News front page, the new version keeps the library's outward behavior close to htmx 2 even though its internals were rewritten around the fetch() API.
How version 4 came together
The announcement's author explains that the idea took shape while building fixi, a small experimental hypermedia library, which meant getting familiar with fetch() and modern async JavaScript — APIs htmx had long avoided in favor of XMLHttpRequest for backward-compatibility reasons. A later conversation with a contributor named Christian about streaming HTML responses suggested that moving to fetch() would simplify both that use case and the library in general, and contributors Michael and Alex eventually joined the effort.
The team began by porting fixi alongside the existing htmx test suite, then gradually nudged the new implementation back toward the old one as they rediscovered why htmx had made its original design choices. The announcement describes the behavioral gap between 2.x and 4.x as relatively small, with the remaining differences being deliberate choices meant to keep htmx-based applications healthy as very long-lived web services.
Three changes users will notice
Attribute inheritance is now explicit rather than implicit. In htmx 2, attributes such as hx-confirm placed on a parent element silently applied to its children — a behavior dating back to intercooler.js and modeled on CSS. In htmx 4, inheritance must be requested with an :inherited suffix, for example hx-confirm:inherited. The announcement calls this the single largest upgrade burden, and a command-line tool is provided to locate affected markup.
Event names have been standardized into an htmx:phase:action pattern: htmx:beforeRequest becomes htmx:before:request, htmx:afterSwap becomes htmx:after:swap, and so on. Most error events collapse into a single htmx:error, HTTP failures fire htmx:response:error, the htmx:xhr:* events disappear along with XMLHttpRequest itself, and the validation events are dropped in favor of native browser form validation.
History handling no longer snapshots pages into localStorage, which the announcement identifies as a long-running source of support headaches, because mutations made by third-party scripts persisted in the snapshot while the logic behind them did not. On back navigation, htmx 4 re-fetches the page and swaps it into the body, or into a designated hx-history-elt element. A new hx-history-cache extension restores local caching using sessionStorage and is designed to integrate with scripting solutions such as Alpine.js.
Morph swaps and a new partial tag
Two headline features arrive in 4.0. Morphing swaps are now supported out of the box, building on the author's earlier idiomorph work with an improved algorithm contributed by Michael, so swaps can update only the parts of a DOM tree that actually changed. The new hx-partial element extends the idea of out-of-band swaps: a single response can carry multiple partials, each with its own hx-target and hx-swap, which the team argues is far clearer when doing anything beyond replacing one element with a new version of itself.
A larger extension ecosystem
Switching to fetch() internally let the team rethink how extensions work, and several ship with the release: hx-preload for prefetching content on hover, hx-download for native fetch-based file downloads, hx-alpine-compat for smoothing over htmx and Alpine.js friction, and hx-history-cache. Streaming gets three options — hx-sse over text/event-stream, hx-ws over WebSockets, and a new hx-multipart over multipart/mixed responses.
There is also hx-live, the project's own small front-end scripting layer inspired by Alpine.js, jQuery and hyperscript, including what the team calls DOM-based, HATEOAS-friendly reactivity. For those who would rather not choose, a new htmax.js bundle packages htmx with the most popular extensions in a single file.
Upgrading from htmx 2
Notably, 4.0 is not being marked as latest on npm. To avoid force-upgrading sites that load htmx through non-versioned CDN URLs, the 2.x line keeps the latest tag while the 4.0 line remains on next until some point in early 2027, although the project website will reference 4.0.
For migration, the team provides an upgrade checker, run via npx [email protected] upgrade-check, which scans templates and scripts across file types such as .html, .php, .js, .ts, .jinja and .erb. It flags missing :inherited suffixes — including cases like CSRF headers that would silently stop reaching child elements — plus renamed attributes such as hx-disable becoming hx-ignore, and removed attributes like hx-vars, with hx-prompt now available again as an extension.
Why it matters
htmx has become one of the most widely adopted alternatives to heavy client-side frameworks, and this release shows a mature project modernizing its foundation without demanding a painful migration. Explicit inheritance removes a longstanding source of confusion, dropping localStorage history addresses years of support complaints, and the fetch()-based core unlocks a streaming-friendly extension ecosystem. The npm rollout — keeping 2.x as latest well into 2027 to protect unversioned CDN users — is a rare example of a library prioritizing existing users over release-day visibility. For teams invested in server-rendered HTML, htmx 4 signals that the hypermedia approach is still actively evolving.
- #htmx
- #javascript
- #web-development
- #html
- #open-source