Predictable. Guardrailed. Fast.
Let end users generate dashboards, widgets, apps, and data visualizations from prompts — safely constrained to components you define.
npm install @json-render/core @json-render/reactWhen users prompt for UI, you need guarantees. json-render gives AI a constrained vocabulary so output is always predictable:
- Guardrailed — AI can only use components in your catalog
- Predictable — JSON output matches your schema, every time
- Fast — Stream and render progressively as the model responds
import { createCatalog } from '@json-render/core';
import { z } from 'zod';
const catalog = createCatalog({
components: {
Card: {
props: z.object({ title: z.string() }),
hasChildren: true,
},
Metric: {
props: z.object({
label: z.string(),
valuePath: z.string(), // Binds to your data
format: z.enum(['currency', 'percent', 'number']),
}),
},
Button: {
props: z.object({
label: z.string(),
action: ActionSchema, // AI declares intent, you handle it
}),
},
},
actions: {
export_report: { description: 'Export dashboard to PDF' },
refresh_data: { description: 'Refresh all metrics' },
},
});const registry = {
Card: ({ element, children }) => (
<div className="card">
<h3>{element.props.title}</h3>
{children}
</div>
),
Metric: ({ element }) => {
const value = useDataValue(element.props.valuePath);
return <div className="metric">{format(value)}</div>;
},
Button: ({ element, onAction }) => (
<button onClick={() => onAction(element.props.action)}>
{element.props.label}
</button>
),
};import { DataProvider, ActionProvider, Renderer, useUIStream } from '@json-render/react';
function Dashboard() {
const { tree, send } = useUIStream({ api: '/api/generate' });
return (
<DataProvider initialData={{ revenue: 125000, growth: 0.15 }}>
<ActionProvider actions={{
export_report: () => downloadPDF(),
refresh_data: () => refetch(),
}}>
<input
placeholder="Create a revenue dashboard..."
onKeyDown={(e) => e.key === 'Enter' && send(e.target.value)}
/>
<Renderer tree={tree} components={registry} />
</ActionProvider>
</DataProvider>
);
}That's it. AI generates JSON, you render it safely.
Show/hide components based on data, auth, or complex logic:
{
"type": "Alert",
"props": { "message": "Error occurred" },
"visible": {
"and": [
{ "path": "/form/hasError" },
{ "not": { "path": "/form/errorDismissed" } }
]
}
}{
"type": "AdminPanel",
"visible": { "auth": "signedIn" }
}Actions with confirmation dialogs and callbacks:
{
"type": "Button",
"props": {
"label": "Refund Payment",
"action": {
"name": "refund",
"params": {
"paymentId": { "path": "/selected/id" },
"amount": { "path": "/refund/amount" }
},
"confirm": {
"title": "Confirm Refund",
"message": "Refund ${/refund/amount} to customer?",
"variant": "danger"
},
"onSuccess": { "set": { "/ui/success": true } },
"onError": { "set": { "/ui/error": "$error.message" } }
}
}
}{
"type": "TextField",
"props": {
"label": "Email",
"valuePath": "/form/email",
"checks": [
{ "fn": "required", "message": "Email is required" },
{ "fn": "email", "message": "Invalid email" }
],
"validateOn": "blur"
}
}| Package | Description |
|---|---|
@json-render/core |
Types, schemas, visibility, actions, validation |
@json-render/react |
React renderer, providers, hooks |
git clone https://github.com/vercel-labs/json-render
cd json-render
pnpm install
pnpm dev- http://localhost:3000 — Docs & Playground
- http://localhost:3001 — Example Dashboard
json-render/
├── packages/
│ ├── core/ → @json-render/core
│ └── react/ → @json-render/react
├── apps/
│ └── web/ → Docs & Playground site
└── examples/
└── dashboard/ → Example dashboard app
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ User Prompt │────▶│ AI + Catalog│────▶│ JSON Tree │
│ "dashboard" │ │ (guardrailed)│ │(predictable)│
└─────────────┘ └──────────────┘ └─────────────┘
│
┌──────────────┐ │
│ Your React │◀───────────┘
│ Components │ (streamed)
└──────────────┘
- Define the guardrails — what components, actions, and data bindings AI can use
- Users prompt — end users describe what they want in natural language
- AI generates JSON — output is always predictable, constrained to your catalog
- Render fast — stream and render progressively as the model responds
Apache-2.0