vercel-labs/json-render
vercel-labs/json-render là dự án TypeScript với 15.8k sao trong nhóm AI Tools. The Generative UI framework
Tóm tắt dựng từ metadata GitHub của chính dự án — chưa có bài review TopGit. Trang sẽ tự động cập nhật khi bài review đầy đủ được xuất bản.
TopGit viết bài đầy đủ cho repo có nhiều sao nhất và được yêu cầu nhiều nhất. Trang này là snapshot trong thời gian chờ — xem README gốc ở tab READ ME.
Snapshot
Cộng tác viên hàng đầu
Xem cộng tác viên hàng đầu
json-render
The Generative UI framework.
Generate dynamic, personalized UIs from prompts without sacrificing reliability. Predefined components and actions for safe, predictable output.
# for React
npm install @json-render/core @json-render/react
# for React with pre-built shadcn/ui components
npm install @json-render/shadcn
# or for React Native
npm install @json-render/core @json-render/react-native
# or for video
npm install @json-render/core @json-render/remotion
# or for PDF documents
npm install @json-render/core @json-render/react-pdf
# or for HTML email
npm install @json-render/core @json-render/react-email @react-email/components @react-email/render
# or for Vue
npm install @json-render/core @json-render/vue
# or for Svelte
npm install @json-render/core @json-render/svelte
# or for SolidJS
npm install @json-render/core @json-render/solid
# or for terminal UIs
npm install @json-render/core @json-render/ink ink react
# or for full Next.js apps (routes, layouts, SSR, metadata)
npm install @json-render/core @json-render/react @json-render/next
# or for 3D scenes (and gaussian splatting via the GaussianSplat component)
npm install @json-render/core @json-render/react-three-fiber @react-three/fiber @react-three/drei three
Why json-render?
json-render is a Generative UI framework: AI generates interfaces from natural language prompts, constrained to components you define. You set the guardrails, AI generates within them:
- Guardrailed - AI can only use components in your catalog
- Predictable - JSON output matches your schema, every time
- Fast - Stream and render progressively as the model responds
- Cross-Platform - React, Vue, Svelte, Solid (web), React Native (mobile) from the same catalog
- Batteries Included - 36 pre-built shadcn/ui components ready to use
Quick Start
1. Define Your Catalog
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/react/schema";
import { z } from "zod";
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(),
}),
description: "Display a metric value",
},
Button: {
props: z.object({
label: z.string(),
action: z.string(),
}),
description: "Clickable button",
},
},
actions: {
export_report: { description: "Export dashboard to PDF" },
refresh_data: { description: "Refresh all metrics" },
},
});
2. Define Your Components
import { defineRegistry, Renderer } from "@json-render/react";
const { registry } = defineRegistry(catalog, {
components: {
Card: ({ props, children }) => (
<div className="card">
<h3>{props.title}</h3>
{children}
</div>
),
Metric: ({ props }) => (
<div className="metric">
<span>{props.label}</span>
<span>{format(props.value, props.format)}</span>
</div>
),
Button: ({ props, emit }) => (
<button onClick={() => emit("press")}>{props.label}</button>
),
},
});
3. Render AI-Generated Specs
function Dashboard({ spec }) {
return <Renderer spec={spec} registry={registry} />;
}
That's it. AI generates JSON, you render it safely.
Packages
| Package | Description |
|---|---|
@json-render/core | Schemas, catalogs, AI prompts, dynamic props, SpecStream utilities |
@json-render/react | React renderer, contexts, hooks |
@json-render/vue | Vue 3 renderer, composables, providers |
@json-render/svelte | Svelte 5 renderer with runes-based reactivity |
@json-render/solid | SolidJS renderer with fine-grained reactive contexts |
@json-render/shadcn | 36 pre-built shadcn/ui components (Radix UI + Tailwind CSS) |
@json-render/shadcn-svelte | 36 pre-built shadcn-svelte components (Svelte 5 + Tailwind CSS) |
@json-render/react-three-fiber | React Three Fiber renderer for 3D scenes (20 built-in components, including GaussianSplat) |
@json-render/react-native | React Native renderer with standard mobile components |
@json-render/next | Next.js renderer — JSON becomes full apps with routes, layouts, SSR |
@json-render/remotion | Remotion video renderer, timeline schema |
@json-render/react-pdf | React PDF renderer for generating PDF documents from specs |
@json-render/react-email | React Email renderer for HTML/plain-text emails from specs |
@json-render/ink | Ink terminal renderer with built-in components for interactive TUIs. |
@json-render/image | Image renderer for SVG/PNG output (OG images, social cards) via Satori |
@json-render/directives | Pre-built custom directives — $format, $math, $concat, $count, $truncate, $pluralize, $join, $t (i18n) |
@json-render/codegen | Utilities for generating code from json-render UI trees |
@json-render/devtools | Framework-agnostic devtools core — panel UI, event store, picker, stream taps |
@json-render/devtools-react | React adapter for @json-render/devtools (drop-in <JsonRenderDevtools />) |
@json-render/devtools-vue | Vue adapter for @json-render/devtools |
@json-render/devtools-svelte | Svelte adapter for @json-render/devtools |
@json-render/devtools-solid | SolidJS adapter for @json-render/devtools |
@json-render/redux | Redux / Redux Toolkit adapter for StateStore |
@json-render/zustand | Zustand adapter for StateStore |
@json-render/jotai | Jotai adapter for StateStore |
@json-render/xstate | XState Store (atom) adapter for StateStore |
@json-render/mcp | MCP Apps integration for Claude, ChatGPT, Cursor, VS Code |
@json-render/yaml | YAML wire format with streaming parser, edit modes, AI SDK transform |
Renderers
React (UI)
import { defineRegistry, Renderer } from "@json-render/react";
import { schema } from "@json-render/react/schema";
// Flat spec format (root key + elements map)
const spec = {
root: "card-1",
elements: {
"card-1": {
type: "Card",
props: { title: "Hello" },
children: ["button-1"],
},
"button-1": {
type: "Button",
props: { label: "Click me" },
children: [],
},
},
};
// defineRegistry creates a type-safe component registry
const { registry } = defineRegistry(catalog, { components });
<Renderer spec={spec} registry={registry} />;
Vue (UI)
import { h } from "vue";
import { defineRegistry, Renderer } from "@json-render/vue";
import { schema } from "@json-render/vue/schema";
const { registry } = defineRegistry(catalog, {
components: {
Card: ({ props, children }) =>
h("div", { class: "card" }, [h("h3", null, props.title), children]),
Button: ({ props, emit }) =>
h("button", { onClick: () => emit("press") }, props.label),
},
});
// In your Vue component template:
// <Renderer :spec="spec" :registry="registry" />
Svelte (UI)
import { defineRegistry, Renderer } from "@json-render/svelte";
import { schema } from "@json-render/svelte/schema";
const { registry } = defineRegistry(catalog, {
components: {
Card: ({ props, children }) => /* Svelte 5 snippet */,
Button: ({ props, emit }) => /* Svelte 5 snippet */,
},
});
// In your Svelte component:
// <Renderer spec={spec} registry={registry} />
Solid (UI)
import { defineRegistry, Renderer } from "@json-render/solid";
import { schema } from "@json-render/solid/schema";
const { registry } = defineRegistry(catalog, {
components: {
Card: (renderProps) => <div>{renderProps.children}</div>,
Button: (renderProps) => (
<button onClick={() => renderProps.emit("press")}>
{renderProps.element.props.label as string}
</button>
),
},
});
<Renderer spec={spec} registry={registry} />;
shadcn/ui (Web)
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/react/schema";
import { defineRegistry, Renderer } from "@json-render/react";
import { shadcnComponentDefinitions } from "@json-render/shadcn/catalog";
import { shadcnComponents } from "@json-render/shadcn";
// Pick components from the 36 standard definitions
const catalog = defineCatalog(schema, {
components: {
Card: shadcnComponentDefinitions.Card,
Stack: shadcnComponentDefinitions.Stack,
Heading: shadcnComponentDefinitions.Heading,
Button: shadcnComponentDefinitions.Button,
},
actions: {},
});
// Use matching implementations
const { registry } = defineRegistry(catalog, {
components: {
Card: shadcnComponents.Card,
Stack: shadcnComponents.Stack,
Heading: shadcnComponents.Heading,
Button: shadcnComponents.Button,
},
});
<Renderer spec={spec} registry={registry} />;
React Native (Mobile)
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/react-native/schema";
import {
standardComponentDefinitions,
standardActionDefinitions,
} from "@json-render/react-native/catalog";
import { defineRegistry, Renderer } from "@json-render/react-native";
// 25+ standard components included
const catalog = defineCatalog(schema, {
components: { ...standardComponentDefinitions },
actions: standardActionDefinitions,
});
const { registry } = defineRegistry(catalog, { components: {} });
<Renderer spec={spec} registry={registry} />;
Remotion (Video)
import { Player } from "@remotion/player";
import {
Renderer,
schema,
standardComponentDefinitions,
} from "@json-render/remotion";
// Timeline spec format
const spec = {
composition: {
id: "video",
fps: 30,
width: 1920,
height: 1080,
durationInFrames: 300,
},
tracks: [{ id: "main", name: "Main", type: "video", enabled: true }],
clips: [
{
id: "clip-1",
trackId: "main",
component: "TitleCard",
props: { title: "Hello" },
from: 0,
durationInFrames: 90,
},
],
audio: { tracks: [] },
};
<Player
component={Renderer}
inputProps={{ spec }}
durationInFrames={spec.composition.durationInFrames}
fps={spec.composition.fps}
compositionWidth={spec.composition.width}
compositionHeight={spec.composition.height}
/>;
React PDF (Documents)
import { renderToBuffer } from "@json-render/react-pdf";
const spec = {
root: "doc",
elements: {
doc: {
type: "Document",
props: { title: "Invoice" },
children: ["page-1"],
},
"page-1": {
type: "Page",
props: { size: "A4" },
children: ["heading-1", "table-1"],
},
"heading-1": {
type: "Heading",
props: { text: "Invoice #1234", level: "h1" },
children: [],
},
"table-1": {
type: "Table",
props: {
columns: [
{ header: "Item", width: "60%" },
{ header: "Price", width: "40%", align: "right" },
],
rows: [
["Widget A", "$10.00"],
["Widget B", "$25.00"],
],
},
children: [],
},
},
};
// Render to buffer, stream, or file
const buffer = await renderToBuffer(spec);
React Email (Email)
import { renderToHtml } from "@json-render/react-email";
import { schema, standardComponentDefinitions } from "@json-render/react-email";
import { defineCatalog } from "@json-render/core";
const catalog = defineCatalog(schema, {
components: standardComponentDefinitions,
});
const spec = {
root: "html-1",
elements: {
"html-1": {
type: "Html",
props: { lang: "en", dir: "ltr" },
children: ["head-1", "body-1"],
},
"head-1": { type: "Head", props: {}, children: [] },
"body-1": {
type: "Body",
props: { style: { backgroundColor: "#f6f9fc" } },
children: ["container-1"],
},
"container-1": {
type: "Container",
props: {
style: { maxWidth: "600px", margin: "0 auto", padding: "20px" },
},
children: ["heading-1", "text-1"],
},
"heading-1": { type: "Heading", props: { text: "Welcome" }, children: [] },
"text-1": {
type: "Text",
props: { text: "Thanks for signing up." },
children: [],
},
},
};
const html = await renderToHtml(spec);
Image (SVG/PNG)
import { renderToPng } from "@json-render/image/render";
const spec = {
root: "frame",
elements: {
frame: {
type: "Frame",
props: { width: 1200, height: 630, backgroundColor: "#1a1a2e" },
children: ["heading"],
},
heading: {
type: "Heading",
props: { text: "Hello World", level: "h1", color: "#ffffff" },
children: [],
},
},
};
// Render to PNG (requires @resvg/resvg-js)
const png = await renderToPng(spec, { fonts });
// Or render to SVG string
import { renderToSvg } from "@json-render/image/render";
const svg = await renderToSvg(spec, { fonts });
Three.js (3D)
import { defineCatalog } from "@json-render/core";
import { schema, defineRegistry } from "@json-render/react";
import {
threeComponentDefinitions,
threeComponents,
ThreeCanvas,
} from "@json-render/react-three-fiber";
const catalog = defineCatalog(schema, {
components: {
Box: threeComponentDefinitions.Box,
Sphere: threeComponentDefinitions.Sphere,
AmbientLight: threeComponentDefinitions.AmbientLight,
DirectionalLight: threeComponentDefinitions.DirectionalLight,
GaussianSplat: threeComponentDefinitions.GaussianSplat,
OrbitControls: threeComponentDefinitions.OrbitControls,
},
actions: {},
});
const { registry } = defineRegistry(catalog, {
components: {
Box: threeComponents.Box,
Sphere: threeComponents.Sphere,
AmbientLight: threeComponents.AmbientLight,
DirectionalLight: threeComponents.DirectionalLight,
GaussianSplat: threeComponents.GaussianSplat,
OrbitControls: threeComponents.OrbitControls,
},
});
<ThreeCanvas
spec={spec}
registry={registry}
shadows
camera={{ position: [5, 5, 5], fov: 50 }}
style={{ width: "100%", height: "100vh" }}
/>;
Next.js (Full Apps)
import type { NextAppSpec } from "@json-render/next";
import { createNextApp } from "@json-render/next/server";
import { NextAppProvider } from "@json-render/next";
const spec: NextAppSpec = {
metadata: { title: { default: "My App", template: "%s | My App" } },
layouts: {
main: {
root: "shell",
elements: {
shell: { type: "Container", props: {}, children: ["nav", "slot"] },
nav: { type: "NavBar", props: {}, children: [] },
slot: { type: "Slot", props: {}, children: [] },
},
},
},
routes: {
"/": {
layout: "main",
metadata: { title: "Home" },
page: {
root: "hero",
elements: {
hero: { type: "Card", props: { title: "Welcome" }, children: [] },
},
},
},
},
};
// Server: creates Page, generateMetadata, generateStaticParams
const app = createNextApp({ spec });
// Client: wrap your layout with NextAppProvider
// <NextAppProvider registry={registry} handlers={handlers}>
// {children}
// </NextAppProvider>
shadcn-svelte (Svelte)
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/svelte/schema";
import { defineRegistry, Renderer } from "@json-render/svelte";
import { shadcnComponentDefinitions } from "@json-render/shadcn-svelte/catalog";
import { shadcnComponents } from "@json-render/shadcn-svelte";
const catalog = defineCatalog(schema, {
components: {
Card: shadcnComponentDefinitions.Card,
Stack: shadcnComponentDefinitions.Stack,
Heading: shadcnComponentDefinitions.Heading,
Button: shadcnComponentDefinitions.Button,
},
actions: {},
});
const { registry } = defineRegistry(catalog, {
components: {
Card: shadcnComponents.Card,
Stack: shadcnComponents.Stack,
Heading: shadcnComponents.Heading,
Button: shadcnComponents.Button,
},
});
// In your Svelte component:
// <Renderer spec={spec} registry={registry} />
Devtools
Drop-in inspector panel for any json-render app. Spec tree, state editor, action log, stream log, catalog browser, DOM picker.
// React
import { JsonRenderDevtools } from "@json-render/devtools-react";
<JSONUIProvider registry={registry} handlers={handlers}>
<Renderer spec={spec} registry={registry} />
<JsonRenderDevtools spec={spec} catalog={catalog} messages={messages} />
</JSONUIProvider>;
Floating toggle appears bottom-right. Hotkey: Ctrl/Cmd + Shift + J. Tree-shakes to null in production.
Available for React, Vue, Svelte, and Solid — swap @json-render/devtools-react for the adapter that matches your renderer.
Ink (Terminal)
import { defineCatalog } from "@json-render/core";
import {
schema,
standardComponentDefinitions,
standardActionDefinitions,
defineRegistry,
Renderer,
JSONUIProvider,
} from "@json-render/ink";
const catalog = defineCatalog(schema, {
components: { ...standardComponentDefinitions },
actions: standardActionDefinitions,
});
const { registry } = defineRegistry(catalog, { components: {} });
const spec = {
root: "card-1",
elements: {
"card-1": {
type: "Card",
props: { title: "Status" },
children: ["status-1"],
},
"status-1": {
type: "StatusLine",
props: { label: "Build", status: "success" },
children: [],
},
},
};
<JSONUIProvider initialState={{}}>
<Renderer spec={spec} registry={registry} />
</JSONUIProvider>;
Features
Streaming (SpecStream)
Stream AI responses progressively:
import { createSpecStreamCompiler } from "@json-render/core";
const compiler = createSpecStreamCompiler<MySpec>();
// Process chunks as they arrive
const { result, newPatches } = compiler.push(chunk);
setSpec(result); // Update UI with partial result
// Get final result
const finalSpec = compiler.getResult();
AI Prompt Generation
Generate system prompts from your catalog:
const systemPrompt = catalog.prompt();
// Includes component descriptions, props schemas, available actions
Conditional Visibility
{
"type": "Alert",
"props": { "message": "Error occurred" },
"visible": [
{ "$state": "/form/hasError" },
{ "$state": "/form/errorDismissed", "not": true }
]
}
Dynamic Props
Any prop value can be data-driven using expressions:
{
"type": "Icon",
"props": {
"name": {
"$cond": { "$state": "/activeTab", "eq": "home" },
"$then": "home",
"$else": "home-outline"
},
"color": {
"$cond": { "$state": "/activeTab", "eq": "home" },
"$then": "#007AFF",
"$else": "#8E8E93"
}
}
}
Expression forms:
{ "$state": "/state/key" }- reads a value from the state model{ "$cond": <condition>, "$then": <value>, "$else": <value> }- evaluates a condition and picks a branch{ "$template": "Hello, ${/user/name}!" }- interpolates state values into strings{ "$computed": "fn", "args": { ... } }- calls a registered function with resolved args
Actions
Components can trigger actions, including the built-in setState action:
{
"type": "Pressable",
"props": {
"action": "setState",
"actionParams": { "statePath": "/activeTab", "value": "home" }
},
"children": ["home-icon"]
}
The setState action updates the state model directly, which re-evaluates visibility conditions and dynamic prop expressions.
State Watchers
React to state changes by triggering actions:
{
"type": "Select",
"props": {
"value": { "$bindState": "/form/country" },
"options": ["US", "Canada", "UK"]
},
"watch": {
"/form/country": {
"action": "loadCities",
"params": { "country": { "$state": "/form/country" } }
}
}
}
watch is a top-level field on elements (sibling of type/props/children). Watchers fire when the watched value changes, not on initial render.
Demo
git clone https://github.com/vercel-labs/json-render
cd json-render
pnpm install
pnpm dev
- http://json-render.localhost:1355 - Docs & Playground
- http://dashboard-demo.json-render.localhost:1355 - Example Dashboard
- http://react-email-demo.json-render.localhost:1355 - React Email Example
- http://remotion-demo.json-render.localhost:1355 - Remotion Video Example
- Chat Example: run
pnpm devinexamples/chat - Svelte Example: run
pnpm devinexamples/svelteorexamples/svelte-chat - Vue Example: run
pnpm devinexamples/vue - Vite Renderers (React + Vue + Svelte + Solid): run
pnpm devinexamples/vite-renderers - React Native example: run
npx expo startinexamples/react-native - Gaussian Splatting (R3F): run
pnpm devinexamples/react-three-fiber-gsplat - Gaussian Splatting (experimental standalone gsplat.js demo): run
pnpm devinexamples/gsplat
How It Works
flowchart LR
A[User Prompt] --> B[AI + Catalog]
B --> C[JSON Spec]
C --> D[Renderer]
B -.- E([guardrailed])
C -.- F([predictable])
D -.- G([streamed])
- Define the guardrails - what components, actions, and data bindings AI can use
- Prompt - describe what you want in natural language
- AI generates JSON - output is always predictable, constrained to your catalog
- Render fast - stream and render progressively as the model responds
License
Apache-2.0
Repo liên quan
Superpowers is an open-source (MIT) skills library and bootstrap instruction set that turns a coding agent's ad-hoc habits into a fixed pipeline: brainstorm a spec, write a plan, build under TDD, review, then close out the branch. Skills trigger automatically once installed, and the same methodology works across eleven different agent harnesses, each requiring its own install step.
TensorFlow is Google's open-source, end-to-end platform for machine learning, hosted at tensorflow/tensorflow with 196,995 stars and 76,009 forks under the Apache-2.0 license. It was originally built within Google Brain's Machine Intelligence team for ML and neural network research, and today it ships stable Python and C++ APIs alongside GPU, CPU-only, and Docker install paths. The README positions it as covering both research work and shipping ML-powered applications.
DigitalPlat FreeDomain: Free Domain For Everyone
AutoGPT is an open-source platform for building, deploying, and running AI agents that automate complete workflows. Users can define tasks in plain English using AutoPilot or visually construct steps with the Build interface. The project offers both a managed, hosted platform that handles infrastructure and model access, and a self-hosting option where users provide their own infrastructure and API keys. AutoGPT agents are designed to automate tasks across various domains, including executive operations, sales, and engineering, and integrate with over 45 platforms like Gmail and GitHub. While its `autogpt_platform/` component is licensed under Polyform Shield, the original `classic/` agent and other parts of the project use the MIT License.
Trả lời nhanh
Đọc thêm về vercel-labs/json-render ở đâu?
Trang TopGit này là một snapshot — tab "Readme" hiển thị nguyên văn README của repo (đã bỏ link, giữ ảnh). Repo GitHub ở github.com/vercel-labs/json-render là nguồn chính thức.
vercel-labs/json-render có bao nhiêu sao?
vercel-labs/json-render có 15.8k sao GitHub — tải lại trang để xem số mới nhất, hoặc xem trực tiếp github.com/vercel-labs/json-render. TopGit phản chiếu số sao của GitHub nhưng không cam kết đến từng phút.
vercel-labs/json-render có phải mã nguồn mở không?
Có — vercel-labs/json-render phát hành theo license Apache-2.0, nghĩa là mã nguồn mở để đọc, fork và (tùy license) tái sử dụng. Mã: github.com/vercel-labs/json-render.
vercel-labs/json-render còn đang phát triển không?
Commit gần nhất trên vercel-labs/json-render là 1 tháng trước (theo timestamp GitHub). Repo có 857 fork — một chỉ báo về mức độ quan tâm của cộng đồng.
vercel-labs/json-render là gì?
vercel-labs/json-render (vercel-labs/json-render) là dự án TypeScript trên GitHub. Theo mô tả gốc: The Generative UI framework
vercel-labs/json-render so với các dự án AI Tools khác thế nào?
vercel-labs/json-render được TopGit xếp vào nhóm AI Tools, với 15.8k sao GitHub và viết bằng TypeScript. Xem trang chủ đề AI Tools trên TopGit để so sánh với các dự án tương tự theo số sao và mức độ hoạt động.
Đọc đầy đủ README ở tab phía trên.
Vẫn đang phân vân về json-render?
Một cú bấm sẽ gửi câu hỏi kèm trang này cho AI — xem AI nói gì về json-render.