page.tsx 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. import Link from "next/link";
  2. import { Code } from "@/components/code";
  3. export const metadata = {
  4. title: "Schemas | json-render",
  5. };
  6. export default function SchemasPage() {
  7. return (
  8. <article>
  9. <h1 className="text-3xl font-bold mb-4">Schemas</h1>
  10. <p className="text-muted-foreground mb-8">
  11. Schemas define the structure and validation rules for your UI specs.
  12. </p>
  13. <h2 className="text-xl font-semibold mt-12 mb-4">What is a Schema?</h2>
  14. <p className="text-sm text-muted-foreground mb-4">
  15. A schema defines the JSON structure that describes your UI. It includes:
  16. </p>
  17. <ul className="list-disc list-inside text-sm text-muted-foreground space-y-1 mb-4">
  18. <li>
  19. <strong className="text-foreground">Element structure</strong> — How
  20. components are nested and referenced
  21. </li>
  22. <li>
  23. <strong className="text-foreground">Property types</strong> — What
  24. props each component accepts
  25. </li>
  26. <li>
  27. <strong className="text-foreground">Data binding syntax</strong> — How
  28. to reference dynamic data
  29. </li>
  30. <li>
  31. <strong className="text-foreground">Action format</strong> — How user
  32. interactions are defined
  33. </li>
  34. </ul>
  35. <h2 className="text-xl font-semibold mt-12 mb-4">
  36. Schema-Agnostic by Design
  37. </h2>
  38. <p className="text-sm text-muted-foreground mb-4">
  39. json-render can work with any JSON schema.{" "}
  40. <code className="text-foreground">@json-render/core</code> provides the
  41. primitives to define catalogs and renderers for any format:
  42. </p>
  43. <ul className="list-disc list-inside text-sm text-muted-foreground space-y-1 mb-4">
  44. <li>
  45. <strong className="text-foreground">@json-render/react</strong> — The
  46. built-in flat element tree schema
  47. </li>
  48. <li>
  49. <strong className="text-foreground">
  50. <Link href="/docs/a2ui" className="hover:underline">
  51. A2UI
  52. </Link>
  53. </strong>{" "}
  54. — Google{"'"}s Agent-to-User Interaction protocol
  55. </li>
  56. <li>
  57. <strong className="text-foreground">
  58. <Link href="/docs/adaptive-cards" className="hover:underline">
  59. Adaptive Cards
  60. </Link>
  61. </strong>{" "}
  62. — Microsoft{"'"}s platform-agnostic UI format
  63. </li>
  64. <li>
  65. <strong className="text-foreground">AG-UI</strong> — CopilotKit{"'"}s
  66. Agent User Interaction Protocol
  67. </li>
  68. <li>
  69. <strong className="text-foreground">OpenAPI/Swagger</strong> — API
  70. documentation schemas for dynamic forms
  71. </li>
  72. <li>
  73. <strong className="text-foreground">Custom schemas</strong> — Design
  74. your own format tailored to your domain
  75. </li>
  76. </ul>
  77. <p className="text-sm text-muted-foreground mb-4">
  78. See the{" "}
  79. <Link
  80. href="/docs/custom-schema"
  81. className="text-foreground hover:underline"
  82. >
  83. Custom Schema guide
  84. </Link>{" "}
  85. to learn how to implement support for any schema.
  86. </p>
  87. <h2 className="text-xl font-semibold mt-12 mb-4">Built-in Schema</h2>
  88. <p className="text-sm text-muted-foreground mb-4">
  89. <code className="text-foreground">@json-render/react</code> uses a flat
  90. element tree schema with a root key and elements map:
  91. </p>
  92. <Code lang="json">{`{
  93. "root": "card-1",
  94. "elements": {
  95. "card-1": {
  96. "type": "Card",
  97. "props": { "title": "Dashboard" },
  98. "children": ["text-1", "button-1"]
  99. },
  100. "text-1": {
  101. "type": "Text",
  102. "props": { "content": "Welcome, $data.user.name" },
  103. "children": []
  104. },
  105. "button-1": {
  106. "type": "Button",
  107. "props": { "label": "Click me" },
  108. "children": []
  109. }
  110. }
  111. }`}</Code>
  112. <h2 className="text-xl font-semibold mt-12 mb-4">Schema Components</h2>
  113. <h3 className="text-lg font-medium mt-8 mb-3">Element Structure</h3>
  114. <p className="text-sm text-muted-foreground mb-4">
  115. In the built-in schema, each element in the elements map has this
  116. structure:
  117. </p>
  118. <Code lang="typescript">{`interface Element {
  119. type: string; // Component type from catalog
  120. props: Record<string, any>; // Component properties
  121. children: string[]; // Array of child element keys
  122. visible?: VisibilityRule; // Conditional display
  123. }`}</Code>
  124. <h3 className="text-lg font-medium mt-8 mb-3">Data Binding Syntax</h3>
  125. <p className="text-sm text-muted-foreground mb-4">
  126. Reference dynamic data using the{" "}
  127. <code className="text-foreground">$data</code> prefix in props:
  128. </p>
  129. <Code lang="json">{`{
  130. "type": "Text",
  131. "props": {
  132. "content": "$data.user.name",
  133. "count": "$data.items.length"
  134. },
  135. "children": []
  136. }`}</Code>
  137. <h3 className="text-lg font-medium mt-8 mb-3">Action Format</h3>
  138. <p className="text-sm text-muted-foreground mb-4">
  139. Actions are defined in the catalog and referenced from components. The
  140. renderer handles action execution:
  141. </p>
  142. <Code lang="typescript">{`// In your catalog
  143. actions: {
  144. navigate: {
  145. params: z.object({ url: z.string() }),
  146. description: 'Navigate to a URL',
  147. },
  148. apiCall: {
  149. params: z.object({
  150. endpoint: z.string(),
  151. method: z.enum(['GET', 'POST', 'PUT', 'DELETE']),
  152. }),
  153. description: 'Make an API request',
  154. },
  155. }`}</Code>
  156. <h2 className="text-xl font-semibold mt-12 mb-4">Custom Schemas</h2>
  157. <p className="text-sm text-muted-foreground mb-4">
  158. <code className="text-foreground">@json-render/core</code> is
  159. schema-agnostic. You can define any JSON structure:
  160. </p>
  161. <Code lang="typescript">{`import { z } from 'zod';
  162. // Define your own element schema
  163. const MyElementSchema = z.object({
  164. component: z.string(),
  165. settings: z.record(z.unknown()),
  166. nested: z.array(z.lazy(() => MyElementSchema)).optional(),
  167. });
  168. // Define your own data binding format
  169. const BoundValue = z.object({
  170. literal: z.string().optional(),
  171. path: z.string().optional(), // e.g., "/users/0/name"
  172. });
  173. // Define your own action format
  174. const ActionSchema = z.object({
  175. name: z.string(),
  176. context: z.record(z.unknown()).optional(),
  177. });`}</Code>
  178. <h2 className="text-xl font-semibold mt-12 mb-4">Schema vs Catalog</h2>
  179. <p className="text-sm text-muted-foreground mb-4">
  180. The schema and catalog work together but serve different purposes:
  181. </p>
  182. <ul className="list-disc list-inside text-sm text-muted-foreground space-y-1 mb-4">
  183. <li>
  184. <strong className="text-foreground">Schema</strong> — Defines the JSON
  185. structure (how elements are organized)
  186. </li>
  187. <li>
  188. <strong className="text-foreground">Catalog</strong> — Defines
  189. available components and their props (what can be used)
  190. </li>
  191. </ul>
  192. <p className="text-sm text-muted-foreground mb-4">
  193. The schema is the grammar; the catalog is the vocabulary.
  194. </p>
  195. <h2 className="text-xl font-semibold mt-12 mb-4">Next</h2>
  196. <p className="text-sm text-muted-foreground">
  197. Learn about{" "}
  198. <Link href="/docs/specs" className="text-foreground hover:underline">
  199. specs
  200. </Link>{" "}
  201. — the actual JSON documents that describe your UI.
  202. </p>
  203. </article>
  204. );
  205. }