You direct.
Agents build.
Whole engine in one prompt. Everything else is your app.
define('counter', {
$({ count = 0 }) {
return [
mx.button({ onclick: _ => this.$({ count: count - 1 }) }, '-'),
mx.span(count),
mx.button({ onclick: _ => this.$({ count: count + 1 }) }, '+')
];
}
});
document.getElementById('app').render(mx.counter());let count = 0;
let label = document.createElement('span');
let step = (text, delta) => {
let button = document.createElement('button');
button.textContent = text;
button.onclick = _ => label.textContent = count += delta;
return button;
};
label.textContent = count;
document.getElementById('app').append(step('-', -1), label, step('+', 1));Four names that work the same way
Describes
mx.div(...) returns a lightweight description, a small marked array, so no JSX or build tooling is needed.
Creates real nodes
Same syntax, returns a real element. Build it now, keep the reference, mount it anywhere.
Reconciles
el.render(...) diffs descriptions against live children. The attribute cache skips anything unchanged.
Registers components
A tag with state and methods: this.$({ count }) merges into its state and re-renders it.
What frameworks cost an AI
The next million apps won't be scaffolded with npm install. They'll be prompted into existence as single files that get generated and thrown away, so the engine behind them should be small enough to fit in a system prompt.
Tokens spent on setup
In a typical framework project, imports, build setup and config files are tokens the model reasons about but the user never sees, and all that setup is paid for in inference.
Config the model gets wrong
AI often gets bundler and compiler configuration wrong, and a broken config stops the whole app before any of your code runs. mx works as a raw script tag. Minify if you like, but there's nothing to configure.
API surface
Every extra API, such as useEffect, useMemo, forwardRef, Suspense or Server Components, is one more thing a model can make up. mx exposes four API bindings: mx, dom, define and components.
Weight mismatch
React 19 + ReactDOM is about 60 times the size of mx. A smaller surface leaves less to misuse or hallucinate, and less to debug when the AI gets it wrong.
From single files up to real apps
A paste-ready system prompt, the React habits agents bring, and a self-check list.
A 20 Hz feed at 60 fps with zero dropped frames and a 97% attribute-cache hit rate.
Routing, lazy views, real-time data and the patterns that hold across 200+ components.
Render to static HTML at build time, then upgrade the same markup in place. This site is built that way.
Use mx and dom inside registered custom elements, with or without Shadow DOM.
One script with no dependencies, so it brings no library versions to clash with the host page and needs nothing from its build.
Why smaller ends up faster
Every framework runs the same app with identical data and CSS, as a production build in Playwright headless Chromium.
Paint-synchronized sort
Frame time at 120 Hz, where the budget is 8.33 ms. mx fits with ~2 ms to spare.
Three suites on M1, M4 Pro and M5 Pro hardware. Where a competitor wins, it's listed.
- mx: 6.24 ms
- Angular: 7.28 ms
- React: 7.32 ms
- Vue: 10.94 ms
- Svelte: 11.66 ms
Whole applications stay small
The engine is only part of it. A production app with 200+ components ships about 100 KB of JS and 50 KB of CSS gzipped, while framework apps of similar scope typically ship 5 to 10 times as much. Live data, forms and dozens of views stay this small because there's no machinery between your code and the DOM.
The engine itself
Brotli size next to mx, with ReactDOM counted in React and hooks in Preact, and how you usually write code for each. Angular and Svelte have no runtime file of their own, so their figure is a hello-world production build that grows as you add components. Dependencies are the packages each one installs besides its own, not counting build tooling.
| Feature | mx | Preact | Svelte 5 | Angular 22 | Vue 3 | React 19 |
|---|---|---|---|---|---|---|
| Size (brotli) | <1 KB | ~5x | ~8x | ~30x | ~35x | ~60x |
| Usual syntax | Plain function calls | JSX | .svelte components | Decorators and templates | Single-file components | JSX |
| Without a build | Runs as written | With htm | Not possible, it's a compiler | Needs the JIT compiler, no decorators | Needs the template compiler, no SFCs | createElement or htm |
| Dependencies | None | None | About 20, compiler included | 2 | About 20, compiler included | 1 |
| Server rendering | Needs a DOM library | Separate package | Built in | Separate packages | Built in | Built in |
| Existing server HTML | Any matching markup | Any matching markup | Its own output, with markers | Its own output, with markers | Its own server output | Its own server output |
Give your AI an engine that fits in its context
The minified engine is about 900 tokens of source with no dependencies, so all of it fits inside a system prompt as code rather than as a reference.