The End of Hallucinated Interfaces: Inside vercel-labs/json-render

Why generating raw React code is a dead end for AI agents, and how a strict JSON grammar is finally making Generative UI safe for production.

6 min read · vercel-labs/json-render

A split scene showing a mechanical hand painting a chaotic mural on the left, and a precise drafting machine placing geometric blocks into a grid on the right. This illustrates the shift from unconstrained code generation to structured UI composition.
Generative UI is rapidly moving away from raw code generation toward strict, schema-driven composition.
Portrait of Chris McKenzie

RUG constrains the model to only the UI components you explicitly give it. Components you’ve built, tested, and QA’d. The AI decides which to use. You get dynamic, AI-driven layout without giving up ownership of what actually renders.

— Chris McKenzie, Medium
Key Takeaways

The Problem with String-Based UI

The first wave of AI-generated user interfaces relied on a simple but flawed premise. Developers asked large language models to write raw HTML, Tailwind classes, or React components as plain text strings. While this works for rapid prototyping, it becomes a liability in production environments.

Unconstrained generation is inherently brittle. When a model is free to write any code it wants, it will inevitably hallucinate invalid syntax, invent non-existent props, or break brand guidelines. Worse, piping raw, AI-generated strings directly into a browser DOM introduces severe security risks and layout instability.

Restrictive UI Generation

The solution to AI hallucinations is not to build a smarter model. The solution is to remove the model's ability to write code entirely. This paradigm is known as Restrictive UI Generation (RUG), and it is the foundation of the json-render framework.

Instead of acting as a programmer typing out React components, the AI acts as a composer filling out a strict, pre-approved form. The framework forces the model to communicate using a predefined JSON grammar. If the AI attempts to use a component that does not exist, or passes a string to a property that requires a number, the validation layer safely catches the error before it ever reaches the user.

A close-up of a heavy industrial funnel catching jagged alphabet soup debris while allowing smooth spheres to pass through. This represents the strict validation layer catching AI hallucinations.
By passing AI output through strict schema validation, invalid properties and hallucinated syntax are caught before rendering.

Catalog, Registry, and Spec

To enforce these boundaries, json-render splits the UI rendering process into three distinct pillars. This separation of concerns ensures that the AI only handles abstract logic while the host application retains complete control over the actual pixels.

The Catalog acts as the vocabulary. It is a collection of Zod schemas that define exactly which components are available and what properties they accept. These schemas are fed directly into the LLM's system prompt.

The Spec is the instance. It is the flat JSON object streamed back by the AI, containing a root element and an element map. Because it is flat rather than deeply nested, it is highly resilient to the partial updates common in LLM streaming.

A five-step interactive pipeline showing how a natural language prompt becomes safe UI. Step 1: User prompt and Zod Catalog rules enter the LLM node. Step 2: The LLM streams a JSON patch outlining an abstract component. Step 3: The patch hits a Zod validation gate which flashes green to indicate a valid schema match. Step 4: The validated JSON passes to a Registry node which maps the abstract component ID to a concrete React component. Step 5: The final rendered UI updates on a simulated screen.

Finally, the Registry serves as the concrete implementation. It maps the abstract names defined in the Catalog (such as a generic "Button") to the actual framework-specific code (like a styled React component). The AI never sees or touches the implementation details.

The state the model generates (communicated as JSON) is the sole input to the renderer, which maps that state to your components and data.

— Chris McKenzie, Medium

Write Once, Render Anywhere

By abstracting the UI into a pure JSON spec, the framework unlocks a powerful cross-platform capability. Because the AI is not generating framework-specific code, the exact same AI output can be piped into entirely different environments.

A single generated payload can be rendered as a React web application, a Vue dashboard, or a React Native mobile screen. The framework even supports specialized renderers, allowing developers to turn the same JSON spec into a static PDF document or a dynamic Remotion video. The AI simply describes the intent, and the platform-specific Registry handles the execution.

A single beam of light entering a glass prism and splitting into a printed document, a mobile screen, and a desktop monitor. This illustrates the framework's ability to render one JSON spec across multiple platforms.
An abstract JSON spec acts as a universal intermediate representation, allowing the same AI output to render natively across web, mobile, and print.

Code Generation vs. Schema Mapping

The distinction between traditional AI UI tools and the json-render approach comes down to control. Tools that generate raw code are optimized for developers building new applications from scratch. Schema mapping frameworks are designed for embedding dynamic, AI-driven features into existing, mature codebases.

Feature Unconstrained Generation (e.g. OpenUI) Schema Mapping (json-render)
Output Format Raw React, HTML, or Tailwind strings Strictly typed JSON objects
Security Risk High (Requires parsing arbitrary code) Low (Only approved components render)
Validation Post-generation syntax checks Pre-render Zod schema enforcement
Framework Lock-in Tied to the generated language Agnostic (React, Vue, Svelte, PDF)
Best Use Case Rapid prototyping and boilerplate creation Production features in existing apps

The era of treating language models as unsupervised junior developers writing raw DOM elements is coming to a close. By enforcing a strict boundary between AI intent and UI execution, frameworks like json-render are proving that generative interfaces can be both highly dynamic and entirely predictable.


Sources: