add-components-to-registry

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Add Components to Registry

向注册表添加组件

Convert existing React components into Tambo-registered components that AI can render.
将现有React组件转换为AI可渲染的Tambo注册组件。

Quick Start

快速开始

bash
undefined
bash
undefined

Point to a component file or folder

指向组件文件或文件夹

/add-components-to-registry src/components/ProductCard.tsx /add-components-to-registry src/components/cards/
undefined
/add-components-to-registry src/components/ProductCard.tsx /add-components-to-registry src/components/cards/
undefined

Workflow

工作流程

  1. Read component(s) - Analyze props, types, and purpose
  2. Generate Zod schema - Create propsSchema from prop types
  3. Write description - Help AI know when to use it
  4. Add to registry - Update lib/tambo.ts
  1. 读取组件 - 分析Props、类型和用途
  2. 生成Zod Schema - 根据Prop类型创建propsSchema
  3. 编写描述 - 帮助AI了解何时使用该组件
  4. 添加到注册表 - 更新lib/tambo.ts

Step 1: Analyze Component

步骤1:分析组件

Read the component file and extract:
  • Component name
  • Props interface/type
  • What it renders (for description)
  • Optional vs required props
读取组件文件并提取以下信息:
  • 组件名称
  • Props接口/类型
  • 组件渲染内容(用于描述)
  • 可选与必填Props

Example Input

输入示例

tsx
// src/components/ProductCard.tsx
interface ProductCardProps {
  name: string;
  price: number;
  imageUrl?: string;
  onSale?: boolean;
  rating?: number;
}

export function ProductCard({
  name,
  price,
  imageUrl,
  onSale,
  rating,
}: ProductCardProps) {
  return (
    <div className="product-card">
      {imageUrl && <img src={imageUrl} alt={name} />}
      <h3>{name}</h3>
      <p>
        ${price}
        {onSale && " (On Sale!)"}
      </p>
      {rating && <span>{rating}/5</span>}
    </div>
  );
}
tsx
// src/components/ProductCard.tsx
interface ProductCardProps {
  name: string;
  price: number;
  imageUrl?: string;
  onSale?: boolean;
  rating?: number;
}

export function ProductCard({
  name,
  price,
  imageUrl,
  onSale,
  rating,
}: ProductCardProps) {
  return (
    <div className="product-card">
      {imageUrl && <img src={imageUrl} alt={name} />}
      <h3>{name}</h3>
      <p>
        ${price}
        {onSale && " (On Sale!)"}
      </p>
      {rating && <span>{rating}/5</span>}
    </div>
  );
}

Step 2: Generate Zod Schema

步骤2:生成Zod Schema

Convert TypeScript types to Zod with
.describe()
:
tsx
import { z } from "zod";

export const ProductCardSchema = z.object({
  name: z.string().describe("Product name"),
  price: z.number().describe("Price in dollars"),
  imageUrl: z.string().optional().describe("Product image URL"),
  onSale: z.boolean().optional().describe("Whether product is on sale"),
  rating: z.number().optional().describe("Rating out of 5"),
});
将TypeScript类型转换为带
.describe()
的Zod Schema:
tsx
import { z } from "zod";

export const ProductCardSchema = z.object({
  name: z.string().describe("Product name"),
  price: z.number().describe("Price in dollars"),
  imageUrl: z.string().optional().describe("Product image URL"),
  onSale: z.boolean().optional().describe("Whether product is on sale"),
  rating: z.number().optional().describe("Rating out of 5"),
});

Type Mapping

类型映射

TypeScriptZod
string
z.string()
number
z.number()
boolean
z.boolean()
string[]
z.array(z.string())
"a" | "b"
z.enum(["a", "b"])
optional
.optional()
Date
z.string().describe("ISO date string")
Record<K,V>
z.record(z.string(), z.number())
TypeScriptZod
string
z.string()
number
z.number()
boolean
z.boolean()
string[]
z.array(z.string())
"a" | "b"
z.enum(["a", "b"])
optional
.optional()
Date
z.string().describe("ISO date string")
Record<K,V>
z.record(z.string(), z.number())

Step 3: Write Description

步骤3:编写描述

The description tells AI when to render this component. Be specific:
tsx
// Bad: Too vague
description: "Shows a product";

// Good: Tells AI when to use it
description: "Displays a product with name, price, and optional image/rating. Use when user asks to see product details, browse items, or view catalog entries.";
描述用于告知AI何时渲染该组件,请尽可能具体:
tsx
// 不佳:过于模糊
description: "Shows a product";

// 良好:明确告知AI使用场景
description: "Displays a product with name, price, and optional image/rating. Use when user asks to see product details, browse items, or view catalog entries.";

Step 4: Add to Registry

步骤4:添加到注册表

tsx
// lib/tambo.ts
import { TamboComponent } from "@tambo-ai/react";
import { ProductCard } from "@/components/ProductCard";
import { ProductCardSchema } from "@/components/ProductCard.schema";

export const components: TamboComponent[] = [
  {
    name: "ProductCard",
    component: ProductCard,
    description:
      "Displays a product with name, price, and optional image/rating. Use when user asks to see product details, browse items, or view catalog entries.",
    propsSchema: ProductCardSchema,
  },
  // ... other components
];
tsx
// lib/tambo.ts
import { TamboComponent } from "@tambo-ai/react";
import { ProductCard } from "@/components/ProductCard";
import { ProductCardSchema } from "@/components/ProductCard.schema";

export const components: TamboComponent[] = [
  {
    name: "ProductCard",
    component: ProductCard,
    description:
      "Displays a product with name, price, and optional image/rating. Use when user asks to see product details, browse items, or view catalog entries.",
    propsSchema: ProductCardSchema,
  },
  // ... 其他组件
];

Batch Registration

批量注册

When given a folder, process all
.tsx
files:
src/components/cards/
├── ProductCard.tsx    → Register as "ProductCard"
├── UserCard.tsx       → Register as "UserCard"
├── StatCard.tsx       → Register as "StatCard"
└── index.ts           → Skip (barrel file)
Skip files that:
  • Are barrel exports (index.ts)
  • Don't export React components
  • Are test files (_.test.tsx, _.spec.tsx)
  • Are story files (*.stories.tsx)
当指定文件夹时,将处理所有
.tsx
文件:
src/components/cards/
├── ProductCard.tsx    → 注册为"ProductCard"
├── UserCard.tsx       → 注册为"UserCard"
├── StatCard.tsx       → 注册为"StatCard"
└── index.ts           → 跳过(桶文件)
以下文件将被跳过:
  • 桶导出文件(index.ts)
  • 未导出React组件的文件
  • 测试文件(.test.tsx、.spec.tsx)
  • 故事文件(*.stories.tsx)

Schema File Location

Schema文件位置

Place schemas next to components:
src/components/
├── ProductCard.tsx
├── ProductCard.schema.ts    # Zod schema
├── UserCard.tsx
└── UserCard.schema.ts
Or in a dedicated schemas folder:
src/
├── components/
│   ├── ProductCard.tsx
│   └── UserCard.tsx
└── schemas/
    ├── ProductCard.schema.ts
    └── UserCard.schema.ts
将Schema文件放在组件旁边:
src/components/
├── ProductCard.tsx
├── ProductCard.schema.ts    # Zod Schema
├── UserCard.tsx
└── UserCard.schema.ts
或者放在专门的schemas文件夹中:
src/
├── components/
│   ├── ProductCard.tsx
│   └── UserCard.tsx
└── schemas/
    ├── ProductCard.schema.ts
    └── UserCard.schema.ts

Handling Complex Props

处理复杂Props

Nested Objects

嵌套对象

tsx
// TypeScript
interface Address {
  street: string;
  city: string;
  zip: string;
}
interface Props {
  address: Address;
}

// Zod
const AddressSchema = z.object({
  street: z.string().describe("Street address"),
  city: z.string().describe("City name"),
  zip: z.string().describe("ZIP/postal code"),
});

const PropsSchema = z.object({
  address: AddressSchema.describe("Shipping address"),
});
tsx
// TypeScript
interface Address {
  street: string;
  city: string;
  zip: string;
}
interface Props {
  address: Address;
}

// Zod
const AddressSchema = z.object({
  street: z.string().describe("Street address"),
  city: z.string().describe("City name"),
  zip: z.string().describe("ZIP/postal code"),
});

const PropsSchema = z.object({
  address: AddressSchema.describe("Shipping address"),
});

Callbacks (Skip)

回调函数(跳过)

Don't include callbacks in propsSchema - AI can't provide functions:
tsx
// TypeScript
interface Props {
  name: string;
  onClick: () => void; // Skip this
}

// Zod - only data props
const PropsSchema = z.object({
  name: z.string().describe("Display name"),
  // onClick omitted - AI provides data, not behavior
});
不要在propsSchema中包含回调函数——AI无法提供函数:
tsx
// TypeScript
interface Props {
  name: string;
  onClick: () => void; // 跳过此项
}

// Zod - 仅包含数据类Props
const PropsSchema = z.object({
  name: z.string().describe("Display name"),
  // onClick 已省略 - AI仅提供数据,不处理行为
});

Children (Skip)

子元素(跳过)

Don't include children - AI renders the component, doesn't compose it:
tsx
// Skip children prop in schema
不要包含子元素——AI负责渲染组件,而非组合组件:
tsx
// 在Schema中跳过children prop

Verification

验证

After registration, verify in the chat:
"Show me a product card for a laptop priced at $999"
AI should render the ProductCard with appropriate props.
注册完成后,在聊天中进行验证:
"Show me a product card for a laptop priced at $999"
AI应渲染带有合适Props的ProductCard组件。