generative-ui

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Generative UI

生成式UI

Build generative UI apps with Tambo — create rich, interactive React components from natural language.
使用Tambo构建生成式UI应用——通过自然语言创建丰富的交互式React组件。

Reference Guides

参考指南

For deeper implementation details beyond bootstrap flow, load:
  • components
  • component-rendering
  • threads
  • tools-and-context
  • cli
These references are duplicated across both skills so each skill works independently.
如需了解引导流程之外的更深入实现细节,请查看:
  • components
  • component-rendering
  • threads
  • tools-and-context
  • cli
这些参考内容在两个技能中重复提供,以便每个技能都能独立运行。

One-Prompt Flow

单提示流程

The goal is to get the user from zero to a running app in a single prompt. Ask all questions upfront using AskUserQuestion with multiple questions, then execute everything without stopping.
目标是让用户通过一次提示就能从无到有运行起应用。使用AskUserQuestion一次性提出所有问题,然后无需停顿地执行所有操作。

Step 1: Gather All Non-Sensitive Preferences (Single AskUserQuestion Call)

步骤1:收集所有非敏感偏好(单次AskUserQuestion调用)

Use AskUserQuestion with up to 4 questions in ONE call. The API key is collected as free-text input here — no follow-up needed.
Question 1: What do you want to build?
Ask the user what kind of app they're building. This drives which starter components to create. Examples: "a dashboard", "a chatbot", "a data visualization tool", "a task manager". If the user already said what they want in their initial message, skip this question.
Question 2: Framework
Options:
  • Next.js (Recommended) - Full-stack React with App Router
  • Vite - Fast, lightweight React setup
Question 3: API Key
Do NOT use AskUserQuestion for the API key. Instead, after collecting the other preferences, explicitly ask the user in a plain text message to paste their API key. Say something like:
"Paste your Tambo API key below (get one at https://console.tambo.co). This is a client-side public key (like NEXT_PUBLIC_TAMBO_API_KEY) — not a secret, safe to share here. Or just say 'skip' if you don't have one yet."
Then wait for their response. If they paste a key (starts with
tambo_
), use it. If they say "skip" or similar, move on without it.
This means Step 1 only has 3 questions in AskUserQuestion (app idea, framework, app name). The API key is collected as a plain message exchange right after.
Question 4: App name
Let the user pick a name for their project directory. Default suggestion: derive from what they want to build (e.g., "my-dashboard", "my-chatbot"). Use kebab-case (letters, numbers, hyphens only). If the user gives a non-slug name like "Sales Dashboard", propose
sales-dashboard
instead.
Skip questions when the user already told you the answer. If they said "build me a Next.js dashboard app called analytics", you already know the framework, the app idea, and the name — just ask for the API key.
使用AskUserQuestion在一次调用中提出最多4个问题。API密钥在此处作为纯文本输入收集——无需后续跟进。
问题1:你想要构建什么?
询问用户要构建的应用类型。这将决定要创建哪些初始组件。示例:"一个仪表板"、"一个聊天机器人"、"一个数据可视化工具"、"一个任务管理器"。如果用户在初始消息中已经说明需求,跳过此问题。
问题2:框架选择
选项:
  • Next.js(推荐)- 带App Router的全栈React框架
  • Vite - 快速、轻量的React开发环境
问题3:API密钥
请勿使用AskUserQuestion获取API密钥。在收集完其他偏好后,用纯文本消息明确要求用户粘贴其API密钥。例如可以说:
然后等待用户回复。如果用户粘贴了密钥(以
tambo_
开头),则使用该密钥。如果用户回复"skip"或类似内容,则跳过此步骤继续后续操作。
这意味着步骤1中AskUserQuestion仅包含3个问题(应用需求、框架、应用名称)。API密钥在之后通过纯文本消息交互收集。
问题4:应用名称
让用户选择项目目录的名称。默认建议:根据用户的应用需求生成(例如"my-dashboard"、"my-chatbot")。使用短横线分隔格式(仅包含字母、数字和短横线)。如果用户提供的是非短横线格式的名称,如"Sales Dashboard",则建议使用
sales-dashboard
替代。
如果用户已在初始消息中说明答案,跳过对应问题。如果用户说"帮我构建一个名为analytics的Next.js仪表板应用",那么你已经知道框架、应用需求和名称——只需询问API密钥即可。

Step 2: Execute Everything (No Stopping)

步骤2:执行所有操作(无需停顿)

Run all of these sequentially without asking for confirmation between steps. If any command fails, stop the flow, surface the error, and ask the user how to proceed — do not continue to later steps.
All templates (
standard
,
vite
,
analytics
) come with chat UI, TamboProvider wiring, component registry, and starter components already included. You do NOT need to add chat UI or wire up the app — just scaffold, configure the API key, add custom components, and start the server.
按顺序运行以下所有操作,步骤之间无需确认。如果任何命令失败,停止流程,显示错误信息,并询问用户如何处理——不要继续后续步骤。
所有模板(
standard
vite
analytics
)都已包含聊天UI、TamboProvider配置、组件注册表和初始组件。你无需添加聊天UI或配置应用——只需搭建项目、配置API密钥、添加自定义组件并启动服务器。

2a. Scaffold the project

2a. 搭建项目框架

For Next.js (recommended):
bash
npx tambo create-app <app-name> --template=standard --skip-tambo-init
cd <app-name>
For Vite:
bash
npx tambo create-app <app-name> --template=vite --skip-tambo-init
cd <app-name>
Use
--skip-tambo-init
since
create-app
normally tries to run
tambo init
interactively, which won't work in non-interactive environments like coding agents. We handle the API key in the next step.
对于Next.js(推荐):
bash
npx tambo create-app <app-name> --template=standard --skip-tambo-init
cd <app-name>
对于Vite:
bash
npx tambo create-app <app-name> --template=vite --skip-tambo-init
cd <app-name>
使用
--skip-tambo-init
参数,因为
create-app
通常会尝试交互式运行
tambo init
,这在编码代理等非交互式环境中无法正常工作。我们将在下一步处理API密钥配置。

2b. Set up API key

2b. 设置API密钥

If the user provided a key:
bash
npx tambo init --api-key=<USER_PROVIDED_KEY>
This writes the key to the correct
.env
file with the framework-appropriate variable name (
NEXT_PUBLIC_TAMBO_API_KEY
,
VITE_TAMBO_API_KEY
, etc.).
If the user skipped, tell them once at the end to run
npx tambo init
when ready. Don't nag about it during setup.
IMPORTANT: Do NOT hardcode
--api-key=sk_...
in commands you run. The
--api-key
flag should only be used with an actual key the user has provided.
如果用户提供了密钥:
bash
npx tambo init --api-key=<USER_PROVIDED_KEY>
这会将密钥写入正确的
.env
文件,并使用适合对应框架的变量名(
NEXT_PUBLIC_TAMBO_API_KEY
VITE_TAMBO_API_KEY
等)。
如果用户跳过了密钥设置,在流程结束时提醒他们一次,待准备好后运行
npx tambo init
即可。在设置过程中不要反复提及此事。
重要提示: 请勿在运行的命令中硬编码
--api-key=sk_...
--api-key
标志仅应与用户提供的实际密钥一起使用。

2c. Create custom starter components

2c. 创建自定义初始组件

The template includes basic components, but add 1-2 components tailored to what the user wants to build. Don't use generic examples:
  • Dashboard app
    StatsCard
    ,
    DataTable
  • Chatbot
    BotResponse
    with markdown support
  • Data visualization
    Chart
    with configurable data
  • Task manager
    TaskCard
    ,
    TaskBoard
  • Generic / unclear
    ContentCard
Each component needs:
  1. A Zod schema with
    .describe()
    on every field
  2. The React component itself
  3. Registration in the existing component registry (
    lib/tambo.ts
    — add to the existing
    components
    array, don't replace it)
Schema constraints — Tambo will reject invalid schemas at runtime:
  • No
    z.record()
    — Record types (objects with dynamic keys) are not supported anywhere in the schema, including nested inside arrays or objects. Use
    z.object()
    with explicit named keys instead.
  • No
    z.map()
    or
    z.set()
    — Use arrays and objects instead.
  • For tabular data like rows, use
    z.array(z.object({ col1: z.string(), col2: z.number() }))
    with explicit column keys — NOT
    z.array(z.record(z.string(), z.unknown()))
    .
React best practices for generated components:
  • Always add unique
    key
    props when rendering lists (
    .map()
    ). Use a unique field from the data (like
    id
    ) — not the array index.
  • Include an
    id
    field (e.g.,
    z.string().describe("Unique identifier")
    ) in schemas for array items so there's always a stable key available.
Example:
tsx
// src/components/StatsCard.tsx
import { z } from "zod/v4";

export const StatsCardSchema = z.object({
  title: z.string().describe("Metric name"),
  value: z.number().describe("Current value"),
  change: z.number().optional().describe("Percent change from previous period"),
  trend: z.enum(["up", "down", "flat"]).optional().describe("Trend direction"),
});

type StatsCardProps = z.infer<typeof StatsCardSchema>;

export function StatsCard({
  title,
  value,
  change,
  trend = "flat",
}: StatsCardProps) {
  // ... implementation with Tailwind styling
}
Then add to the existing registry in
lib/tambo.ts
:
tsx
// Add to the existing components array — don't replace what's already there
// Next.js: import { StatsCard, StatsCardSchema } from "@/components/StatsCard";
// Vite: import { StatsCard, StatsCardSchema } from "../components/StatsCard";
import { StatsCard, StatsCardSchema } from "@/components/StatsCard";

// ... existing components ...
{
  name: "StatsCard",
  component: StatsCard,
  description: "Displays a metric with value and trend. Use when user asks about stats, metrics, or KPIs.",
  propsSchema: StatsCardSchema,
},
模板中包含基础组件,但需添加1-2个符合用户需求的定制组件。请勿使用通用示例:
  • 仪表板应用
    StatsCard
    DataTable
  • 聊天机器人 → 支持markdown的
    BotResponse
  • 数据可视化工具 → 可配置数据的
    Chart
  • 任务管理器
    TaskCard
    TaskBoard
  • 通用/需求不明确
    ContentCard
每个组件需要包含:
  1. 每个字段都带有
    .describe()
    的Zod schema
  2. React组件本身
  3. 在现有组件注册表中注册(
    lib/tambo.ts
    ——添加到现有的
    components
    数组中,不要替换原有内容)
Schema约束——Tambo在运行时会拒绝无效的schema:
  • 禁止使用
    z.record()
    ——记录类型(带有动态键的对象)在schema的任何位置都不被支持,包括数组或对象内部。请改用带有明确命名键的
    z.object()
  • 禁止使用
    z.map()
    z.set()
    ——请改用数组和对象。
  • 对于表格数据(如行),请使用
    z.array(z.object({ col1: z.string(), col2: z.number() }))
    并带有明确的列键——不要使用
    z.array(z.record(z.string(), z.unknown()))
生成组件的React最佳实践:
  • 渲染列表(
    .map()
    )时始终添加唯一的
    key
    属性。使用数据中的唯一字段(如
    id
    )——不要使用数组索引。
  • 在数组项的schema中包含
    id
    字段(例如
    z.string().describe("唯一标识符")
    ),以便始终有稳定的key可用。
示例:
tsx
// src/components/StatsCard.tsx
import { z } from "zod/v4";

export const StatsCardSchema = z.object({
  title: z.string().describe("指标名称"),
  value: z.number().describe("当前数值"),
  change: z.number().optional().describe("与上期相比的变化百分比"),
  trend: z.enum(["up", "down", "flat"]).optional().describe("趋势方向"),
});

type StatsCardProps = z.infer<typeof StatsCardSchema>;

export function StatsCard({
  title,
  value,
  change,
  trend = "flat",
}: StatsCardProps) {
  // ... 使用Tailwind样式的实现代码
}
然后添加到
lib/tambo.ts
中的现有注册表:
tsx
// 添加到现有的components数组中——不要替换原有内容
// Next.js: import { StatsCard, StatsCardSchema } from "@/components/StatsCard";
// Vite: import { StatsCard, StatsCardSchema } from "../components/StatsCard";
import { StatsCard, StatsCardSchema } from "@/components/StatsCard";

// ... 现有组件 ...
{
  name: "StatsCard",
  component: StatsCard,
  description: "显示带有数值和趋势的指标。当用户询问统计数据、指标或KPI时使用。",
  propsSchema: StatsCardSchema,
},

2d. Start the dev server

2d. 启动开发服务器

Only start the dev server after all code changes (scaffolding, init, component creation, registry updates) are complete.
bash
npm run dev
Run this in the background so the user can see their app immediately.
仅在所有代码变更(项目搭建、初始化、组件创建、注册表更新)完成后启动开发服务器。
bash
npm run dev
在后台运行此命令,以便用户能立即看到他们的应用。

Step 3: Summary

步骤3:总结

After everything is running, give a brief summary:
  • What was set up
  • What components were created and what they do
  • The URL where the app is running (typically
    http://localhost:3000
    for Next.js,
    http://localhost:5173
    for Vite)
  • If they skipped the API key: remind them once to run
    npx tambo init
    to set it up
  • A suggestion for what to try first (e.g., "Try asking it to show you a stats card for monthly revenue")
所有操作完成后,提供简要总结:
  • 已搭建的内容
  • 创建的组件及其功能
  • 应用运行的URL(Next.js通常为
    http://localhost:3000
    ,Vite通常为
    http://localhost:5173
  • 如果用户跳过了API密钥设置:提醒他们一次,待准备好后运行
    npx tambo init
    进行配置
  • 首次尝试的建议(例如:"尝试让它展示月度收入的统计卡片")

Technology Stacks Reference

技术栈参考

Recommended Stack (Default)

推荐技术栈(默认)

Next.js 14+ (App Router)
├── TypeScript
├── Tailwind CSS
├── Zod (for schemas)
└── @tambo-ai/react
bash
npx tambo create-app my-app --template=standard
Next.js 14+ (App Router)
├── TypeScript
├── Tailwind CSS
├── Zod(用于schema)
└── @tambo-ai/react
bash
npx tambo create-app my-app --template=standard

Vite Stack

Vite技术栈

Vite + React
├── TypeScript
├── Tailwind CSS
├── Zod
└── @tambo-ai/react
Vite + React
├── TypeScript
├── Tailwind CSS
├── Zod
└── @tambo-ai/react

Minimal Stack (No Tailwind)

极简技术栈(无Tailwind)

Vite + React
├── TypeScript
├── Plain CSS
├── Zod
└── @tambo-ai/react
Vite + React
├── TypeScript
├── 纯CSS
├── Zod
└── @tambo-ai/react

Component Registry Pattern

组件注册表模式

Every generative component must be registered:
tsx
import { TamboComponent } from "@tambo-ai/react";
import { ComponentName, ComponentNameSchema } from "@/components/ComponentName";

export const components: TamboComponent[] = [
  {
    name: "ComponentName",
    component: ComponentName,
    description: "What it does. When to use it.",
    propsSchema: ComponentNameSchema,
  },
];
Key rules:
  • propsSchema: Zod object with
    .describe()
    on every field — this is how the AI knows what to pass
  • description: Tell the AI when to use this component — be specific about trigger phrases
  • Streaming: Props arrive incrementally, so handle undefined gracefully (optional fields or defaults)
每个生成式组件都必须注册:
tsx
import { TamboComponent } from "@tambo-ai/react";
import { ComponentName, ComponentNameSchema } from "@/components/ComponentName";

export const components: TamboComponent[] = [
  {
    name: "ComponentName",
    component: ComponentName,
    description: "组件功能及使用场景。",
    propsSchema: ComponentNameSchema,
  },
];
核心规则:
  • propsSchema:每个字段都带有
    .describe()
    的Zod对象——AI通过此了解需要传递的参数
  • description:告知AI何时使用该组件——明确说明触发短语
  • 流式传输:参数会增量传递,因此需优雅处理未定义的情况(可选字段或默认值)

Adding More Chat UI (Optional)

添加更多聊天UI(可选)

Templates already include chat UI. These are only needed if the user wants additional UI primitives beyond what the template provides:
bash
npx tambo add message-thread-full --yes    # Complete chat interface
npx tambo add control-bar --yes            # Controls and actions
npx tambo add canvas-space --yes           # Rendered component display area
npx tambo add thread-history --yes         # Conversation history sidebar
模板中已包含聊天UI。仅当用户需要模板之外的额外UI原语时,才需要使用以下命令:
bash
npx tambo add message-thread-full --yes    # 完整的聊天界面
npx tambo add control-bar --yes            # 控制栏及操作按钮
npx tambo add canvas-space --yes           # 渲染组件的展示区域
npx tambo add thread-history --yes         # 对话历史侧边栏

Supported Technologies

支持的技术

TechnologySupport LevelNotes
Next.js 14+FullRecommended, App Router preferred
ViteFullGreat for SPAs
Create React AppPartialWorks but CRA is deprecated
RemixPartialWorks with client components
TypeScriptFullStrongly recommended
JavaScriptFullWorks but less type safety
Tailwind CSSFullDefault for CLI components
Plain CSSFullNeed custom component styling
CSS ModulesFullSupported
ZodRequiredUsed for all schemas
技术支持等级说明
Next.js 14+完全支持推荐使用,优先选择App Router
Vite完全支持非常适合单页应用
Create React App部分支持可运行但CRA已被弃用
Remix部分支持可与客户端组件配合使用
TypeScript完全支持强烈推荐
JavaScript完全支持可运行但类型安全性较低
Tailwind CSS完全支持CLI组件的默认样式方案
纯CSS完全支持需要自定义组件样式
CSS Modules完全支持已兼容
Zod必须使用所有schema均依赖此库
",