Show HN: Mador – Make any DOM reactive with a tiny 80-line Proxy state tuple
bosmarcel
84 points
24 comments
September 06, 2026
Related Discussions
Found 5 related stories in 63.1ms across 5,720 title embeddings via pgvector HNSW
- Show HN: TermDOM – HTML, CSS and JavaScript (With a Real DOM) for TUIs and CLIs bikeshaving · 12 pts · August 11, 2026 · 55% similar
- Removing React.js from the codebase and adapting Htmx for UI interactivity (2023) Ralfp · 239 pts · July 27, 2026 · 54% similar
- Show HN: I built a zero-latency developer tool suite in pure Vanilla JavaScript AAPD_Studio · 19 pts · July 23, 2026 · 51% similar
- Show HN: OTP Inspired actor supervisor based full stack templates annrap1d · 11 pts · July 20, 2026 · 51% similar
- Show HN: A Rosetta Stone for UI component libraries ch-bas · 13 pts · August 13, 2026 · 51% similar
Discussion Highlights (11 comments)
bosmarcel
Hey HN! I wanted to see how far you can push modern JavaScript Proxies without all the heavy overhead of a traditional framework. The result is Mador: a tiny ~80-line reactive state tuple ([r, w]) that lets you make any DOM element reactive using a simple CSS selector, automated dependency tracking, and batched microtasks. No build steps required—just drop it in. I built this over the weekend just to experiment with clean, zero-dependency reactivity. Would love to hear your thoughts or see where you'd run into limits with something like this!
DylanMerigaud
Clean launch, good luck!
ahmedhossamdev
Great work!
moostee
Proposed variant optimised for human readaiblity... ```js import mador from "mador"; const [read, write] = mador({ count: 1 }); read(".counter", ctx => ctx.el.textContent = ctx.count); write(".increment", "click", ctx => ctx.count++); write(ctx => ctx.count = 0); ``` ## Read Dependencies are detected automatically when the read function is run during initiation. ```js read(".counter", ctx => ctx.el.textContent = `Count: ${ctx.count}`); ``` ## Write Immediate: ```js write(ctx => ctx.count++); ``` Event-triggered: ```js write(".increment", "click", ctx => ctx.count++); ``` Event writes expose `ctx.el` and `ctx.event`.
PoignardAzur
Are reactive updates based on deep equality or reference equality?
dpweb
The core idiom I've used for years is deliberately tiny: fully encapsulated custom Web Components that simply re-render when matching an attribute and `window.state` changes. Data model is simply: window.state = new Proxy({}, { set(target, key, value) { target[key] = value document.querySelectorAll(`[data="${key}"]`) .forEach(el => el.render?.()) return true } }) handles reactivity.. https://github.com/digplan/vanilla-light
bedroom_jabroni
There are many standalone plug-n-play implementations of the signal primitive in JS. To name a few: preact/signals, vue reactivity, etc, there's even a TC39 proposal for a lang feature. Is this meant to stand out by doing things differently or reinvent them?
hamburglar
> Hey HN! I wanted to see how far you can push modern JavaScript Proxies without all the heavy overhead of a traditional framework. The result is Mador: a tiny ~80-line reactive state tuple ([r, w]) that lets you make any DOM element reactive using a simple CSS selector, automated dependency tracking, and batched microtasks. No build steps required—just drop it in. I built this over the weekend just to experiment with clean, zero-dependency reactivity. Would love to hear your thoughts or see where you'd run into limits with something like this! Unsure why this comment from the author was flagged/dead but it certainly doesn’t seem to run afoul of HN guidelines.
afavour
I’m curious to know what performance looks like. In the recesses of my memory is the belief that proxies are not good for performance but I have no idea if that’s well founded (or maybe once was but isn’t any more). It’s a very smart idea though, I like it.
abosalehworld
I love the minimalist approach here. Using Proxies for state management without the heavy overhead of large frameworks is really elegant. Keeping it under 80 lines is impressive. Great work!
codedokode
The syntax looks a bit too verbose for me. And function names like "read" and "write" are confusing too, given that "read" function isn't made for reading values. Cannot we use a single function for binding, like this (and name it "bind")? let counter = proxy({ count: 0 }); bind('.counter', (el) => el.textContent = counter.count); counter.count++; // Queues DOM update Also, > Mador is distributed as an ES module. This means it cannot be used on a page opened from disk, and the user needs to set up a HTTP server which is time-consuming and distracting. And you cannot distribute an app as as HTML file.