A 530-point Hacker News launch would usually send developers straight to npm install. With htmx 4.0, that command still resolves to version 2.0.10. The split is deliberate: htmx 4 is a stable release, but the maintainers have put it on npm's next tag so sites using an unversioned package or CDN URL do not cross a major-version boundary by accident. The latest tag will remain on htmx 2 until some point in early 2027.
That distribution choice says more about this release than a list of new attributes would. htmx is often dropped into server-rendered applications with a script tag, sometimes without a build step or lockfile. Its new version changes how attributes flow through markup, how browser history is restored, which HTTP responses replace page content, and what events application code receives. Keeping version 4 off the default channel gives those applications an unusual commodity in front-end tooling: time to inspect the migration before receiving it.
The release announcement says the work took eight months. From an application's point of view, htmx 4 is meant to stay close to htmx 2. Underneath, however, the request engine has moved from XMLHttpRequest to the browser's fetch() API. That move opened the way for streaming extensions and a different extension system, while removing XHR-specific events that some applications may still observe.
The default install stays on the old branch
The npm versions page lists 2.0.10 as latest and 4.0.0 as next. A developer who wants the new branch must request it by tag or version:
npm install htmx.org@4.0.0
The same rule applies to CDN use. Pinning the full version is the safe form:
<script src="https://unpkg.com/htmx.org@4.0.0/dist/htmx.min.js"></script>
This staging creates a period in which "current htmx" has two reasonable meanings. The version 4 documentation is live, while the ordinary npm install remains on version 2. Teams copying an example from the new documentation into an old installation will need to check which syntax the example expects. Package manifests and CDN URLs should carry an explicit version during the transition.
The maintainers say htmx 2 will be supported indefinitely. There is no deadline in the announcement requiring existing applications to move. That matters because the largest migration task sits in HTML templates, where ordinary JavaScript codemods have less reach.
Inheritance becomes visible in the markup
In htmx 2, several hx-* attributes placed on a parent element automatically apply to descendants. Version 4 requires an :inherited suffix. A confirmation placed on a container, for example, no longer reaches its delete button unless the template says so explicitly:
<div hx-confirm:inherited="Are you sure?">
<button hx-delete="/item/1">Delete</button>
</div>
The maintainers call this the biggest upgrade item. Implicit inheritance made concise layouts possible, but behavior could originate far above the element that sent a request. Version 4 puts that relationship at the declaration site. The migration guide documents a temporary compatibility switch, htmx.config.implicitInheritance = true, for applications that need to separate the runtime upgrade from the template edits.
There is a sharper edge here than a missing confirmation dialog. Shared parent attributes can carry hx-headers, including anti-forgery tokens. If a child request loses an inherited header, the server may reject it. A visual smoke test will not necessarily expose that path. The supplied checker specifically calls out likely CSRF headers.
The release packages that checker as a command-line program:
npx htmx.org@4.0.0 upgrade-check -- ./templates
According to the release example, it scans HTML and common server-template extensions for inherited attributes, renamed or removed attributes, old event names, and removed JavaScript APIs. Its output is a map for review, not proof that an application is compatible. Templates constructed at runtime, event names assembled from strings, or wrappers that generate htmx attributes can escape static scanning.
Error pages and the back button now take different paths
Two default changes deserve tests at the HTTP boundary. First, htmx 4 swaps the body of every response except status 204 and 304. Version 2 did not swap 4xx and 5xx responses by default. An application that returns a complete branded 500 page may now place that document inside a small component target. A server that already returns a target-sized validation fragment with status 422 may benefit immediately. The guide provides hx-status rules for per-status behavior and a noSwap compatibility setting for teams that need the old 4xx and 5xx treatment.
Second, browser history no longer depends on page snapshots in localStorage. On a back navigation, htmx re-fetches the page and swaps it into the body, or into the element marked with hx-history-elt. The project says cached snapshots were a recurring source of support problems because third-party scripts could mutate saved DOM without restoring the JavaScript state behind those mutations. Re-fetching gives the server and scripts a clean reconstruction, at the cost of making history restoration depend on a request and the application's cache behavior.
Applications with an offline requirement or expensive history endpoints cannot treat this as a cosmetic change. htmx 4 includes an optional hx-history-cache extension that uses sessionStorage. The core default, though, is a network retrieval. Tests should cover back and forward navigation with slow responses, expired sessions, and pages that initialize other JavaScript after a swap.
There are smaller request changes with similarly concrete consequences. The migration guide says hx-delete no longer includes inputs from an enclosing form unless the element adds hx-include="closest form". The default request timeout is now 60 seconds instead of unlimited. Out-of-band swaps occur after the main swap, reversing version 2's order. Code that relies on one replacement creating a target for another needs direct coverage.
Fetch makes streaming part of the extension story
The internal move to fetch() removes htmx:xhr:* events and standardizes the rest under names such as htmx:before:request and htmx:after:swap. Most error events now collapse into htmx:error, while HTTP error responses emit htmx:response:error. Event listeners in application JavaScript, observability hooks, and test helpers may require edits even when the visible UI behaves the same.
Version 4 adds morphing swaps to core through innerMorph and outerMorph. Instead of replacing a target wholesale, a morph can preserve useful DOM state while reconciling the returned HTML. The new <hx-partial> element lets one server response describe updates for multiple targets, each with its own target and swap strategy. hx-status can vary those choices by exact code or status range.
Streaming remains outside the small core. The release includes extensions for server-sent events, WebSockets, and multipart/mixed responses, all built around the fetch-era extension design. It also adds hx-live, a compact client scripting layer inspired by Alpine.js, jQuery, and hyperscript. Developers who want the common extensions bundled with htmx can use the new htmax.js distribution. That bundle is a convenience option, while applications can still load individual extension scripts directly.
The GitHub 4.0.0 release records the final fixes and the full comparison with 2.0.8. Its length is another reason to judge the release through application behavior rather than changelog volume. Start with inherited headers, error fragments, history navigation, event listeners, and delete requests. Those are the places where a locally reasonable default changed the meaning of existing code.
What to watch during the split release
The next useful signal will come from real migrations during the months when 4.0 remains on the next tag. Watch whether server-side htmx integrations adopt the changed request-header formats and event model, and whether the upgrade checker catches the template patterns used by large applications. The other date is early 2027, when the maintainers expect version 4 to become npm's default. Until that switch, a reproducible htmx setup needs one plain detail in every install path: an explicit version.