← all notes

Take the manifest, not the framework

august 2026 · 3 minute read · design-systems, agents

An agent will not tell you it is guessing. It writes a prop that looks plausible, and the markup renders without complaint.

Meta’s Astryx, an open-sourced React design system, had me weighing a stack switch for about as long as it took to write the advisory down. I decided against and stayed on Vue, Nuxt and Reka, but took a file rather than the framework.

Three things pulled at me: it was easy to edit, it claimed built for agents, and it shipped with a long list of components. My tokens are already CSS custom properties, so the first was mostly there already; the second was a project rather than a rewrite; the third, component count, was the only gap. A stack switch is a high-cost, low-reversibility bet, and marginal gain is the wrong way to advance. The one genuinely strong reason to touch React is React Native, and that is additive and I'm already working with capacitor.

Astryx dumps a JSON manifest from a single command, carrying every component’s props, slots, events and composition hints for an agent to read instead of guess. A thin MCP server sits over it, exposing two tools, search and get. A declarative theme config, one file, pushes colour, type, spacing and motion everywhere without anyone forking a component. The manifest was the headline at the time, written up as the thing that stops agents hallucinating UI props.

A component library doesn’t move between stacks and a Vue button can’t magically become a React button. Documentation that a machine can understand moves perfectly well because a JSON manifest is agnostic to the underlying component languages. The framework itself was the part I was tempted by but ultimately the least important.

The final decision was to keep the stack and take the shape – Reka gives me somewhere around 50 headless primitives to build on, and Nerv wraps those and adds compositions of its own on top; Astryx counts 150 components. A documented 50 beats an undocumented 150, because what makes a component useful to an agent is whether it can be trusted without being read first. The manifest became the keystone, with the thin MCP and the theme config built around it: three phases, seven tasks, all shipped.

The manifest is generated from the Nerv source at build time, since defineProps, JSDoc, slots and emits already carry the metadata, so there is no hand-maintained copy to drift away from the code. It covers 82 components, each entry carrying props, slots, emits, and tokens mapped to the theme key that drives them. The two read-only tools sit over it in an MCP server wired into the agent fleet and into Claude Desktop, and get is forgiving about the prefix an agent guesses: ask for NervButton and you get NButton back.

The coverage checker that reports on all this is not clean, and I am not going to pretend otherwise. Much of Nerv predates the JSDoc convention the manifest depends on, so parts of the library come back as gaps rather than entries, and closing that is a slow, ongoing job rather than a phase I could tick off. A checker that reports nothing wrong on its first run is not measuring anything.

Growing the component count is still a track I am pushing along, but it stopped being the number I look at. The one that decides whether Nerv is usable by the fleet is the share of it an agent can pick up without guessing, and I would rather hold a small number that is true than a large one nobody has ever checked.