page.mdx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. export const metadata = { title: "Changelog" }
  2. # Changelog
  3. Notable changes and updates to json-render.
  4. ## v0.6.0
  5. February 2026
  6. ### New: Chat Mode (Inline GenUI)
  7. json-render now supports two generation modes: **Generate** (JSONL-only, the default) and **Chat** (text + JSONL inline). Chat mode lets the AI respond conversationally with embedded UI specs, ideal for chatbots and copilot experiences.
  8. ```typescript
  9. // Generate mode (default) — AI outputs only JSONL
  10. const prompt = catalog.prompt();
  11. // Chat mode — AI outputs text + JSONL inline
  12. const chatPrompt = catalog.prompt({ mode: "chat" });
  13. ```
  14. On the server, `pipeJsonRender()` separates text from JSONL patches in a mixed stream:
  15. ```typescript
  16. import { pipeJsonRender } from "@json-render/core";
  17. import { createUIMessageStream, createUIMessageStreamResponse } from "ai";
  18. const stream = createUIMessageStream({
  19. execute: async ({ writer }) => {
  20. writer.merge(pipeJsonRender(result.toUIMessageStream()));
  21. },
  22. });
  23. return createUIMessageStreamResponse({ stream });
  24. ```
  25. On the client, `useJsonRenderMessage` extracts the spec and text from message parts:
  26. ```tsx
  27. import { useJsonRenderMessage } from "@json-render/react";
  28. function ChatMessage({ message }) {
  29. const { spec, text, hasSpec } = useJsonRenderMessage(message.parts);
  30. return (
  31. <div>
  32. {text && <Markdown>{text}</Markdown>}
  33. {hasSpec && <Renderer spec={spec} registry={registry} />}
  34. </div>
  35. );
  36. }
  37. ```
  38. ### New: AI SDK Integration
  39. First-class Vercel AI SDK support with typed data parts and stream utilities.
  40. - `SpecDataPart` type for `data-spec` stream parts (patch, flat, nested payloads)
  41. - `SPEC_DATA_PART` / `SPEC_DATA_PART_TYPE` constants for type-safe part filtering
  42. - `createJsonRenderTransform()` low-level TransformStream for custom pipelines
  43. - `createMixedStreamParser()` for parsing mixed text + JSONL streams
  44. ### New: Two-Way Binding
  45. Props can now use `$bindState` and `$bindItem` expressions for two-way data binding. The renderer resolves bindings and passes a `bindings` map to components, enabling write-back to state without custom `valuePath` props.
  46. ```json
  47. {
  48. "type": "Input",
  49. "props": { "label": "Email", "value": { "$bindState": "/form/email" } }
  50. }
  51. ```
  52. ```tsx
  53. import { useBoundProp } from "@json-render/react";
  54. Input: ({ props, bindings }) => {
  55. const [value, setValue] = useBoundProp<string>(props.value, bindings?.value);
  56. return <input value={value ?? ""} onChange={(e) => setValue(e.target.value)} />;
  57. }
  58. ```
  59. ### New: Expression-Based Props and Visibility
  60. All dynamic expressions now use structured `$state`, `$item`, and `$index` objects instead of string token rewriting. This is simpler, more explicit, and works for both props and visibility conditions.
  61. **Props:**
  62. ```json
  63. { "title": { "$state": "/user/name" } }
  64. { "label": { "$item": "title" } }
  65. { "position": { "$index": true } }
  66. ```
  67. **Visibility:**
  68. ```json
  69. { "$state": "/isAdmin" }
  70. { "$state": "/role", "eq": "admin" }
  71. [{ "$state": "/isAdmin" }, { "$state": "/feature" }]
  72. { "$or": [{ "$state": "/roleA" }, { "$state": "/roleB" }] }
  73. { "$item": "isActive" }
  74. { "$index": true, "gt": 0 }
  75. ```
  76. Comparison operators: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `not`.
  77. ### New: React Chat Hooks
  78. - `useChatUI()` — full chat hook with message history, streaming, and spec extraction
  79. - `useJsonRenderMessage()` — extract spec + text from a message's parts array
  80. - `buildSpecFromParts()` / `getTextFromParts()` — utilities for working with AI SDK message parts
  81. - `useBoundProp()` — two-way binding hook for `$bindState` / `$bindItem`
  82. ### New: Chat Example
  83. Full-featured chat example (`examples/chat`) with AI agent, tool calls (crypto, GitHub, Hacker News, weather, search), theme toggle, and streaming inline UI generation.
  84. ### Improved: Renderer Performance
  85. - `ElementRenderer` is now `React.memo`'d for better performance with repeat lists
  86. - `emit` is always defined (never `undefined`)
  87. - Repeat scope passes the actual item object, eliminating string token rewriting
  88. ### Improved: Utilities
  89. - `applySpecPatch()` — typed wrapper for applying a single patch to a Spec
  90. - `nestedToFlat()` — convert nested tree specs to flat format
  91. - `resolveBindings()` / `resolveActionParam()` — resolve binding paths and action params
  92. ### Breaking Changes
  93. - `{ $path }` and `{ path }` replaced by `{ $state }`, `{ $item }`, `{ $index }` in props
  94. - Visibility: `{ path }` -> `{ $state }`, `{ and/or/not }` -> `{ $and/$or }` with `not` as operator flag
  95. - `DynamicValue`: `{ path: string }` -> `{ $state: string }`
  96. - `repeat.path` -> `repeat.statePath`
  97. - Action params: `path` -> `statePath` in setState action
  98. - `actionHandlers` -> `handlers` on `JSONUIProvider` / `ActionProvider`
  99. - `AuthState` and `{ auth }` visibility conditions removed (model auth as regular state)
  100. - Legacy catalog API removed: `createCatalog`, `generateCatalogPrompt`, `generateSystemPrompt`
  101. - React exports removed: `createRendererFromCatalog`, `rewriteRepeatTokens`
  102. - Codegen: `traverseTree` -> `traverseSpec`
  103. See the [Migration Guide](/docs/migration) for detailed upgrade instructions.
  104. ---
  105. ## v0.5.0
  106. February 2026
  107. ### New: @json-render/react-native
  108. Full React Native renderer with 25+ standard components, data binding, visibility, actions, and dynamic props. Build AI-generated native mobile UIs with the same catalog-driven approach as web.
  109. ```tsx
  110. import { defineCatalog } from "@json-render/core";
  111. import { schema } from "@json-render/react-native/schema";
  112. import {
  113. standardComponentDefinitions,
  114. standardActionDefinitions,
  115. } from "@json-render/react-native/catalog";
  116. import { defineRegistry, Renderer } from "@json-render/react-native";
  117. const catalog = defineCatalog(schema, {
  118. components: { ...standardComponentDefinitions },
  119. actions: standardActionDefinitions,
  120. });
  121. const { registry } = defineRegistry(catalog, { components: {} });
  122. <Renderer spec={spec} registry={registry} />
  123. ```
  124. Includes standard components for layout (Container, Row, Column, ScrollContainer, SafeArea, Pressable, Spacer, Divider), content (Heading, Paragraph, Label, Image, Avatar, Badge, Chip), input (Button, TextInput, Switch, Checkbox, Slider, SearchBar), feedback (Spinner, ProgressBar), and composite (Card, ListItem, Modal).
  125. ### New: Event System
  126. Components now use `emit` to fire named events instead of directly dispatching actions. The element's `on` field maps events to action bindings, decoupling component logic from action handling.
  127. ```tsx
  128. // Component emits a named event
  129. Button: ({ props, emit }) => (
  130. <button onClick={() => emit("press")}>{props.label}</button>
  131. ),
  132. // Element spec maps events to actions
  133. {
  134. "type": "Button",
  135. "props": { "label": "Submit" },
  136. "on": { "press": { "action": "submit", "params": { "formId": "main" } } }
  137. }
  138. ```
  139. ### New: Repeat/List Rendering
  140. Elements can now iterate over state arrays using the `repeat` field. Child elements use `{ "$item": "field" }` to read from the current item and `{ "$index": true }` for the current array index.
  141. ```json
  142. {
  143. "type": "Column",
  144. "repeat": { "statePath": "/posts", "key": "id" },
  145. "children": ["post-card"]
  146. }
  147. ```
  148. ```json
  149. {
  150. "type": "Card",
  151. "props": { "title": { "$item": "title" } }
  152. }
  153. ```
  154. ### New: User Prompt Builder
  155. Build structured user prompts with optional spec refinement and state context:
  156. ```typescript
  157. import { buildUserPrompt } from "@json-render/core";
  158. // Fresh generation
  159. buildUserPrompt({ prompt: "create a todo app" });
  160. // Refinement (patch-only mode)
  161. buildUserPrompt({ prompt: "add a toggle", currentSpec: spec });
  162. // With runtime state
  163. buildUserPrompt({ prompt: "show data", state: { todos: [] } });
  164. ```
  165. ### New: Spec Validation
  166. Validate spec structure and auto-fix common issues:
  167. ```typescript
  168. import { validateSpec, autoFixSpec } from "@json-render/core";
  169. const { valid, issues } = validateSpec(spec);
  170. const fixed = autoFixSpec(spec);
  171. ```
  172. ### Improved: State Management
  173. `DataProvider` has been renamed to `StateProvider` with a clearer API. State is now a first-class part of specs. Elements can bind to state via `$state` expressions, and the built-in `setState` action updates state directly.
  174. ### Improved: AI Prompts
  175. Schema prompts now include streaming best practices, repeat/list examples, and state patching guidance. Schemas can also define `defaultRules` that are always included in generated prompts.
  176. ### Improved: Documentation
  177. - All documentation pages migrated to MDX
  178. - AI-powered documentation chat
  179. - Dynamic Open Graph images for all docs pages
  180. - Improved playground
  181. ### Breaking Changes
  182. - `DataProvider` renamed to `StateProvider`
  183. - `useData` renamed to `useStateStore`, `useDataValue` to `useStateValue`, `useDataBinding` to `useStateBinding`
  184. - `onAction` renamed to `emit` in component context
  185. - `DataModel` type renamed to `StateModel`
  186. - `Action` type renamed to `ActionBinding` (old name still available but deprecated)
  187. ---
  188. ## v0.4.0
  189. February 2026
  190. ### New: Custom Schema System
  191. Create custom output formats with `defineSchema`. Each renderer now defines its own schema, enabling completely different spec formats for different use cases.
  192. ```typescript
  193. import { defineSchema } from "@json-render/core";
  194. const mySchema = defineSchema((s) => ({
  195. spec: s.object({
  196. pages: s.array(s.object({
  197. title: s.string(),
  198. blocks: s.array(s.ref("catalog.blocks")),
  199. })),
  200. }),
  201. catalog: s.object({
  202. blocks: s.map({ props: s.zod(), description: s.string() }),
  203. }),
  204. }), {
  205. promptTemplate: myPromptTemplate,
  206. });
  207. ```
  208. ### New: Component Slots
  209. Components can now define which slots they accept. Use `["default"]` for regular children, or named slots like `["header", "footer"]` for more complex layouts.
  210. ```typescript
  211. const catalog = defineCatalog(schema, {
  212. components: {
  213. Card: {
  214. props: z.object({ title: z.string() }),
  215. slots: ["default"], // accepts children
  216. description: "A card container",
  217. },
  218. Layout: {
  219. props: z.object({}),
  220. slots: ["header", "content", "footer"], // named slots
  221. description: "Page layout with header, content, footer",
  222. },
  223. },
  224. });
  225. ```
  226. ### New: AI Prompt Generation
  227. Catalogs now generate AI system prompts automatically with `catalog.prompt()`. The prompt includes all component definitions, props schemas, and action descriptions - ensuring the AI only generates valid specs.
  228. ```typescript
  229. import { defineCatalog } from "@json-render/core";
  230. import { schema } from "@json-render/react/schema";
  231. const catalog = defineCatalog(schema, {
  232. components: { /* ... */ },
  233. actions: { /* ... */ },
  234. });
  235. // Generate system prompt for AI
  236. const systemPrompt = catalog.prompt();
  237. // Use with any AI SDK
  238. const result = await streamText({
  239. model: "claude-haiku-4.5",
  240. system: systemPrompt,
  241. prompt: userMessage,
  242. });
  243. ```
  244. ### New: @json-render/remotion
  245. Generate AI-powered videos with Remotion. Define video catalogs, stream timeline specs, and render with the Remotion Player.
  246. ```tsx
  247. import { Player } from "@remotion/player";
  248. import { Renderer, schema, standardComponentDefinitions } from "@json-render/remotion";
  249. const catalog = defineCatalog(schema, {
  250. components: standardComponentDefinitions,
  251. transitions: standardTransitionDefinitions,
  252. });
  253. <Player
  254. component={Renderer}
  255. inputProps={{ spec }}
  256. durationInFrames={spec.composition.durationInFrames}
  257. fps={spec.composition.fps}
  258. compositionWidth={spec.composition.width}
  259. compositionHeight={spec.composition.height}
  260. />
  261. ```
  262. Includes 10 standard video components (TitleCard, TypingText, SplitScreen, etc.), 7 transition types, and the ClipWrapper utility for custom components.
  263. ### New: SpecStream
  264. SpecStream is json-render's streaming format for progressively building specs from JSONL patches. The new compiler API makes it easy to process streaming AI responses.
  265. ```typescript
  266. import { createSpecStreamCompiler } from "@json-render/core";
  267. const compiler = createSpecStreamCompiler<MySpec>();
  268. // Process streaming chunks
  269. const { result, newPatches } = compiler.push(chunk);
  270. setSpec(result); // Update UI with partial result
  271. ```
  272. ### Improved: Dashboard Example
  273. The dashboard example is now a full-featured accounting dashboard with:
  274. - Persistent SQLite database with Drizzle ORM
  275. - RESTful API for customers, invoices, expenses, accounts
  276. - Draggable widget reordering
  277. - AI-powered widget generation with streaming
  278. - Real data binding to database records
  279. ### Improved: Documentation
  280. - Interactive playground for testing specs
  281. - New guides: Custom Schema, Streaming, Code Export
  282. - Full API reference for all packages
  283. - Integration guides: A2UI, AG-UI, Adaptive Cards, OpenAPI
  284. ### Breaking Changes
  285. - `UITree` type renamed to `Spec`
  286. - Schema is now imported from renderer packages (`@json-render/react`) not core
  287. - `defineCatalog` now requires a schema as first argument
  288. ---
  289. ## v0.3.0
  290. January 2026
  291. Internal release with codegen foundations.
  292. - Added `@json-render/codegen` package (spec traversal and JSX serialization)
  293. - Configurable AI model via environment variables
  294. - Documentation improvements and bug fixes
  295. *Note: Only @json-render/core was published to npm for this release.*
  296. ---
  297. ## v0.2.0
  298. January 2026
  299. Initial public release.
  300. - Core catalog and spec types
  301. - React renderer with contexts for data, actions, visibility
  302. - AI prompt generation from catalogs
  303. - Basic streaming support
  304. - Dashboard example application