Server-rendered, always
Your server owns every byte of markup. Pages are crawlable, printable, and viewable with JavaScript disabled — Heron only enhances what's already there.
return render("results.html", rows)
Heron is an 8kb framework for hypermedia apps. Drive your UI with a handful of HTML attributes — server-rendered, no build step, no bundler, no virtual DOM.
$ npm install heron
Zero dependencies · Works with any backend · 8kb gzipped
Trusted in production at
The whole idea, in twelve lines
The server sends HTML. The browser swaps it in. Heron is the thin layer of attributes between those two facts — nothing more.
1<!-- The input asks the server on every keystroke --> 2<input type="search" name="q" placeholder="Search the docs…" 3 hx-get="/search" 4 hx-trigger="keyup changed delay:200ms" 5 hx-target="#results" 6 hx-indicator="#spin" /> 7 8<!-- A spinner Heron shows while the request is in flight --> 9<span id="spin" class="heron-indicator">searching…</span> 10 11<!-- The server's HTML response lands right here --> 12<ul id="results"></ul>
That is the entire feature. No state store, no client router, no rebuild on save.
Why Heron exists
Roughly four in five web apps are content-driven: a dashboard, a catalogue, a settings page, an admin panel. They navigate, they submit forms, they refresh a fragment. Hypermedia — links and forms that return HTML — already describes that shape perfectly. It has since 1993. Heron's whole bet is that you can extend that model with a thin layer of attributes instead of throwing it away for a client-side runtime.
A React SPA pays a fixed tax for every one of those pages: a bundler, a build step, a hydration pass, a state library, an API layer that exists only to feed the client, and a second copy of your routing logic. For a genuinely interactive surface — a spreadsheet, a canvas editor — that tax buys something real. For a pricing page or an issue tracker, you have paid 240kb to re-implement what an anchor tag did for free.
HTMX proved the hypermedia approach at scale, and Heron owes it everything. Heron is the leaner sibling: 8kb gzipped instead of 14, eleven attributes instead of forty, and stricter defaults — requests are scoped, swaps are explicit, and history is opt-in. Fewer knobs, fewer footguns, the same idea. If you outgrow it, you outgrow it onto plain HTML, not onto a migration.
Heron is defined as much by its omissions as its features.
What you get
Every feature below is reachable from an HTML attribute. There is no imperative API to learn and no escape hatch you'll be forced into.
Your server owns every byte of markup. Pages are crawlable, printable, and viewable with JavaScript disabled — Heron only enhances what's already there.
return render("results.html", rows)
Drop in one script tag and ship. No transpiler, no dev server to keep alive, no source maps to debug. The file you write is the file the browser runs.
<script src="heron.min.js"></script>
Webpack, Vite, esbuild, Rollup — Heron needs none of them. Dependency graphs, tree-shaking and chunk-splitting are problems you simply no longer have.
# node_modules: 1 package
The entire runtime is 8,192 bytes over the wire — smaller than most hero images. A CI gate fails the build if a commit pushes it past that line.
heron.min.js.gz → 8.0 kB
Heron speaks plain HTTP and reads plain HTML. Pair it with Rails, Laravel, Express, Flask, ASP.NET or a static generator — no adapter, no SDK.
GET /search → 200 text/html
Behaviour lives in markup, next to the element it affects. Read an HTML file top to bottom and you have read the whole feature — no jumping to a controller.
hx-post="/cart" hx-swap="outerHTML"
How it compares
Numbers below are for an equivalent CRUD admin panel, measured at the same feature parity.
| Heron | React | HTMX | Hotwire | |
|---|---|---|---|---|
| Runtime size (gzipped) | 8 kb | 240 kb | 14 kb | 39 kb |
| Build step required | None |
Webpack | None |
esbuild |
| Authoring model | HTML attrs | JSX | HTML attrs | HTML + Stimulus |
| SSR-native (no hydration) | ||||
| Works with no JS (graceful) | ||||
| Distinct API surface | 11 attrs | ~120 hooks/APIs | ~40 attrs | ~30 + Stimulus |
| Time to first interaction* | 0.21s | 1.18s | 0.34s | 0.52s |
* P95, cold cache, simulated Fast 3G, 4× CPU throttle — Lighthouse 12, median of 28 runs against the reference admin panel.
Quick start
Three steps. No scaffolding command, no project template, no account. Add Heron to a page you already have.
Install via npm, or for a no-build site, drop the CDN tag straight into your <head>.
$ npm install heron
Add three attributes to a button. It now asks the server for HTML and swaps the reply in place.
<button hx-get="/quote" hx-target="#out" hx-swap="innerHTML"> Get a quote </button> <div id="out"></div>
Your route replies with a snippet of HTML — not JSON. Heron places it exactly where you pointed it.
app.get("/quote", (req, res) => { res.send("<p>That will be $48/mo.</p>"); });
That's a working interaction. No bundler ran, no client state, no page reload — elapsed: about forty seconds.
Skip step 1 entirely. Paste this one tag into your page's <head> and you're done — no install, no build.
<script src="https://unpkg.com/[email protected]"></script>
Community
Heron is maintained by a small team and a wide circle of contributors. Questions get real answers — most discussion threads close within a day.
2,941
threads · 94% answered within 24h
6,182
members · #help, #showcase, #internals
148
across 36 countries · 11 with commit access
Esther Maguire
@esmag · lead
Rafael Tavares
@rtav · core
Anjali Khanna
@anjk · docs
Lukas Nielsen
@lukn · runtime
It runs on GitHub Sponsors. If your business ships on it, fund a maintainer day.
Sponsors
Every sponsorship goes directly to maintainer hours, security review, and the documentation site. Thank you.
Organisation sponsors
47 individual sponsors
FAQ
Yes. Heron has been on a stable 1.x line since October 2025 and follows strict semver — no breaking change ships outside a major. It powers 4,408 sites we can see in the wild, including the Northwind and Driftwood admin panels above. The runtime carries a 600-case test suite run against every supported browser, and security-relevant fixes are backported to the previous minor for twelve months.
HTMX is excellent, and Heron exists because of it — please use HTMX if it fits. Heron is a deliberately narrower take: eleven attributes instead of roughly forty, 8kb instead of 14, and stricter defaults so there are fewer ways to surprise yourself. Requests are scoped to their element, swaps must be named explicitly, and history is opt-in. If you want the broader, more configurable toolkit, stay on HTMX. If you want the smallest possible hypermedia layer with sharp edges sanded off, that's Heron.
It can coexist, though that isn't the design goal. Heron only touches elements carrying hx- attributes, so you can keep a React or Vue island elsewhere on the page and Heron will never reach inside it. Many teams use Heron for the content-driven 80% of a product and reserve a framework for the genuinely interactive 20% — a canvas, a complex editor. What we don't recommend is rendering a React tree and then asking Heron to swap nodes inside it; pick one owner per region of the DOM.
The 8kb figure is enforced, not aspirational. Every pull request runs a size check in CI; if the gzipped runtime would cross 8,192 bytes, the build fails and the PR cannot merge until it's back under budget. The number is published on each release and has not moved since 1.0. Heron also ships zero runtime dependencies, so your lockfile gains exactly one line and there is no transitive tree to audit.
Heron is MIT-licensed and governed by a four-person maintainer team plus 148 contributors, so it does not depend on any single person. Funding comes through GitHub Sponsors from organisations including Vercel, Cloudflare, Sentry and Linear, which pays for steady maintainer hours rather than a launch-and-leave release. The 1.x line has a published support window through at least 2029, and because the API is just HTML attributes, the worst-case migration path is plain HTML you already own.
One install, three attributes, a page you already have. Heron stays out of your way and ships nothing you didn't write.
$ npm install heron
28,408
GitHub stars
148,408
npm / week
Stars · 12 months