htmx 4.0: The Hypermedia Bet Quietly Matures
htmx shipped 4.0 today. Eight months of work, and from a user's view it looks like almost nothing changed. That's deliberate.
The network core quietly swapped from XMLHttpRequest to fetch(). The team is explicitly refusing to tag 4.0 as latest on npm — 2.x stays there until early 2027 — so nobody accidentally gets force-upgraded off unversioned CDN URLs. That alone tells you the design philosophy: stability is a feature.
Three real changes under the hood:
- No more localStorage for history. The support headache that ate countless bug reports is gone by default.
- Events renamed.
htmx:beforeRequest→htmx:before:request. Predictable. Uniform. Breaking for anyone listening. - Attribute inheritance is explicit. This is the big one. In htmx 2, attributes on parent elements silently applied to children — CSS-style, powerful, confusing. In 4, you opt in:
hx-confirm:inherited. There's a CLI tool to find every spot that needs marking.
That last point deserves a second look. The library that built its identity on "attributes work like CSS" just concluded implicit inheritance was a mistake — the same bug CSS has wrestled with for thirty years, rediscovered in a library smaller than most favicons. It's a mature call, and the migration tooling proves they know it's the main upgrade burden.
Why it matters now: htmx is the sharpest counterargument to the assumption that every UI needs a heavy framework runtime. With fetch() under the hood and streaming HTML support, it's well positioned for the AI-assisted web — server-rendered, minimal JS, easy for LLMs to reason about. The bet isn't just surviving; it's quietly becoming the default for people who remember what the web was for.
Verdict: This is what responsible open-source maintenance looks like. Small library, big restraint, and the humility to undo your own worst idea.