import Link from "next/link"; import { Code } from "@/components/code"; export const metadata = { title: "Specs | json-render", }; export default function SpecsPage() { return (

Specs

A spec is a JSON document that describes your UI.

What is a Spec?

A spec (specification) is the actual JSON that describes a UI. It conforms to a{" "} schema {" "} and uses components from a{" "} catalog . Specs can be:

json-render is schema-agnostic — your specs can follow any JSON structure you choose.

Example Specs

Simple Spec

A basic spec using the{" "} @json-render/react schema. Note the flat structure with a root{" "} key and elements map:

{`{ "root": "card-1", "elements": { "card-1": { "key": "card-1", "type": "Card", "props": { "title": "Welcome" }, "children": ["text-1"], "parentKey": "" }, "text-1": { "key": "text-1", "type": "Text", "props": { "content": "Hello, $data.user.name!" }, "children": [], "parentKey": "card-1" } } }`}

Complex Spec

A more complex spec with multiple nested elements:

{`{ "root": "card-1", "elements": { "card-1": { "key": "card-1", "type": "Card", "props": { "title": "User Profile", "padding": "md" }, "children": ["row-1", "button-1"], "parentKey": "" }, "row-1": { "key": "row-1", "type": "Row", "props": { "gap": "md" }, "children": ["avatar-1", "stack-1"], "parentKey": "card-1" }, "avatar-1": { "key": "avatar-1", "type": "Avatar", "props": { "src": "$data.user.avatar", "alt": "$data.user.name" }, "children": [], "parentKey": "row-1" }, "stack-1": { "key": "stack-1", "type": "Stack", "props": { "gap": "sm" }, "children": ["name-text", "email-text"], "parentKey": "row-1" }, "name-text": { "key": "name-text", "type": "Text", "props": { "content": "$data.user.name", "variant": "heading" }, "children": [], "parentKey": "stack-1" }, "email-text": { "key": "email-text", "type": "Text", "props": { "content": "$data.user.email", "variant": "caption" }, "children": [], "parentKey": "stack-1" }, "button-1": { "key": "button-1", "type": "Button", "props": { "label": "Edit Profile" }, "children": [], "parentKey": "card-1" } } }`}

Block-Level Spec

A high-level spec using semantic blocks for page layouts:

{`{ "root": "page", "elements": { "page": { "key": "page", "type": "Page", "props": {}, "children": ["header", "hero", "features", "footer"], "parentKey": "" }, "header": { "key": "header", "type": "Header", "props": { "logo": "/logo.svg", "navItems": ["Products", "Pricing", "Docs"] }, "children": [], "parentKey": "page" }, "hero": { "key": "hero", "type": "Hero", "props": { "title": "Build UIs with JSON", "subtitle": "Let AI generate your interfaces", "ctaLabel": "Get Started", "ctaHref": "/docs" }, "children": [], "parentKey": "page" }, "features": { "key": "features", "type": "Features", "props": { "columns": 3 }, "children": ["feature-1", "feature-2", "feature-3"], "parentKey": "page" }, "feature-1": { "key": "feature-1", "type": "Feature", "props": { "icon": "zap", "title": "Fast", "description": "Render UIs in milliseconds" }, "children": [], "parentKey": "features" }, "feature-2": { "key": "feature-2", "type": "Feature", "props": { "icon": "shield", "title": "Secure", "description": "Validate all specs against your catalog" }, "children": [], "parentKey": "features" }, "feature-3": { "key": "feature-3", "type": "Feature", "props": { "icon": "sparkles", "title": "AI-Ready", "description": "Generate prompts from your catalog" }, "children": [], "parentKey": "features" }, "footer": { "key": "footer", "type": "Footer", "props": { "copyright": "2025 Acme Inc", "links": ["Privacy", "Terms", "Contact"] }, "children": [], "parentKey": "page" } } }`}

Spec Anatomy

Root and Elements

Every spec has a root key pointing to the entry element, and an{" "} elements map containing all elements:

{`{ "root": "card-1", "elements": { "card-1": { "key": "card-1", "type": "Card", "props": { "title": "My Card" }, "children": ["text-1"], "parentKey": "" }, "text-1": { ... } } }`}

Element Structure

Each element in the map has a consistent shape:

{`{ "key": "unique-id", "type": "ComponentName", "props": { "label": "Hello" }, "children": ["child-1", "child-2"], "parentKey": "parent-id" }`}

Dynamic Data

Props can reference data using{" "} $data paths:

{`{ "key": "metric-1", "type": "Metric", "props": { "label": "Total Revenue", "value": "$data.metrics.revenue", "change": "$data.metrics.revenueChange" }, "children": [], "parentKey": "dashboard" }`}

Conditional Visibility

Control when elements appear using the{" "} visible property:

{`{ "key": "alert-1", "type": "Alert", "props": { "message": "You have unsaved changes" }, "children": [], "parentKey": "form", "visible": { "path": "$data.form.isDirty", "operator": "eq", "value": true } }`}

Working with Specs

Rendering a Spec

{`import { Renderer } from '@json-render/react'; function MyApp({ spec, data }) { return ( ); }`}

Validating a Spec

{`import { validate } from '@json-render/core'; const result = validate(spec, catalog); if (!result.valid) { console.error('Invalid spec:', result.errors); }`}

Streaming Specs

Specs can be streamed incrementally for progressive rendering:

{`import { useUIStream } from '@json-render/react'; function GenerativeUI() { const { spec, isStreaming } = useUIStream({ api: '/api/generate', }); return ( ); }`}

Spec Sources

Specs can come from various sources:

Next

Learn about{" "} catalogs {" "} — the vocabulary of components available in your specs.

); }