npx claudepluginhub yonatangross/orchestkit --plugin orkThis skill uses the workspace's default tool permissions.
json-render (Vercel Labs, 12.9K stars, Apache-2.0) is a framework for AI-safe generative UI. AI generates flat-tree JSON (or YAML) specs constrained to a developer-defined catalog — the catalog is the contract between your design system and AI output. If a component or prop is not in the catalog, AI cannot generate it.
Renders AI-generated JSON UI specs into type-safe components for React, Vue, Svelte, Solid, React Native, video, PDF, email, and more. Useful for generative UIs from prompts.
Renders JSON specs into React component trees using @json-render/react. Supports catalogs with Zod schemas, state providers, visibility conditions, and external stores like Zustand.
Generates JSON UI specs from predefined component catalogs for json-render framework, covering renderer selection (React, shadcn, React Native), catalog design, MCP Apps delivery, and GemSkills visual asset integration.
Share bugs, ideas, or general feedback.
json-render (Vercel Labs, 12.9K stars, Apache-2.0) is a framework for AI-safe generative UI. AI generates flat-tree JSON (or YAML) specs constrained to a developer-defined catalog — the catalog is the contract between your design system and AI output. If a component or prop is not in the catalog, AI cannot generate it.
| Category | Rules | Impact | When to Use |
|---|---|---|---|
| Catalog Definition | 1 | HIGH | Defining component catalogs with Zod |
| Prop Constraints | 1 | HIGH | Constraining AI-generated props for safety |
| shadcn Catalog | 1 | MEDIUM | Using pre-built shadcn components |
| Token Optimization | 1 | MEDIUM | Reducing token usage with YAML mode |
| Actions & State | 1 | MEDIUM | Adding interactivity to specs |
Total: 5 rules across 5 categories
<Render> component validates and renders each elementThe catalog is the safety boundary. AI can only reference types that exist in the catalog, and props are validated against Zod schemas at runtime. This prevents hallucinated components and invalid props from reaching the UI.
import { defineCatalog } from '@json-render/core'
import { z } from 'zod'
export const catalog = defineCatalog({
Card: {
props: z.object({
title: z.string(),
description: z.string().optional(),
}),
children: true,
},
Button: {
props: z.object({
label: z.string(),
variant: z.enum(['default', 'destructive', 'outline', 'ghost']),
}),
children: false,
},
StatGrid: {
props: z.object({
items: z.array(z.object({
label: z.string(),
value: z.string(),
trend: z.enum(['up', 'down', 'flat']).optional(),
})).max(20),
}),
children: false,
},
})
import type { CatalogComponents } from '@json-render/react'
import type { catalog } from './catalog'
export const components: CatalogComponents<typeof catalog> = {
Card: ({ title, description, children }) => (
<div className="rounded-lg border p-4">
<h3 className="font-semibold">{title}</h3>
{description && <p className="text-muted-foreground">{description}</p>}
{children}
</div>
),
Button: ({ label, variant }) => (
<button className={cn('btn', `btn-${variant}`)}>{label}</button>
),
StatGrid: ({ items }) => (
<div className="grid grid-cols-3 gap-4">
{items.map((item) => (
<div key={item.label}>
<span>{item.label}</span>
<strong>{item.value}</strong>
</div>
))}
</div>
),
}
import { Render } from '@json-render/react'
import { catalog } from './catalog'
import { components } from './components'
function App({ spec }: { spec: JsonRenderSpec }) {
return <Render catalog={catalog} components={components} spec={spec} />
}
The JSON spec is a flat tree — no nesting, just IDs and references. Load references/spec-format.md for full documentation.
{
"root": "card-1",
"elements": {
"card-1": {
"type": "Card",
"props": { "title": "Dashboard" },
"children": ["chart-1", "btn-1"]
},
"btn-1": {
"type": "Button",
"props": { "label": "View Details", "variant": "default" }
}
}
}
{
"root": "card-1",
"elements": {
"card-1": {
"type": "Card",
"props": { "title": "Dashboard" },
"children": ["chart-1", "btn-1"],
"on": { "press": { "action": "setState", "path": "/view", "value": "detail" } },
"watch": { "/data": { "action": "load_data", "url": "/api/stats" } }
}
},
"state": { "/activeTab": "overview" }
}
Load rules/action-state.md for event handlers, watch bindings, and state adapter patterns.
For one-shot (non-streaming) generation, YAML specs use ~30% fewer tokens than JSON:
root: card-1
elements:
card-1:
type: Card
props:
title: Dashboard
children: [chart-1, btn-1]
btn-1:
type: Button
props:
label: View Details
variant: default
Use JSON for streaming (JSON Patch RFC 6902 over JSONL requires JSON). Use YAML for one-shot generation where token cost matters. Load rules/token-optimization.md for selection criteria.
json-render supports progressive rendering during streaming. As the AI generates spec elements, they render immediately — the user sees the UI building in real-time. This uses JSON Patch (RFC 6902) operations streamed over JSONL:
{"op":"add","path":"/elements/card-1","value":{"type":"Card","props":{"title":"Dashboard"},"children":[]}}
{"op":"add","path":"/elements/btn-1","value":{"type":"Button","props":{"label":"Save","variant":"default"}}}
{"op":"add","path":"/elements/card-1/children/-","value":"btn-1"}
Elements render as soon as their props are complete — no waiting for the full spec.
The @json-render/shadcn package provides a production-ready catalog of 29 components with Zod schemas already defined. Load rules/shadcn-catalog.md for the full component list and when to extend vs use as-is.
import { shadcnCatalog, shadcnComponents } from '@json-render/shadcn'
import { mergeCatalogs } from '@json-render/core'
// Use as-is
<Render catalog={shadcnCatalog} components={shadcnComponents} spec={spec} />
// Or merge with custom components
const catalog = mergeCatalogs(shadcnCatalog, customCatalog)
23 packages covering web, mobile, 3D, codegen, and state management. Load references/package-ecosystem.md for the full list organized by category.
Use json-render when:
Do NOT use json-render when:
If you have existing custom generative UI (hand-rolled JSON-to-component mapping), load references/migration-from-genui.md for a step-by-step migration guide.
How to define catalogs with defineCatalog() and Zod schemas.
| Rule | File | Key Pattern |
|---|---|---|
| Catalog Definition | rules/catalog-definition.md | defineCatalog with Zod schemas, children types |
Constraining props to prevent AI hallucination.
| Rule | File | Key Pattern |
|---|---|---|
| Prop Constraints | rules/prop-constraints.md | z.enum, z.string().max(), z.array().max() |
Using the 29 pre-built shadcn components.
| Rule | File | Key Pattern |
|---|---|---|
| shadcn Catalog | rules/shadcn-catalog.md | @json-render/shadcn components and extension |
Choosing JSON vs YAML for token efficiency.
| Rule | File | Key Pattern |
|---|---|---|
| Token Optimization | rules/token-optimization.md | YAML for one-shot, JSON for streaming |
Adding interactivity with events, watchers, and state.
| Rule | File | Key Pattern |
|---|---|---|
| Action & State | rules/action-state.md | on events, watch reactivity, state adapters |
| Decision | Recommendation |
|---|---|
| Custom vs shadcn catalog | Start with shadcn, extend with custom types for domain-specific components |
| JSON vs YAML spec format | YAML for one-shot (30% fewer tokens), JSON for streaming |
| Zod constraint strictness | Tighter is better — use z.enum over z.string, z.array().max() over unbounded |
| State management adapter | Match your app's existing state library (Zustand, Redux, Jotai, XState) |
z.any() or z.unknown() in catalog props — defeats the purpose of catalog constraints, AI can generate anythingmergeCatalogs() when combining shadcn + custom — manual merging loses type safety.max() on arrays — AI can generate unbounded lists that break layoutsork:ai-ui-generation — AI-assisted UI generation patterns for v0, Bolt, Cursorork:ui-components — shadcn/ui component patterns and CVA variantsork:component-search — Finding and evaluating React/Vue componentsork:design-to-code — Converting designs to production code