page.mdx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import { pageMetadata } from "@/lib/page-metadata"
  2. export const metadata = pageMetadata("docs/quick-start")
  3. # Quick Start
  4. Get up and running with json-render in 5 minutes.
  5. ## 1. Define your catalog
  6. Create a catalog that defines what components AI can use:
  7. ```typescript
  8. // lib/catalog.ts
  9. import { defineCatalog } from '@json-render/core';
  10. import { schema } from '@json-render/react/schema';
  11. import { z } from 'zod';
  12. export const catalog = defineCatalog(schema, {
  13. components: {
  14. Card: {
  15. props: z.object({
  16. title: z.string(),
  17. description: z.string().nullable(),
  18. }),
  19. slots: ["default"],
  20. description: "Container card with optional title",
  21. },
  22. Button: {
  23. props: z.object({
  24. label: z.string(),
  25. action: z.string().nullable(),
  26. }),
  27. description: "Clickable button that triggers an action",
  28. },
  29. Text: {
  30. props: z.object({
  31. content: z.string(),
  32. }),
  33. description: "Text paragraph",
  34. },
  35. },
  36. actions: {
  37. submit: {
  38. params: z.object({ formId: z.string() }),
  39. description: "Submit a form",
  40. },
  41. navigate: {
  42. params: z.object({ url: z.string() }),
  43. description: "Navigate to a URL",
  44. },
  45. },
  46. });
  47. ```
  48. ## 2. Define your components
  49. Use `defineRegistry` to map catalog types to React components. Each component receives type-safe `props`, `children`, and `emit`:
  50. ```tsx
  51. // lib/registry.tsx
  52. import { defineRegistry } from '@json-render/react';
  53. import { catalog } from './catalog';
  54. export const { registry } = defineRegistry(catalog, {
  55. components: {
  56. Card: ({ props, children }) => (
  57. <div className="p-4 border rounded-lg">
  58. <h2 className="font-bold">{props.title}</h2>
  59. {props.description && (
  60. <p className="text-gray-600">{props.description}</p>
  61. )}
  62. {children}
  63. </div>
  64. ),
  65. Button: ({ props, emit }) => (
  66. <button
  67. className="px-4 py-2 bg-blue-500 text-white rounded"
  68. onClick={() => emit("press")}
  69. >
  70. {props.label}
  71. </button>
  72. ),
  73. Text: ({ props }) => (
  74. <p>{props.content}</p>
  75. ),
  76. },
  77. });
  78. ```
  79. ## 3. Create an API route
  80. Set up a streaming API route for AI generation:
  81. ```typescript
  82. // app/api/generate/route.ts
  83. import { streamText } from 'ai';
  84. import { catalog } from '@/lib/catalog';
  85. export async function POST(req: Request) {
  86. const { prompt } = await req.json();
  87. // Generate system prompt from catalog
  88. const systemPrompt = catalog.prompt();
  89. const result = streamText({
  90. model: 'anthropic/claude-haiku-4.5',
  91. system: systemPrompt,
  92. prompt,
  93. });
  94. return result.toTextStreamResponse();
  95. }
  96. ```
  97. ## 4. Render the UI
  98. Use providers and the `Renderer` with your registry to display AI-generated UI:
  99. ```tsx
  100. // app/page.tsx
  101. 'use client';
  102. import { Renderer, StateProvider, ActionProvider, VisibilityProvider, ValidationProvider, useUIStream } from '@json-render/react';
  103. import { registry } from '@/lib/registry';
  104. export default function Page() {
  105. const { spec, isStreaming, send } = useUIStream({
  106. api: '/api/generate',
  107. });
  108. const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
  109. e.preventDefault();
  110. const formData = new FormData(e.currentTarget);
  111. send(formData.get('prompt') as string);
  112. };
  113. return (
  114. <StateProvider initialState={{}}>
  115. <VisibilityProvider>
  116. <ActionProvider handlers={{
  117. submit: (params) => console.log('Submit:', params),
  118. navigate: (params) => console.log('Navigate:', params),
  119. }}>
  120. <ValidationProvider customFunctions={{}}>
  121. <form onSubmit={handleSubmit}>
  122. <input
  123. name="prompt"
  124. placeholder="Describe what you want..."
  125. className="border p-2 rounded"
  126. />
  127. <button type="submit" disabled={isStreaming}>
  128. Generate
  129. </button>
  130. </form>
  131. <div className="mt-8">
  132. <Renderer spec={spec} registry={registry} loading={isStreaming} />
  133. </div>
  134. </ValidationProvider>
  135. </ActionProvider>
  136. </VisibilityProvider>
  137. </StateProvider>
  138. );
  139. }
  140. ```
  141. ## Quick Start with shadcn/ui
  142. If you want to skip defining components from scratch, use `@json-render/shadcn` for 36 pre-built components:
  143. ```typescript
  144. // lib/catalog.ts
  145. import { defineCatalog } from '@json-render/core';
  146. import { schema } from '@json-render/react/schema';
  147. import { shadcnComponentDefinitions } from '@json-render/shadcn/catalog';
  148. export const catalog = defineCatalog(schema, {
  149. components: {
  150. Card: shadcnComponentDefinitions.Card,
  151. Stack: shadcnComponentDefinitions.Stack,
  152. Heading: shadcnComponentDefinitions.Heading,
  153. Button: shadcnComponentDefinitions.Button,
  154. Input: shadcnComponentDefinitions.Input,
  155. },
  156. actions: {},
  157. });
  158. ```
  159. ```tsx
  160. // lib/registry.tsx
  161. import { defineRegistry } from '@json-render/react';
  162. import { shadcnComponents } from '@json-render/shadcn';
  163. import { catalog } from './catalog';
  164. export const { registry } = defineRegistry(catalog, {
  165. components: {
  166. Card: shadcnComponents.Card,
  167. Stack: shadcnComponents.Stack,
  168. Heading: shadcnComponents.Heading,
  169. Button: shadcnComponents.Button,
  170. Input: shadcnComponents.Input,
  171. },
  172. });
  173. ```
  174. See the [@json-render/shadcn API reference](/docs/api/shadcn) for the full component list.
  175. ## Next steps
  176. - Learn about [catalogs](/docs/catalog) in depth
  177. - Explore [data binding](/docs/data-binding) for dynamic values
  178. - Add [action handlers](/docs/registry#action-handlers) for interactivity
  179. - Implement [conditional visibility](/docs/visibility)
  180. - Use [pre-built shadcn/ui components](/docs/api/shadcn) for fast prototyping