Micro JavaScript Framework for AI Agents

Reactive components with a React-like API in ~9 KB gzip: zero dependencies, no build step. Designed for both human developers and AI agents.

  • Zero dependencies
  • MIT licensed
  • No build step
  • TypeScript types
counter.html: the whole app
import { html, mount } from 'lemonadejs';
const Counter = (props, { state }) => {
    const count = state(0);
    return html`<div>
        <h1>${count}</h1>
        <button onclick="${() => count.value++}">+1</button>
    </div>`;
};
mount(Counter, document.getElementById('app'));

● live: this exact code, running on this page

Open in the playground
9.3 KBengine, gzipped
0dependencies
1,049tests gating the repo
62real-Chrome probes
43contract-verified blocks

Verified, not assumed.

Every component is published with a typed contract and checked against it. The result is machine-readable JSON, consumable by humans, agents, and CI.

1

Publish with a contract

component('switch', {
    bind: false,
    label: '',
    onchange: Function,
    api: { toggle: Function },
}, fn);
2

The schema is the interface

contract(Switch)
// { name: "switch",
//   props: { label: …},
//   bind, events, api }
// agents read THIS, not source
3

verify() enforces it

verify(Switch)
// { pass: true, checks: [
//   'mounts with defaults',
//   'prop label (live state)',
//   'bind', 'api via ref' ] }

All 43 Studio blocks pass this check before release; a failing verify() cannot enter the registry. How contracts work

A small core with strong guarantees.

The entire framework: four template rules, one file, an API that fits in 2k tokens. An agent reads all of it in one prompt; you read it in an afternoon.

Four template rules

The entire template language: live state, live expression, snapshot, and loops/conditionals as expressions. Everything else follows.

Contracts, verified

component(name, contract, fn) publishes a typed schema; verify() proves the implementation honors it. Agents read interfaces, not source.

Keys that move state

Keyed lists move DOM and component state on reorder; changed values patch living instances instead of rebuilding them.

Lifecycle managed by the engine

listen() cleans up listeners automatically; resource() cancels stale fetches and discards out-of-order responses. Entire classes of bugs are prevented by design.

Causality as data

trace() answers “why didn’t my update happen?” with plain JSON: every write, who wrote it, what re-ran. No devtools UI required.

Actionable errors

Stable error codes with the fix in the message. An exception in one expression is contained, so the rest of the page keeps updating.

For agents

Designed for agent-authored code

An agent reads llms.txt (~2k tokens, the complete API), generates a component, and verifies it with verify() in a single loop. On failure, errors carry stable codes and trace() reports the causality.

How agents use LemonadeJS
trace()
> count.value++
write  counter.s0   old: 0  value: 1
run    counter#slot   cause: counter.s0
> trace()  // causality, as plain JSON

43 blocks, every one contract-verified

The Studio: datagrids, calendars, modals, published with their schema and their proof. Explore the catalog

Battle-tested across the Jspreadsheet ecosystem

LemonadeJS powers extensions shipped with our commercial products. Not a side project: production code, maintained by the team behind the suite.

Your agent reads the whole API in 2k tokens.
Then verify proves the code it wrote.

Point it at llms.txt and start building. No tutorial, no scaffold, no afternoon spent reading.