Files
crepes-demo/HOW_IT_WORKS.md
OpenClaw 9b750238c2
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
Initial commit: json-render crepes demo
2026-02-09 07:30:54 +01:00

229 lines
5.2 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🎯 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! 🚀