| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- export const metadata = { title: "Schemas" }
- # 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:
- - **Element structure** — How components are nested and referenced
- - **Property types** — What props each component accepts
- - **Data binding syntax** — How to reference dynamic data
- - **Action format** — How user interactions are defined
- ## 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:
- - **@json-render/react** — The built-in flat element tree schema
- - **[A2UI](/docs/a2ui)** — Google's Agent-to-User Interaction protocol
- - **[Adaptive Cards](/docs/adaptive-cards)** — Microsoft's platform-agnostic UI format
- - **AG-UI** — CopilotKit's Agent User Interaction Protocol
- - **OpenAPI/Swagger** — API documentation schemas for dynamic forms
- - **Custom schemas** — Design your own format tailored to your domain
- See the [Custom Schema guide](/docs/custom-schema) 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:
- ```json
- {
- "root": "card-1",
- "elements": {
- "card-1": {
- "type": "Card",
- "props": { "title": "Dashboard" },
- "children": ["text-1", "button-1"]
- },
- "text-1": {
- "type": "Text",
- "props": { "content": { "$state": "/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:
- ```typescript
- interface Element {
- type: string; // Component type from catalog
- props: Record<string, any>; // Component properties
- children: string[]; // Array of child element keys
- visible?: VisibilityCondition; // Conditional display
- }
- ```
- ### Data Binding Syntax
- Reference dynamic data using `$state` expressions in props. The value is a JSON Pointer path into the state model:
- ```json
- {
- "type": "Text",
- "props": {
- "content": { "$state": "/user/name" },
- "count": { "$state": "/items/count" }
- },
- "children": []
- }
- ```
- json-render also supports `$item` and `$index` expressions for lists, two-way binding via `$bindState` / `$bindItem`, and conditional props. See [Data Binding](/docs/data-binding) for the full reference.
- ### Action Format
- Actions are defined in the catalog and referenced from components. The renderer handles action execution:
- ```typescript
- // 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:
- ```typescript
- 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(),
- source: 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:
- - **Schema** — Defines the JSON structure (how elements are organized)
- - **Catalog** — Defines available components and their props (what can be used)
- The schema is the grammar; the catalog is the vocabulary.
- ## Next
- Learn about [specs](/docs/specs) — the actual JSON documents that describe your UI.
|