Overview
json-render is an open-source framework from Vercel Labs for generative UI: instead of asking a model to write component code, you ask it for JSON that can only describe components you already shipped. The workflow the project describes is AI, then json-render, then UI. A developer defines a catalog of allowed components and actions; the model produces a JSON spec constrained to that catalog; json-render maps the spec onto the real implementations. A generation that does not fit the catalog fails validation rather than rendering something unexpected.
The framework is split into a core package and one package per rendering target. @json-render/core holds the schemas, catalogs, AI prompts and expression evaluation, and the renderers cover web (React, Vue 3, Svelte 5, SolidJS), mobile (React Native), documents (PDF via react-pdf, email via react-email), video (Remotion), 3D (React Three Fiber), terminal UIs (Ink), and whole applications (Next.js and, since 0.21.0, TanStack Start). A companion @json-render/shadcn package ships 36 pre-built shadcn/ui components so a catalog can be useful on day one.
Specs are more than static markup. Props can reference application state through expressions such as { "$state": "/user/name" } or { "$computed": "functionName" }, elements can show or hide on state conditions, setState actions update the state model and re-evaluate anything that depends on it, and state watchers can fire custom actions on change. SpecStream utilities render progressively as the model streams its answer, so the interface fills in rather than appearing all at once.
What it does
- Catalog-constrained generation: defineCatalog declares the components and actions a model may use, with Zod prop schemas, so invalid output fails validation instead of rendering
- One spec, many targets: renderers for React, Vue 3, Svelte 5, SolidJS, React Native, React Three Fiber, Remotion video, PDF, email, HTML, Ink terminal UIs, Next.js and TanStack Start
- Data binding and state: props can reference state with $state and $computed expressions, conditional visibility, setState actions, and state watchers that trigger custom behaviour
- Progressive rendering: SpecStream renders a spec as the model streams it, instead of waiting for the full response
- Directives: ready-made utilities for date formatting, math, string manipulation and internationalisation, plus a custom directives API for your own JSON shapes
- 36 pre-built shadcn/ui components via @json-render/shadcn, and devtools panels for React, Vue, Svelte and Solid that map rendered DOM back to spec keys
Getting started
Install the core package plus the renderer you want, declare a catalog, implement the components behind it, then render a model-produced spec.
Install
Core plus a renderer. The shadcn package is optional and gives you 36 ready-made components.
# React with shadcn/ui components
npm install @json-render/core @json-render/react @json-render/shadcn
# Full Next.js apps
npm install @json-render/core @json-render/react @json-render/next
# Mobile
npm install @json-render/core @json-render/react-nativeDefine the catalog
The catalog is the contract with the model: it lists every component the model is allowed to use, with a Zod schema for the props and a description the model reads.
import { defineCatalog } from "@json-render/core";
import { z } from "zod";
const catalog = defineCatalog(schema, {
components: {
Card: {
props: z.object({ title: z.string() }),
description: "A card container",
},
Button: {
props: z.object({ label: z.string() }),
description: "Clickable button",
},
},
});Implement the components
defineRegistry binds each catalog entry to a real implementation. Components receive props and children, and call emit to raise the actions the catalog declared.
const { registry } = defineRegistry(catalog, {
components: {
Card: ({ props, children }) => (
<div className="card">
<h3>{props.title}</h3>
{children}
</div>
),
Button: ({ props, emit }) => (
<button onClick={() => emit("press")}>{props.label}</button>
),
},
});Render the model's spec
Pass the JSON the model produced and the registry to the renderer. Nothing outside the catalog can reach the screen.
<Renderer spec={spec} registry={registry} />Commands and code are distilled from the project's own documentation — always check the official repo for the latest.
When to use it
- Build a chat or agent surface where answers come back as real charts, forms, tables and cards instead of markdown
- Ship personalised dashboards and onboarding flows that a model assembles per user from components your design system already owns
- Generate the same spec into different targets, for example a web page, a PDF report and an email, without re-authoring the layout
- Stand up whole routed applications from a spec using the Next.js or TanStack Start renderers, with file-based routes and server rendering
How json-render compares
json-render alongside other open-source generative ui sdks tools AI/TLDR tracks, ranked by GitHub stars.
| Tool | Stars | What it does |
|---|---|---|
| CopilotKit | ★ 37.4k | A frontend framework for adding in-app AI copilots and agent-driven generative UI to React and other apps, and the maker of the AG-UI protocol. |
| Vercel AI SDK | ★ 26.9k | A TypeScript toolkit for building AI apps and agents that includes streaming helpers and generative-UI features for rendering model output as React components. |
| OpenUI | ★ 22.6k | OpenUI lets you describe a UI in plain language, see it rendered live, ask for changes, and convert the result to React, Svelte, or Web Components. |
| AG-UI Protocol | ★ 16k | An open protocol that standardizes how AI agents stream events and UI to frontend applications, with SDKs across multiple languages and frameworks. |
| assistant-ui | ★ 12.2k | A TypeScript/React library of composable chat primitives for building AI chat apps that can render tool calls and JSON as interactive React components. |
| Tambo | ★ 11.2k | A generative UI SDK for React where you register components with Zod schemas and an agent picks the right one and streams its props to the user. |
| OpenUI (Thesys) | ★ 9.8k | An open standard and runtime for generative UI that uses a compact streaming language to let models emit interactive charts, forms, tables, and cards. |
| json-render | — | Let a model write JSON, not components, and render it with your own UI |