Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
5.2 KiB
5.2 KiB
🎯 How json-render Works in This Demo
The Flow
User Prompt (in production)
↓
AI generates JSON spec (constrained to catalog)
↓
json-render Renderer component
↓
Beautiful React UI
Step-by-Step Example
1. Define Your Component Catalog
lib/catalog.ts:
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/react";
import { z } from "zod";
export const catalog = defineCatalog(schema, {
components: {
RecipeHeader: {
props: z.object({
title: z.string(),
chef: z.string(),
prepTime: z.string(),
}),
description: "Header with recipe info",
},
IngredientList: {
props: z.object({
title: z.string(),
ingredients: z.array(
z.object({
name: z.string(),
quantity: z.string(),
})
),
}),
description: "List of ingredients",
},
// ... more components
},
actions: {},
});
This is your guardrail: AI can only use these components.
2. Map Components to React
lib/registry.tsx:
import { defineRegistry } from "@json-render/react";
import { catalog } from "./catalog";
export const { registry } = defineRegistry(catalog, {
components: {
RecipeHeader: ({ props }) => (
<div className="bg-amber-50 p-8 rounded-2xl">
<h1 className="text-4xl font-bold">{props.title}</h1>
<span>👨🍳 Chef: {props.chef}</span>
<span>⏱️ Prep: {props.prepTime}</span>
</div>
),
IngredientList: ({ props }) => (
<div className="bg-green-50 p-6">
<h3>{props.title}</h3>
<ul>
{props.ingredients.map((ing, i) => (
<li key={i}>
{ing.quantity} {ing.name}
</li>
))}
</ul>
</div>
),
// ... more implementations
},
});
3. Create a JSON Spec
lib/recipes.ts:
const recipe = {
root: "root", // Start rendering from this element
elements: {
root: {
type: "RecipeCard", // Component from catalog
props: {
title: "Crêpes Suzette",
description: "Classic French dessert"
},
children: ["header", "ingredients"] // Refs to other elements
},
header: {
type: "RecipeHeader",
props: {
title: "Crêpes Suzette",
chef: "Auguste Escoffier",
prepTime: "45 minutes"
}
},
ingredients: {
type: "IngredientList",
props: {
title: "Ingredients",
ingredients: [
{ quantity: "200g", name: "Flour" },
{ quantity: "4", name: "Eggs" },
{ quantity: "500ml", name: "Milk" }
]
}
}
}
};
This is what AI generates (but here we've pre-written it for the demo).
4. Render with json-render
app/page.tsx:
import { Renderer } from "@json-render/react";
import { registry, Provider } from "@/lib/registry";
import { recipes } from "@/lib/recipes";
export default function Home() {
return (
<main>
{recipes.map((recipe, index) => (
<Provider key={index}>
<Renderer spec={recipe} registry={registry} />
</Provider>
))}
</main>
);
}
Magic happens here: The Renderer takes your spec + registry and outputs fully-styled React components!
What Gets Rendered
The spec above becomes:
<div className="bg-white p-8 rounded-2xl shadow-xl">
<h2>Crêpes Suzette</h2>
<p>Classic French dessert</p>
<div className="bg-amber-50 p-8 rounded-2xl">
<h1 className="text-4xl font-bold">Crêpes Suzette</h1>
<span>👨🍳 Chef: Auguste Escoffier</span>
<span>⏱️ Prep: 45 minutes</span>
</div>
<div className="bg-green-50 p-6">
<h3>Ingredients</h3>
<ul>
<li>200g Flour</li>
<li>4 Eggs</li>
<li>500ml Milk</li>
</ul>
</div>
</div>
Why This Matters
Without json-render:
- AI generates raw HTML/JSX → Security risk (XSS, code injection)
- No type safety → Runtime errors
- Unpredictable output → Broken UIs
With json-render:
- ✅ AI can only use predefined components (guardrailed)
- ✅ Zod schemas enforce type safety (predictable)
- ✅ Your React components control the rendering (safe)
- ✅ Stream rendering as AI generates (fast)
In Production with AI
// User types prompt
const userPrompt = "Show me a recipe for chocolate chip cookies";
// AI generates spec (using your catalog as context)
const aiGeneratedSpec = await ai.generate({
prompt: userPrompt,
catalog: catalog.prompt(), // Gives AI the component vocabulary
});
// Render safely
<Renderer spec={aiGeneratedSpec} registry={registry} />
Result: AI-generated UIs that are:
- Safe - Can't inject malicious code
- Type-safe - Matches your schemas
- Beautiful - Uses your styled components
- Fast - Streams as AI generates
The Power
You define the components once. Then:
- AI can generate infinite variations
- Users can describe UIs in natural language
- Your app stays safe and consistent
- No manual UI coding needed
That's json-render.
Check the full code in lib/ to see it in action! 🚀