export const metadata = { title: "Specs" } # 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](/docs/schemas) and uses components from a [catalog](/docs/catalog). Specs can be: - Generated by AI in real-time - Stored in a database - Streamed progressively from a server - Hand-authored as JSON files 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: ```json { "root": "card-1", "elements": { "card-1": { "type": "Card", "props": { "title": "Welcome" }, "children": ["text-1"] }, "text-1": { "type": "Text", "props": { "content": "Hello, $data.user.name!" }, "children": [] } } } ``` ### Complex Spec A more complex spec with multiple nested elements: ```json { "root": "card-1", "elements": { "card-1": { "type": "Card", "props": { "title": "User Profile", "padding": "md" }, "children": ["row-1", "button-1"] }, "row-1": { "type": "Row", "props": { "gap": "md" }, "children": ["avatar-1", "stack-1"] }, "avatar-1": { "type": "Avatar", "props": { "src": "$data.user.avatar", "alt": "$data.user.name" }, "children": [] }, "stack-1": { "type": "Stack", "props": { "gap": "sm" }, "children": ["name-text", "email-text"] }, "name-text": { "type": "Text", "props": { "content": "$data.user.name", "variant": "heading" }, "children": [] }, "email-text": { "type": "Text", "props": { "content": "$data.user.email", "variant": "caption" }, "children": [] }, "button-1": { "type": "Button", "props": { "label": "Edit Profile" }, "children": [] } } } ``` ### Block-Level Spec A high-level spec using semantic blocks for page layouts: ```json { "root": "page", "elements": { "page": { "type": "Page", "props": {}, "children": ["header", "hero", "features", "footer"] }, "header": { "type": "Header", "props": { "logo": "/logo.svg", "navItems": ["Products", "Pricing", "Docs"] }, "children": [] }, "hero": { "type": "Hero", "props": { "title": "Build UIs with JSON", "subtitle": "Let AI generate your interfaces", "ctaLabel": "Get Started", "ctaHref": "/docs" }, "children": [] }, "features": { "type": "Features", "props": { "columns": 3 }, "children": ["feature-1", "feature-2", "feature-3"] }, "feature-1": { "type": "Feature", "props": { "icon": "zap", "title": "Fast", "description": "Render UIs in milliseconds" }, "children": [] }, "feature-2": { "type": "Feature", "props": { "icon": "shield", "title": "Secure", "description": "Validate all specs against your catalog" }, "children": [] }, "feature-3": { "type": "Feature", "props": { "icon": "sparkles", "title": "AI-Ready", "description": "Generate prompts from your catalog" }, "children": [] }, "footer": { "type": "Footer", "props": { "copyright": "2025 Acme Inc", "links": ["Privacy", "Terms", "Contact"] }, "children": [] } } } ``` ## Spec Anatomy ### Root and Elements Every spec has a `root` key pointing to the entry element, and an `elements` map containing all elements: ```json { "root": "card-1", "elements": { "card-1": { "type": "Card", "props": { "title": "My Card" }, "children": ["text-1"] }, "text-1": { ... } } } ``` ### Element Structure Each element in the map has a consistent shape: ```json { "type": "ComponentName", "props": { "label": "Hello" }, "children": ["child-1", "child-2"] } ``` - `type` — Component type from your catalog - `props` — Component properties - `children` — Array of child element keys ### Dynamic Data Props can reference data using `$data` paths: ```json { "type": "Metric", "props": { "label": "Total Revenue", "value": "$data.metrics.revenue", "change": "$data.metrics.revenueChange" }, "children": [] } ``` ### Conditional Visibility Control when elements appear using the `visible` property: ```json { "type": "Alert", "props": { "message": "You have unsaved changes" }, "children": [], "visible": { "path": "$data.form.isDirty", "operator": "eq", "value": true } } ``` ## Working with Specs ### Rendering a Spec ```tsx import { Renderer } from '@json-render/react'; function MyApp({ spec, data }) { return ( ); } ``` ### Validating a Spec ```typescript 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: ```tsx import { useUIStream } from '@json-render/react'; function GenerativeUI() { const { spec, isStreaming } = useUIStream({ api: '/api/generate', }); return ( ); } ``` ## Spec Sources Specs can come from various sources: - **AI Generation** — LLMs generate specs based on prompts and catalog - **Database** — Store specs as JSON and load dynamically - **API Response** — Server returns specs based on user/context - **Static Files** — Pre-built specs for known UI patterns ## Next Learn about [catalogs](/docs/catalog) — the vocabulary of components available in your specs.