json-render:给 AI 生成 UI 加护栏的 Vercel Labs 框架,目录约束 + JSON Spec + 渐进渲染
阅读时间: 大约 15 分钟
json-render:给 AI 生成 UI 加护栏的 Vercel Labs 框架,目录约束 + JSON Spec + 渐进渲染

json-render 是 Vercel Labs 的 Generative UI 框架(Apache-2.0),npm 命名空间 @json-render/*。它的核心主张写在 slogan 里:Predictable. Guardrailed. Fast.——开发者先声明一份”目录(catalog)“,限定 AI 能用哪些组件、动作与数据绑定,AI 只能在这个范围内输出结构化 JSON,前端再把 JSON Spec 实时渲染成界面。本文基于其 GitHub README、官方文档站与变更日志做一手核对。
一、背景动机:AI 直接写 JSX 不可控,直接写 HTML 又没法复用设计系统
让大模型生成界面有两条朴素路线,都有问题:一是让模型直接输出 JSX/HTML,样式不可控、可能注入任意元素,也接不进现有组件库;二是完全模板化,AI 只能填表单字段,失去”动态生成界面”的意义。
json-render 取中间路线:把”可用什么”做成一份开发者编写、zod 校验的目录,模型输出的不是代码而是一份声明式 JSON Spec(根节点 + elements 映射表,每个元素有 type/props/children),渲染器只认目录里登记过的类型,超出目录的内容没有实现可渲染。
二、是什么:core 目录层 + 多渲染器的包矩阵
README 的工作流(mermaid)为:User Prompt → AI + Catalog → JSON Spec → Renderer,三条虚线分别标注 guardrailed、predictable、streamed。
| 包 | 职责 |
|---|---|
@json-render/core | schema、catalog、AI prompt 生成、动态 props、SpecStream 工具 |
@json-render/react | React 渲染器、context、hooks |
@json-render/vue / svelte / solid | 对应前端框架渲染器 |
@json-render/shadcn | 36 个预置 shadcn/ui 组件(Radix UI + Tailwind) |
@json-render/react-native | 移动端,25+ 标准组件 |
@json-render/next / tanstack-start | 整应用路由、布局、SSR、metadata |
@json-render/remotion / react-pdf / react-email / ink / image | 视频时间线、PDF、HTML 邮件、终端 TUI、Satori SVG/PNG |
@json-render/react-three-fiber | 3D 场景,20 个内置组件含 GaussianSplat |
状态层可接 Redux、Zustand、Jotai、XState 适配器;另有 MCP Apps、YAML 线格式、codegen 与四框架 devtools。
三、技术机制:目录声明 → 系统提示词 → JSON Spec → 渐进渲染
3.1 目录(Catalog)
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/react/schema";
import { z } from "zod";
export const catalog = defineCatalog(schema, {
components: {
Card: { props: z.object({ title: z.string() }), description: "A card container" },
Metric: { props: z.object({ label: z.string(), value: z.string(),
format: z.enum(["currency","percent","number"]).nullable() }) },
Button: { props: z.object({ label: z.string(), action: z.string() }) },
},
actions: { export_report: { description: "Export dashboard to PDF" } },
});catalog.prompt() 把组件描述、props schema、可用动作自动组装成系统提示词,避免手写一大段约束说明。defineRegistry 再把目录类型映射到真实组件实现,返回类型安全的 registry。

需要说明口径:README 称 @json-render/shadcn 提供 36 个预置组件,而官网 playground 面板显示 41 components / 6 actions——后者是站点自带的更大自定义演示目录,两者不是同一计数,不能混用。
3.2 JSON Spec 与动态表达式
Spec 是扁平结构:root 指向元素 id,elements 是 id→定义的映射。props 里可用表达式做数据驱动:
{ "$state": "/form/name" }读状态;{ "$cond": {...}, "$then": ..., "$else": ... }条件分支;{ "$template": "Hello, ${/user/name}!" }字符串插值;{ "$computed": "fn", "args": {...} }调注册函数;$bindState双向绑定;visible声明条件可见;watch监听状态变化触发动作;内置setState动作直接改状态模型。
3.3 SpecStream 渐进渲染
const compiler = createSpecStreamCompiler<MySpec>();
const { result, newPatches } = compiler.push(chunk);
setSpec(result); // 到达一块就更新部分结果
const finalSpec = compiler.getResult();模型边输出边到达,UI 边渲染,不必等完整 JSON。
四、关键数据:可核对的官方数字
| 项目 | 官方口径 | 来源 |
|---|---|---|
| 协议 | Apache-2.0 | README License |
| shadcn 预置组件 | 36(shadcn-svelte 同样 36) | README 包表 |
| react-native 标准组件 | 25+ | README |
| R3F 内置组件 | 20(含 GaussianSplat) | README/变更日志 v0.17.0 |
| 官网 playground 目录 | 41 components / 6 actions | 官网演示面板 |
| 初始公开发布 | v0.2.0,2026-01-14 | 官方 changelog |
| 核对时最新 | v0.21.1,2026-10-13 | 官方 changelog |
| 校验层 | zod 4 | README/变更日志 |
五、评测方法批判:护栏到底挡住了什么
- 护栏只约束”已登记目录”:模型仍可能输出目录外类型或非法 props,真正兜底要靠 zod 校验与渲染器拒收;“predictable”是架构目标,不是模型保证,官方也未给出合规率测试。
- 41/6 是演示目录不是框架上限:计数随你的 catalog 变化,不能写成”框架提供 41 个组件”。
- 版本节奏快且有破坏性变更:从 v0.2.0(1 月中)到 v0.21.1(10 月中)约 21 个 minor,v0.4–v0.9 多次重命名(
$path→$state、DataProvider→StateProvider 等),0.x 阶段升级需要跟 changelog;v0.9.0 还出过私有依赖导致安装失败的历史问题。 - 跨渲染器功能并非完全对齐:Web 四框架较完整,移动端、视频、PDF、邮件、终端各有自己的组件集与边界,文档按包分开,不能假设同一份 Spec 在所有渲染器表现一致。
- Jev 组合是实验品:
experimental_composeSpec/experimental_createEvaluator未正式发布,API 可能随版本变动,官方明确标注。 - 本文未独立跑分:官方没有提供与手写 JSX、其他 GenUI 方案的延迟/成功率对照,不替它编造性能数字。
六、适用 / 不适用场景
适合:
- 已有成熟组件库,想让 AI 在白名单内动态拼装卡片、仪表盘、表单的团队;
- 需要同一套目录同时出 Web(React/Vue/Svelte/Solid)、React Native、邮件、PDF、视频的多端场景;
- 聊天式 copilot 需要边流式边渲染结果卡片,又要避免模型输出任意代码;
- 愿意用 zod 精细建模 props 与动作契约的工程团队。
不适合:
- 期望”一句话生成任意自由布局网页”的用户——目录外元素无法渲染;
- 生产上直接依赖 0.x API 而不锁版本、不跟变更日志的团队;
- 需要复杂自定义交互且预置组件覆盖不到、又不愿自己写 registry 实现的场景;
- 把实验性 Jev 当稳定功能接入的项目。
七、客观分析:优势与局限
优势:
- 契约清晰:zod 目录 + registry 实现 + 类型安全,把模型输出收敛到开发者掌握的组件集;
- 渲染器矩阵宽:Web 四框架、移动端、Next/TanStack 整应用、Remotion、PDF、邮件、终端、3D、图片,一份 Spec 思路跨端;
- 流式渐进渲染内建:SpecStream 把”边生成边显示”做成 core 能力;
- 状态与表达式完整:
$state/$cond/$template/$computed/$bindState、watch、条件可见、外部 store 适配器; - 协议宽松:Apache-2.0,可商用。
局限:
- 前期建模成本:每个可用组件、动作、校验函数都要手写目录,冷启动比直接喂组件给模型重;
- 0.x 频繁破坏性变更,升级有维护负担;
- 护栏非模型层强制,需自行校验拒收非法 Spec;
- 各渲染器成熟度不一,移动端/视频/邮件为补充而非同等深度;
- 实验特性(Jev)边界明确,不可当稳定依赖。
八、它意味着什么 / 谁该关注
json-render 代表 Generative UI 的”受控生成”路线:不追求模型自由作画,而是把设计系统变成机器可读的目录契约,让生成结果可预测、可流式、可跨端。值得关注:构建内部 copilot/仪表盘生成器的前端团队、多端产品希望复用一套组件契约的工程负责人、研究 GenUI 护栏与 zod schema 约束的工具作者。建议先从 @json-render/react + 少量自定义组件起步,跑通 SpecStream,再评估跨渲染器与 shadcn 预置包。