export const metadata = { title: "Streaming" } # Streaming Progressively render UI as AI generates it. ## SpecStream Format json-render uses **SpecStream**, a JSONL-based streaming format where each line is a JSON patch operation that progressively builds your spec: ```json {"op":"add","path":"/root","value":"root"} {"op":"add","path":"/elements/root","value":{"type":"Card","props":{"title":"Dashboard"},"children":["metric-1","metric-2"]}} {"op":"add","path":"/elements/metric-1","value":{"type":"Metric","props":{"label":"Revenue"}}} {"op":"add","path":"/elements/metric-2","value":{"type":"Metric","props":{"label":"Users"}}} ``` ## useUIStream Hook The hook handles parsing and state management: ```tsx import { useUIStream } from '@json-render/react'; function App() { const { spec, // Current UI spec state isStreaming, // True while streaming error, // Any error that occurred send, // Function to start generation clear, // Function to reset spec and error } = useUIStream({ api: '/api/generate', onComplete: (spec) => {}, // Optional: called when streaming completes onError: (error) => {}, // Optional: called when an error occurs }); } ``` ## Patch Operations (RFC 6902) SpecStream uses [RFC 6902 JSON Patch](https://datatracker.ietf.org/doc/html/rfc6902) operations: - `add` — Add a value at a path (creates or replaces for objects, inserts for arrays) - `remove` — Remove the value at a path - `replace` — Replace an existing value at a path - `move` — Move a value from one path to another (requires `from`) - `copy` — Copy a value from one path to another (requires `from`) - `test` — Assert that a value at a path equals the given value ## Path Format Paths use a key-based format for elements: ```bash /root -> Root element /root/children -> Children of root /elements/card-1 -> Element with key "card-1" /elements/card-1/children -> Children of card-1 ``` ## Server-Side Setup Ensure your API route streams properly: ```typescript import { streamText } from 'ai'; import { catalog } from '@/lib/catalog'; export async function POST(req: Request) { const { prompt } = await req.json(); const result = streamText({ model: 'anthropic/claude-haiku-4.5', system: catalog.prompt(), prompt, }); // Return as a streaming response return result.toTextStreamResponse(); } ``` ## Progressive Rendering The Renderer automatically updates as the spec changes: ```tsx function App() { const { spec, isStreaming } = useUIStream({ api: '/api/generate' }); return (