I used to ship my app with a JavaScript first mindset. It felt fast on my own laptop, but users on weak phones, slow networks, or locked down corporate browsers kept running into sticky pages and half awake UI.
After I finally measured what I was shipping, I realized most of the client code was not adding value. It was just making hydration heavier, breaking accessibility, and hiding simple HTML solutions.
The post walks through the process I used to cut around 80 percent of the JS without going full “no JS”: listing real interactions in human language, leaning on native elements like details and dialog, using bundle analyzers, and deleting dependency creep. It also shows the small performance and accessibility checklist I use now.
This really resonates with something I've been working on. The article nails the core problem: we maintain JavaScript state that's just a shadow copy of what the DOM already knows.
I built a library called stateless that takes this further. Instead of syncing React state with the DOM, it just reads state directly from the DOM using MutationObserver. Your HTML becomes the single source of truth.
// Instead of useState + onChange + value prop dance
const [value, setValue] = useDomValue('#email', 'value');
The hook watches the DOM element and re-renders when it changes. No hydration mismatch bugs. No state sync issues. The DOM is the state.
It's particularly useful for the patterns the article mentions: progressive enhancement where HTML works first, then React enhances. Your form inputs, disclosure widgets, and native elements already hold their state. Why duplicate it?
stateless is part of a broader open source suite: genx for HTML generation, domx for DOM manipulation, all built on the DATAOS architecture, that together form building blocks for a hyper-efficient framework where the DOM isn't an afterthought you sync to, it's the foundation you build on
The mental model shift is weird at first ("wait, I'm not managing state?") but once it clicks, you stop fighting the browser and start letting it do its job.
2 comments
[ 2.4 ms ] story [ 20.5 ms ] threadAfter I finally measured what I was shipping, I realized most of the client code was not adding value. It was just making hydration heavier, breaking accessibility, and hiding simple HTML solutions.
The post walks through the process I used to cut around 80 percent of the JS without going full “no JS”: listing real interactions in human language, leaning on native elements like details and dialog, using bundle analyzers, and deleting dependency creep. It also shows the small performance and accessibility checklist I use now.
I built a library called stateless that takes this further. Instead of syncing React state with the DOM, it just reads state directly from the DOM using MutationObserver. Your HTML becomes the single source of truth.
The hook watches the DOM element and re-renders when it changes. No hydration mismatch bugs. No state sync issues. The DOM is the state.It's particularly useful for the patterns the article mentions: progressive enhancement where HTML works first, then React enhances. Your form inputs, disclosure widgets, and native elements already hold their state. Why duplicate it?
stateless is part of a broader open source suite: genx for HTML generation, domx for DOM manipulation, all built on the DATAOS architecture, that together form building blocks for a hyper-efficient framework where the DOM isn't an afterthought you sync to, it's the foundation you build on
Zero runtime dependencies, ~2KB gzipped: https://github.com/anthropics/stateless (or wherever it's hosted)
The mental model shift is weird at first ("wait, I'm not managing state?") but once it clicks, you stop fighting the browser and start letting it do its job.