Or: How I Learned to Stop Worrying and Love the Underscore
Remember when you could just tell your computer what to do, in plain English, and it would actually do it? No? Well, grab your DeLorean, because we’re going back to the future with _hyperscript (yes, that underscore is part of the name, and yes, it’s important).
I have been using and love it for years. Part of my toolbox and a perfect campanion to htmx. Its not for everything, but a blessing for simple quick frontend interaction.
A Brief History of Being Too Clever
Once upon a time in the glorious 1980s, Apple created something magical called HyperCard. It was like having a stack of interactive cards on your computer, and you could script them using a language called HyperTalk that read like actual human sentences. Want to make a button do something? You’d write:
|
1 2 3 4 5 |
on mouseUp go to next card end mouseUp |
Boom. Done. No semicolons, no curly braces, no existential crisis about whether you should use const or let.
Fast forward to 2025, and here we are drowning in JavaScript frameworks, build tools, transpilers, and npm packages that require other npm packages just to install themselves. It’s like we collectively decided that programming wasn’t hard enough, so we should make it really hard.
Enter Carson Gross, a greybeard programmer and professor at Montana State University who apparently looked at this situation and thought: “You know what? Let’s just go back to making sense.”
What the Heck is _hyperscript?
_hyperscript (created by the same Carson Gross who gave us htmx) is a scripting language that lets you add interactivity to web pages by literally writing what you want to happen. It’s inspired by HyperTalk and runs right in your browser with zero build steps, zero compilation, and zero patience for your webpack configs.
Here’s a taste:
|
1 2 3 4 5 |
<button _="on click toggle .hidden on #menu"> Toggle Menu </button> |
Read that again. Out loud. Notice something? It’s just English. When the button is clicked, toggle the “hidden” class on the element with id “menu.” That’s not pseudo-code or a comment explaining what the code does—that IS the code.
Compare that to the vanilla JavaScript equivalent:
|
1 2 3 4 5 |
document.querySelector('button').addEventListener('click', function() { document.getElementById('menu').classList.toggle('hidden'); }); |
Sure, JavaScript works fine, but which one can your designer read? Which one will you understand when you come back to it at 2 AM six months from now?
Examples That’ll Make You Go “Wait, That’s It?”
The Classic Toggle
|
1 2 3 4 5 |
<button _="on click add .highlighted to me"> Highlight Me </button> |
Async Without the Headache
Remember Promise hell? Callback pyramids? async/await confusion? _hyperscript just… handles it:
|
1 2 3 4 5 6 7 8 9 |
<div _="on click wait 2s then add .fade-in then wait 1s then remove .fade-in"> Click me for a timed animation </div> |
No promises to chain. No await keywords to remember. It just waits. Like a human would.
Events Everywhere
|
1 2 3 4 5 6 7 8 9 |
<button _="on click send customEvent to #target"> Send Event </button> <div id="target" _="on customEvent add .pulsing"> I'll react to that custom event! </div> |
The “Tell” Command (My Personal Favorite)
|
1 2 3 4 5 |
<button _="on click tell <p/> in me to add .highlight"> <p>This paragraph will get highlighted</p> </button> |
You’re literally telling parts of your DOM to do things. It’s like being a tiny benevolent dictator of HTML elements.
The Philosophy: Locality of Behavior
Here’s where it gets interesting. _hyperscript embraces something Carson calls “locality of behavior”—the idea that the behavior of an element should be right there with the element, not hiding in some app.js file three directories away.
Traditional wisdom says “separation of concerns”—put your HTML in one file, CSS in another, JavaScript somewhere else. But Carson (and others like the Tailwind folks) noticed something: splitting things up doesn’t always make them clearer. Sometimes it just means you’re playing detective every time you need to find out what happens when a button is clicked.
With _hyperscript, the behavior is right there:
|
1 2 3 4 5 6 7 8 9 |
<input type="text" _="on change show #warning when my value is empty" > <div id="warning"> Hey! You forgot to fill this out! </div> |
No hunting. No guessing. Just… look at it.
What’s the Deal in 2025?
As of 2025, _hyperscript is still cruising toward its 1.0 release (Carson mentioned in 2024 he was hoping to ship it after htmx 2.0). It’s what he calls a “speculative passion project”—meaning it’s an experiment in making web development not suck.
The cool kids are starting to notice. With htmx’s meteoric rise in popularity (seriously, it’s everywhere now), _hyperscript is riding along as its quirky companion. People building Django, Rails, Laravel, and Go apps are discovering that maybe—just maybe—they don’t need React for everything.
Here’s what’s happening:
Growing Community: The htmx Discord has a thriving #hyperscript channel where people share tricks and help each other out.
Better Docs: The community is actively working on improving documentation and creating real-world examples (check out hyperscript.org).
Production Use: Despite being “pre-1.0,” developers are using it in production, especially for content-heavy sites, dashboards, and server-rendered apps.
The “Wait, This is Simple?” Moment: More developers are having that epiphany where they realize they’ve been over-engineering their frontends.
Who Should (and Shouldn’t) Use It
Great For:
- Content-heavy sites (blogs, e-commerce, CMS)
- Server-rendered applications (Django, Rails, PHP, Go + Templ)
- Prototyping (no build step = instant feedback!)
- Teams that value readability over cleverness
- People who miss HyperCard and want to feel that joy again
Maybe Not So Great For:
- Heavy client-side apps (think Figma, Notion, complex games)
- Real-time multiplayer anything
- Projects where you already have a React team happy with React
- Situations where you need the JavaScript ecosystem’s nuclear arsenal
The Technical Bits (For the Nerds)
_hyperscript is implemented as a lexer, parser, and eval-based runtime in JavaScript. Carson admits this is “right at the edge of complexity” he’d want to tackle in JavaScript, but modern browsers are fast enough to make it work smoothly.
Key features:
- Async Transparency: Automatically resolves Promises so you don’t have to
- No Build Step: Just drop in a script tag and go
- Extensible: You can add your own commands and expressions
- Debugging: Built-in breakpoint support for stepping through code
- Side-by-side JS: Works perfectly with vanilla JavaScript when you need it
Installation? Ridiculously simple:
|
1 2 3 |
<script src="https://unpkg.com/hyperscript.org@0.9.14"></script> |
Done. That’s it. No npm. No webpack. No wondering if your node_modules folder achieved sentience.
The Controversial Part
Carson openly admits that a lot of people hate _hyperscript’s syntax. Some folks see that English-like code and recoil in horror. “It’s not real programming!” they cry. “It’s too verbose!” others complain.
And you know what? That’s fine. _hyperscript isn’t trying to replace JavaScript for everything. It’s not trying to win over the hardcore React developers who dream in JSX. It’s offering an alternative for when you just want to add some interactivity to your HTML without summoning the entire JavaScript industrial complex.
As Carson says on the Grug Brained Developer (another Carson Gross production that you absolutely must read):
“complexity bad”
My Take: It’s Kinda Refreshing?
Look, I build stuff with React. I understand closures, hooks, and all that jazz. But there’s something genuinely delightful about writing:
|
1 2 3 4 5 |
<button _="on click call alert('Hello!')"> Say Hi </button> |
And having it just… work. No transpilation. No build process. No waiting for webpack to bundle. Just refresh the page and see your changes.
It’s like when you first learned HTML and could view source, make a change, refresh, and see results instantly. Remember that feeling? _hyperscript brings it back.
The Future: Hypermedia Strikes Back?
Between htmx and _hyperscript, Carson Gross is leading a quiet revolution that asks: “What if the web already had most of the tools we need, and we just forgot to use them?”
Will _hyperscript take over the world? Probably not. JavaScript isn’t going anywhere, and that’s actually fine—_hyperscript plays nice with it.
But for a growing number of developers tired of JavaScript fatigue, tired of npm hell, tired of explaining to stakeholders why they need to rewrite the entire frontend every 18 months, _hyperscript offers something precious: simplicity.
Give It a Try!
Head over to hyperscript.org, check out the docs, and try adding _="on click toggle .hidden" to a button. See if it makes you smile.
If you’re working on a project that’s mostly server-rendered and you just need some light interactivity, give _hyperscript a shot. If you find yourself writing the same event listeners and DOM manipulation code over and over, maybe there’s a simpler way.
And if nothing else, it’s worth experiencing just to remember that programming can be fun again.
Resources
- Official Site: hyperscript.org
- GitHub: github.com/bigskysoftware/_hyperscript
- htmx (its sibling): htmx.org
- Carson’s Book: “Hypermedia Systems” (available free online)
- The Grug Brained Developer: grugbrain.dev (read this, it’s hilarious and true)
Now go forth and script hyperbolically! Or is it hyperscriptically? Whatever, you get the idea. Just have fun with it.
