Chat on WhatsApp
Headless & Architecture 11 min read

Hypermedia Is Winning: HTMX 4.0 and Datastar for Developers Tired of the SPA Tax

2026 is the year hypermedia stopped being a contrarian take. HTMX 4.0 and the ~11 KB Datastar let you build reactive UIs by shipping HTML, not 300 KB of JavaScript, and they slot neatly into a Magento + Hyvä stack.

Hypermedia Is Winning: HTMX 4.0 and Datastar for Developers Tired of the SPA Tax

You shipped 300 KB of JavaScript so a button could update a number. A hydration pass, a virtual DOM, a state store, a fetch client, a serializer, and a re-render — all so 3 could become 4 in the cart badge. That is the SPA tax, and in 2026 a lot of teams have decided to stop paying it. This is a developer-to-developer tour of the hypermedia renaissance: HTMX 4.0, the tiny powerhouse Datastar, and where both fit in a Magento and Hyvä stack without you ripping out anything that already works.

60%less front-end code, reported
11 KBDatastar, HTMX + Alpine in one
60×less JS shipped vs React, simple dashboards (reported)
4.0HTMX version, now on the Fetch API

The SPA tax, and who's done paying it

For a decade the default answer to "we need some interactivity" was "spin up a React app." It made sense when the alternative was jQuery spaghetti. But the bill kept growing: a build pipeline, a bundler, a router, a data-fetching library, a cache, hydration, and a small mountain of glue that turns JSON into DOM and back again. For a genuine application — Figma, a trading terminal, a spreadsheet — that complexity earns its keep. For a dashboard, a settings page, a product grid, or a checkout step, it is overhead you pay forever.

The industry has split into two camps in 2026. One is the hypermedia renaissance — HTMX and Datastar — where the server owns the HTML and the client just swaps fragments. The other is local-first apps built on heavy sync engines that keep a replicated database in the browser for offline-first, instant, collaborative software. Local-first is genuinely exciting for a narrow class of apps, but it is a big commitment and not what most teams need. This post is about the first camp, because that is where the boring, fast, overlooked wins live.

"Bundle fatigue" is the honest name for the trigger. Shipping 300 KB of JavaScript for a simple dashboard used to be invisible — now it is a liability, because search engines grade Core Web Vitals on real devices, mobile-first. Less JavaScript is not a vibe; it is a ranking input.

Key point

Hypermedia is not anti-JavaScript. It is anti-shipping a second application to the browser just to render server data. You still write JS — a few kilobytes of it — for the interactions HTML can't express on its own.

HTMX in 90 seconds

HTMX is the gateway drug. You add attributes to ordinary HTML, the server returns HTML fragments, and HTMX swaps them into the page. There is no client-side view layer and no JSON-to-DOM mapping to maintain. Here is the whole mental model:

<button hx-get="/cart/count"
        hx-trigger="every 30s"
        hx-target="#cart-count"
        hx-swap="innerHTML">
  Refresh
</button>

<form hx-post="/newsletter" hx-target="#result" hx-swap="outerHTML">
  <input name="email" type="email" required>
  <button>Subscribe</button>
</form>

That's it. hx-get and hx-post say which verb and URL; hx-trigger says when (a click by default, or every 30s here); hx-target says which element to update; hx-swap says how (innerHTML, outerHTML, beforeend, and so on). The server's job is dead simple — return the fragment the client asked for. In a Magento controller that is a few lines:

<?php
declare(strict_types=1);

namespace Panth\Cart\Controller\Count;

use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\Controller\Result\RawFactory;

class Index implements HttpGetActionInterface
{
    public function __construct(
        private readonly RawFactory $rawFactory,
        private readonly \Panth\Cart\Model\CartCount $cartCount
    ) {
    }

    public function execute()
    {
        $count = $this->cartCount->get();
        $resultRaw = $this->rawFactory->create();

        return $resultRaw->setContents(
            '<span id="cart-count">' . (int) $count . '</span>'
        );
    }
}

No application/json, no DTO, no client-side state to reconcile. The response is the UI. You already know how to render HTML on the server — HTMX just lets that HTML come back in small, targeted pieces instead of whole pages.

The server returns HTML. The browser swaps it in. That sentence is the entire architecture — and that is the point.

What changed in HTMX 4.0

HTMX 4.0, released in 2026, is the version that makes this worth a fresh look even if you tried HTMX years ago and shrugged. The headline change is the transport: the old XMLHttpRequest plumbing is gone, replaced by the modern Fetch API. That sounds like an implementation detail until you remember what fetch() can do that XHR couldn't — stream.

Because the response body is a readable stream, the front end can process and render fragments as they arrive instead of buffering the whole response and swapping at the end. A slow, multi-section page can paint its first chunk immediately while the server is still composing the rest. For a list that aggregates from three services, or a report that's expensive to assemble, that is the difference between a spinner and a page that fills in front of the user. It also lines HTMX up with the rest of the platform — abort signals, request/response interception, and the same `fetch()` you already use everywhere else.

Key point

The HTMX 4.0 move to Fetch isn't a rename of XHR. Streaming means perceived performance improves for free on any endpoint that can flush output incrementally — which is most server-rendered HTML.

Datastar: HTMX and Alpine in one 11 KB file

If HTMX is the gateway, Datastar is the next evolution. It started life as a proposed HTMX rewrite and grew into its own project. In roughly 11 KB it does what HTMX and Alpine.js do together: server round-trips for fetching HTML, plus local reactive state for the interactions that should never touch the network. Smaller than HTMX, doing more — that is the part that makes people look twice.

Local reactivity in Datastar is signal-based. You declare signals as data attributes and bind to them; no round-trip needed for a counter or a toggle:

<div data-signals="{count: 0}">
  <button data-on-click="$count++">+1</button>
  <span data-text="$count"></span>
</div>

If you've written Alpine, that will feel familiar — $count is reactive state, data-on-click is an event handler, data-text binds output. The twist is what happens when you do want the server: Datastar is SSE-oriented. The server pushes Server-Sent Events that patch signals and the DOM, which means real-time and collaborative UI fall out of the architecture instead of being bolted on with a separate WebSocket layer.

<button data-on-click="@get('/feed')">Load live feed</button>
<div id="feed"></div>

The @get('/feed') action opens a request to your endpoint, and the server replies with an SSE stream of events. Conceptually the wire format is just named events with HTML or signal payloads — the server says "patch this element" or "set this signal," repeatedly, over one long-lived connection:

event: datastar-patch-elements
data: selector #feed
data: mode append
data: elements <article>New order #1042</article>

event: datastar-patch-signals
data: signals {unread: 3}

Because the stream stays open, the same mechanism that loads a feed also keeps it live. Multiple browsers subscribed to the same stream get the same patches — that is the "multiplayer out of the box" claim, and it is real for the class of apps that suit it.

Why this matters for Core Web Vitals

Here is the part that turns an architecture preference into a business argument. Teams moving from a React build to hypermedia report ~40–60% less front-end code, and for simple dashboards some report on the order of 60× less JavaScript actually shipped to the browser. Even with generous skepticism about any single number, the direction is not in dispute: you send less JS.

Less JavaScript on the main thread maps directly to better INP (Interaction to Next Paint) — the metric most Magento stores fail — because the browser isn't busy hydrating and reconciling when the user taps. It also helps LCP, since server-rendered HTML arrives ready to paint instead of waiting on a bundle to download, parse, and execute before anything meaningful shows. Google grades these on real mobile devices. "Ship less JS" is, in 2026, also "rank better."

Key point

INP is a main-thread problem. The cheapest way to improve it is to not ship the JavaScript that blocks the main thread in the first place. Hypermedia is that, by default.

 HTMXDatastarReact SPA
Bundle size~14 KB~11 KB100–300 KB+
Reactivity modelServer fragmentsSignals + serverVirtual DOM + state
Real-time / SSENo (extension)YesNo (add a lib)
Learning curveHoursHoursWeeks
SEO / CWV by defaultYesYesNo

Where hypermedia fits in a Magento + Hyvä stack

If you build on Hyvä, you are already a hypermedia developer — you just may not call it that. Hyvä ships server-rendered HTML plus a little Alpine.js for interactivity, deliberately not a React SPA. That single decision is why Hyvä storefronts are fast. HTMX and Datastar are the same family of idea, taken a step further. So this isn't a rewrite of your worldview; it's an extension of it. If you want a refresher on that philosophy, my Hyvä theme development work leans on exactly these principles.

Datastar is especially interesting for Hyvä teams who currently combine Magewire (server round-trips) with Alpine (local state). Datastar can cover both responsibilities in one ~11 KB library — the server round-trips Magewire gives you and the local reactivity Alpine gives you — which is worth a hard look the next time you reach for both on the same component.

Be honest about the boundaries, though. Magento's Luma checkout is Knockout and RequireJS — the heavy, JSON-driven thing hypermedia exists to replace — and nobody is suggesting you rip Magento core apart to swap it. The smart play is to use hypermedia where you control the markup: custom widgets, the mini-cart, wishlist toggles, faceted-filter bits, admin tools, and greenfield companion apps that sit alongside the store. There, a few HTMX attributes or a Datastar signal replace a whole component's worth of bespoke JavaScript, and your Magento performance optimization budget thanks you for it.

Key point

Don't fight Magento core. Adopt hypermedia at the edges you own — widgets, mini-cart, admin, companion apps — where shipping less JS is a clean, reversible win.

When you should still reach for React

This is where I refuse to strawman React, because plenty of React teams ship great software. Hypermedia trades a network round-trip for simplicity. When the interaction must be instant and offline-capable — a canvas editor, a drag-and-drop board with complex local rules, a spreadsheet recalculating thousands of cells, a deeply stateful wizard that can't tolerate a server hop — a client-side framework earns its weight. The local-first camp (the other 2026 path) exists precisely for software where the client owns a meaningful chunk of the data model and needs to work without a connection.

If your app is genuinely an application — rich, stateful, offline, collaborative at the data layer — React, Vue, or a local-first sync engine is the honest answer. The mistake the industry made wasn't choosing React; it was choosing it by default for pages that were always just HTML. Hypermedia's win is reclaiming that default. Reach for the SPA when the interaction can't survive a round-trip; reach for hypermedia for everything else — which, for most stores, is almost everything.

Building a fast Hyvä storefront or a hypermedia front end? I'm an Adobe-certified Magento & Hyvä developer who keeps JavaScript budgets lean.

Hire me

Frequently asked questions

Is HTMX production-ready in 2026?

Yes. HTMX has been used in production for years, and 4.0's move to the Fetch API modernizes the transport without changing the attribute API you already know. It's a small, stable, dependency-free library — arguably more production-safe than a sprawling SPA toolchain because there's so much less surface area to break.

HTMX vs Datastar — which should I pick?

Pick HTMX if you mostly need server-driven fragment swaps and want the largest community and ecosystem. Pick Datastar if you also need local reactive state and real-time/SSE updates and would rather have one ~11 KB library than HTMX plus Alpine. For a Hyvä team already running Magewire and Alpine, Datastar is the more interesting consolidation.

Does hypermedia work with Magento and Hyvä?

It fits naturally. Hyvä is already server-rendered HTML plus Alpine, which is the same family of idea. Use HTMX or Datastar for custom widgets, mini-cart, wishlist toggles, faceted bits, admin tools, and companion apps. Leave Magento's Knockout/RequireJS checkout alone — this is about the edges you control, not a core rewrite.

Will this hurt my SEO?

The opposite. Server-rendered HTML is the most crawlable thing you can serve, and shipping far less JavaScript improves INP and LCP — the Core Web Vitals Google grades mobile-first. Hypermedia is one of the few architecture choices that helps SEO by default rather than fighting it.

Do I still need Alpine.js with Datastar?

Generally no. Datastar's signals cover the local-reactivity job Alpine usually does, and it adds server round-trips and SSE on top. Many teams adopt Datastar specifically to drop the Alpine + Magewire combination down to one library. If you only need tiny local toggles and already lean on Hyvä's Alpine, keeping Alpine is fine — it's a consolidation choice, not a requirement.

When is React still the right call?

When the interaction must be instant and offline-capable: canvas editors, complex drag-and-drop, spreadsheets, or deeply stateful apps where the client owns part of the data model. If your software is a genuine application rather than a page with some interactivity, a client framework — or a local-first sync engine — earns its weight. Hypermedia wins the default case, not every case.