Initial commit: json-render crepes demo
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled

This commit is contained in:
2026-02-09 07:30:54 +01:00
commit 9b750238c2
35 changed files with 9237 additions and 0 deletions

228
HOW_IT_WORKS.md Normal file
View File

@@ -0,0 +1,228 @@
# 🎯 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`:
```typescript
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`:
```typescript
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`:
```typescript
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`:
```typescript
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:
```jsx
<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
```typescript
// 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:
1. **Safe** - Can't inject malicious code
2. **Type-safe** - Matches your schemas
3. **Beautiful** - Uses your styled components
4. **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! 🚀