Back to Articles
ReactArchitectureAI

We Decomposed React into Declarative State Mutations

January 15, 20258 min read

Most AI coding tools generate code as text. They output JavaScript strings, hope the syntax is valid, and pray the imports resolve. We took a different approach: we represent React components as structured data.

The Problem with Code Generation

When an AI generates code, several things can go wrong:

  • Syntax errors from unclosed brackets or missing semicolons
  • Import statements that reference non-existent modules
  • Type mismatches that only surface at compile time
  • Formatting inconsistencies across generated files

The traditional fix is to add more validation layers, linters, and compilation steps. But each layer adds latency between "AI writes code" and "user sees result."

Components as Data Structures

Instead of generating code strings, our AI manipulates a typed data structure called ComponentState. Here's what a component looks like in our system:

type ComponentNode = {
  id: string;
  componentType: string | null;  // 'div', 'Button', etc.
  props: Record<string, PropValue>;
  styles?: StyleObject;
  children?: ChildNode[];
  state: {
    declarations: Record<string, Declaration>;
  };
};

When the AI wants to add a button, it doesn't write <button onClick={...}>. It sends a state mutation:

setComponent('button-1', {
  id: 'button-1',
  componentType: 'button',
  props: {
    onClick: { type: 'expression', value: 'handleClick' }
  },
  children: [{ type: 'text', value: 'Click me' }]
});

Why This Matters

1. No Syntax Errors

The AI can't produce invalid syntax because it's not writing text. It's setting properties on a typed object. TypeScript catches structural issues at the mutation layer, not after code generation.

2. Instant Previews

There's no build step between state change and render. When the AI updates ComponentState, React re-renders immediately. Users see changes in real-time, not after a compilation cycle.

3. Reduced Round-Trips

Traditional AI coding: Generate code โ†’ Parse โ†’ Compile โ†’ Bundle โ†’ Render โ†’ Show errors โ†’ Regenerate. Our approach: Mutate state โ†’ Render. The feedback loop shrinks from seconds to milliseconds.

4. Reversible Changes

Every mutation can be undone. The AI doesn't need to "remember" what it changedโ€”the state history is explicit. Users can scrub through AI changes like a timeline.

The Unified Declaration Model

We unified all module-level code into a single declarations map. Functions, variables, types, re-exportsโ€”they're all the same shape:

type Declaration = {
  type: 'function' | 'basic' | 'reexport';
  body?: string;           // For functions
  value?: any;             // For variables
  declarationKind?: 'const' | 'let' | 'interface';
  exported?: boolean | 'default';
};

This uniformity means the AI uses the same mental model for everything. Adding a useState hook, creating a utility function, or defining a TypeScript interfaceโ€”same operation, different properties.

What About Code Export?

The structured state serializes to standard React/TypeScript. When you export your project, we walk the component tree and emit idiomatic code. The internal representation is an implementation detailโ€”your exported codebase looks hand-written.

The Bigger Picture

This architecture enables things that code generation can't:

  • Real-time collaboration โ€“ Multiple users edit the same state simultaneously
  • AI that learns from interactions โ€“ We track which mutations users keep vs. undo
  • Cross-component intelligence โ€“ The AI sees the whole app structure, not isolated files
  • Overnight improvements โ€“ The AI can optimize your app while you sleep

We didn't build another code generator. We built a compiler where the source language is English and the target is structured state. The code is just an export format.

Try it yourself

See declarative state mutations in action. Build something in plain English and watch it render instantly.

Start Building