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

Schemas

Schemas define the structure and validation rules for your UI specs.

What is a Schema?

A schema defines the JSON structure that describes your UI. It includes:

Schema-Agnostic by Design

json-render can work with any JSON schema.{" "} @json-render/core provides the primitives to define catalogs and renderers for any format:

See the{" "} Custom Schema guide {" "} to learn how to implement support for any schema.

Built-in Schema

@json-render/react uses a flat element tree schema with a root key and elements map:

{`{ "root": "card-1", "elements": { "card-1": { "type": "Card", "props": { "title": "Dashboard" }, "children": ["text-1", "button-1"] }, "text-1": { "type": "Text", "props": { "content": "Welcome, $data.user.name" }, "children": [] }, "button-1": { "type": "Button", "props": { "label": "Click me" }, "children": [] } } }`}

Schema Components

Element Structure

In the built-in schema, each element in the elements map has this structure:

{`interface Element { type: string; // Component type from catalog props: Record; // Component properties children: string[]; // Array of child element keys visible?: VisibilityRule; // Conditional display }`}

Data Binding Syntax

Reference dynamic data using the{" "} $data prefix in props:

{`{ "type": "Text", "props": { "content": "$data.user.name", "count": "$data.items.length" }, "children": [] }`}

Action Format

Actions are defined in the catalog and referenced from components. The renderer handles action execution:

{`// In your catalog actions: { navigate: { params: z.object({ url: z.string() }), description: 'Navigate to a URL', }, apiCall: { params: z.object({ endpoint: z.string(), method: z.enum(['GET', 'POST', 'PUT', 'DELETE']), }), description: 'Make an API request', }, }`}

Custom Schemas

@json-render/core is schema-agnostic. You can define any JSON structure:

{`import { z } from 'zod'; // Define your own element schema const MyElementSchema = z.object({ component: z.string(), settings: z.record(z.unknown()), nested: z.array(z.lazy(() => MyElementSchema)).optional(), }); // Define your own data binding format const BoundValue = z.object({ literal: z.string().optional(), path: z.string().optional(), // e.g., "/users/0/name" }); // Define your own action format const ActionSchema = z.object({ name: z.string(), context: z.record(z.unknown()).optional(), });`}

Schema vs Catalog

The schema and catalog work together but serve different purposes:

The schema is the grammar; the catalog is the vocabulary.

Next

Learn about{" "} specs {" "} — the actual JSON documents that describe your UI.

); }