page.mdx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. export const metadata = { title: "Schemas" }
  2. # Schemas
  3. Schemas define the structure and validation rules for your UI specs.
  4. ## What is a Schema?
  5. A schema defines the JSON structure that describes your UI. It includes:
  6. - **Element structure** — How components are nested and referenced
  7. - **Property types** — What props each component accepts
  8. - **Data binding syntax** — How to reference dynamic data
  9. - **Action format** — How user interactions are defined
  10. ## Schema-Agnostic by Design
  11. json-render can work with any JSON schema. `@json-render/core` provides the primitives to define catalogs and renderers for any format:
  12. - **@json-render/react** — The built-in flat element tree schema
  13. - **[A2UI](/docs/a2ui)** — Google's Agent-to-User Interaction protocol
  14. - **[Adaptive Cards](/docs/adaptive-cards)** — Microsoft's platform-agnostic UI format
  15. - **AG-UI** — CopilotKit's Agent User Interaction Protocol
  16. - **OpenAPI/Swagger** — API documentation schemas for dynamic forms
  17. - **Custom schemas** — Design your own format tailored to your domain
  18. See the [Custom Schema guide](/docs/custom-schema) to learn how to implement support for any schema.
  19. ## Built-in Schema
  20. `@json-render/react` uses a flat element tree schema with a root key and elements map:
  21. ```json
  22. {
  23. "root": "card-1",
  24. "elements": {
  25. "card-1": {
  26. "type": "Card",
  27. "props": { "title": "Dashboard" },
  28. "children": ["text-1", "button-1"]
  29. },
  30. "text-1": {
  31. "type": "Text",
  32. "props": { "content": "Welcome, $data.user.name" },
  33. "children": []
  34. },
  35. "button-1": {
  36. "type": "Button",
  37. "props": { "label": "Click me" },
  38. "children": []
  39. }
  40. }
  41. }
  42. ```
  43. ## Schema Components
  44. ### Element Structure
  45. In the built-in schema, each element in the elements map has this structure:
  46. ```typescript
  47. interface Element {
  48. type: string; // Component type from catalog
  49. props: Record<string, any>; // Component properties
  50. children: string[]; // Array of child element keys
  51. visible?: VisibilityRule; // Conditional display
  52. }
  53. ```
  54. ### Data Binding Syntax
  55. Reference dynamic data using the `$data` prefix in props:
  56. ```json
  57. {
  58. "type": "Text",
  59. "props": {
  60. "content": "$data.user.name",
  61. "count": "$data.items.length"
  62. },
  63. "children": []
  64. }
  65. ```
  66. ### Action Format
  67. Actions are defined in the catalog and referenced from components. The renderer handles action execution:
  68. ```typescript
  69. // In your catalog
  70. actions: {
  71. navigate: {
  72. params: z.object({ url: z.string() }),
  73. description: 'Navigate to a URL',
  74. },
  75. apiCall: {
  76. params: z.object({
  77. endpoint: z.string(),
  78. method: z.enum(['GET', 'POST', 'PUT', 'DELETE']),
  79. }),
  80. description: 'Make an API request',
  81. },
  82. }
  83. ```
  84. ## Custom Schemas
  85. `@json-render/core` is schema-agnostic. You can define any JSON structure:
  86. ```typescript
  87. import { z } from 'zod';
  88. // Define your own element schema
  89. const MyElementSchema = z.object({
  90. component: z.string(),
  91. settings: z.record(z.unknown()),
  92. nested: z.array(z.lazy(() => MyElementSchema)).optional(),
  93. });
  94. // Define your own data binding format
  95. const BoundValue = z.object({
  96. literal: z.string().optional(),
  97. path: z.string().optional(), // e.g., "/users/0/name"
  98. });
  99. // Define your own action format
  100. const ActionSchema = z.object({
  101. name: z.string(),
  102. context: z.record(z.unknown()).optional(),
  103. });
  104. ```
  105. ## Schema vs Catalog
  106. The schema and catalog work together but serve different purposes:
  107. - **Schema** — Defines the JSON structure (how elements are organized)
  108. - **Catalog** — Defines available components and their props (what can be used)
  109. The schema is the grammar; the catalog is the vocabulary.
  110. ## Next
  111. Learn about [specs](/docs/specs) — the actual JSON documents that describe your UI.