构建一个实时 tldraw 白板,带 Velt Comments,嵌入 ChatGPT 🤯🔥
Source: Dev.to
我们要构建的内容
我们正在构建一个可以通过 ChatGPT 控制的协作白板。你可以让 ChatGPT 添加形状、放置便利贴或更改布局,白板会即时更新。你的团队成员可以加入白板,实时看到变化,并直接在画布上留下评论。
我们将使用 TLDraw 作为画布,Velt 负责实时协作,并使用 Model Context Protocol (MCP) 将所有内容连接到 ChatGPT。完成后,你将拥有一个可在 ChatGPT 内部运行、能够响应自然语言的功能性白板应用。
理解基础
一个 GPT 应用由两部分组成:
- Web 小部件 – 在 ChatGPT 内渲染的 UI(我们的白板画布)。
- MCP 服务器 – 一个 Node.js 服务,定义 ChatGPT 可以调用的工具(例如 “添加矩形”)。
当你说 “画一个矩形” 时,ChatGPT 读取工具定义,调用你的 MCP 服务器,服务器随后更新画布。

TLDraw
- 负责画布、绘图工具、形状、文字。
- 通过
@tldraw/sync提供实时白板同步——同一房间的所有人都会即时看到更新。
Velt
- 提供协作功能:评论、实时光标、在场指示器。
- 通过前端的 React 组件和后端的 REST API 工作。
这两个库负责构建 UI;MCP 服务器则将 UI 与 ChatGPT 连接。
MCP 服务器
MCP 服务器是一个 Node.js 应用,定义 ChatGPT 可以调用的工具。每个工具包括名称、描述以及描述必需参数的 inputSchema。
const tools = [
{
name: "add-item",
description: "Add an item to the list",
inputSchema: {
type: "object",
properties: {
text: {
type: "string",
description: "The item text"
},
priority: {
type: "string",
enum: ["low", "medium", "high"],
description: "Item priority"
}
},
required: ["text"]
}
}
];
description 用来指导 ChatGPT 何时使用该工具,而 inputSchema 则告诉它需要发送哪些数据。
前置条件
| 服务 | 需要的内容 |
|---|---|
| Velt | API 密钥和 Auth Token(用于处理评论与协作) |
| TLDraw | 许可证密钥(白板画布必需) |
| ngrok | 将本地服务器暴露给 ChatGPT |
| ChatGPT Plus | 必须使用自定义应用 |
设置
git clone https://github.com/Studio1HQ/velt-app-examples
cd velt-app-examples
pnpm install
cd syncboard_server
pnpm install
cd ..
Chrome 142+ 用户: 禁用 local‑network‑access‑check 标志。
- 打开
chrome://flags/ - 搜索
local-network-access-check - 设置为 Disabled 并重启 Chrome。
构建白板
项目分为前端(小部件)和后端(MCP 服务器)两部分。
src/syncboard/ # 前端白板
├── syncboard.jsx # 画布和 Velt 组件
├── mockUsers.js # 测试用户(Bob & Alice)
└── index.jsx # 入口文件
syncboard_server/ # 后端 MCP 服务器
└── src/
├── server.ts # 工具定义
└── velt/ # 评论处理器
设置 TLDraw
编辑 src/syncboard/syncboard.jsx,添加基础 TLDraw 画布:
import { Tldraw } from 'tldraw';
import { useSyncDemo } from '@tldraw/sync';
import 'tldraw/tldraw.css';
function SyncboardCanvas() {
const store = useSyncDemo({
roomId: import.meta.env.VITE_TLDRAW_ROOM_ID // e.g., "my-room-abc"
});
return <Tldraw store={store} />;
}
useSyncDemo 会创建一个与指定 roomId 关联的同步 store。该房间的所有参与者共享同一个画布状态。
添加 Velt
将 TLDraw 画布包裹在 Velt 的 provider 中,并加入协作组件。
// syncboard.jsx
import {
VeltProvider,
useVeltClient,
VeltComments,
VeltPresence,
VeltCursor,
VeltCommentTool,
VeltSidebarButton
} from '@veltdev/react';
import { Tldraw } from 'tldraw';
import { useSyncDemo } from '@tldraw/sync';
import 'tldraw/tldraw.css';
import { useEffect, useState } from 'react';
function SyncboardCanvas() {
const store = useSyncDemo({
roomId: import.meta.env.VITE_TLDRAW_ROOM_ID
});
const { client } = useVeltClient();
const [veltReady, setVeltReady] = useState(false);
// 初始化 Velt 客户端
useEffect(() => {
const init = async () => {
if (!client || veltReady) return;
await client.identify(currentUser, { forceReset: true });
await client.setDocument('syncboard-whiteboard', {
documentName: 'Syncboard Collaborative Whiteboard'
});
setVeltReady(true);
};
init();
}, [client, veltReady]);
return (
<>
{/* 顶部栏,放置协作控制 */}
{veltReady && <VeltSidebarButton />}
{veltReady && <VeltCommentTool />}
{/* 主画布 */}
<Tldraw store={store} />
{/* Velt 覆盖层 */}
{veltReady && (
<>
<VeltComments />
<VeltPresence />
<VeltCursor />
</>
)}
</>
);
}
export default function Syncboard() {
return (
<VeltProvider>
<SyncboardCanvas />
</VeltProvider>
);
}
Velt 组件在 TLDraw 画布之上添加评论线程、在场指示器和实时光标。
MCP 服务器(后端)
在 syncboard_server/src/server.ts 中创建 MCP 服务器。下面是一个最小示例,定义了向白板添加矩形的工具。
import { createMcpServer } from '@openai/mcp';
import { addRectangle } from './velt/rectangleHandler'; // your custom logic
const tools = [
{
name: "add-rectangle",
description: "Add a rectangle shape to the whiteboard",
inputSchema: {
type: "object",
properties: {
width: { type: "number", description: "Width of the rectangle" },
height: { type: "number", description: "Height of the rectangle" },
color: { type: "string", description: "Fill color (hex)" }
},
required: ["width", "height"]
}
}
];
const server = createMcpServer({
tools,
handler: async (toolName, params) => {
if (toolName === "add-rectangle") {
await addRectangle(params);
}
// Add more tool handlers as needed
}
});
server.listen(3000, () => console.log("MCP server listening on port 3000"));
addRectangle 应当通过 Velt 的 REST API 或 SDK 与文档交互,在 TLDraw store 中插入矩形形状。
使用 ngrok 将服务器暴露出来,以便 ChatGPT 能访问:
ngrok http 3000
复制生成的 HTTPS URL,并在 ChatGPT 应用设置中将其配置为 MCP 端点。
运行应用
- 启动前端(小部件)——通常使用 Vite 或你喜欢的开发服务器。
- 启动 MCP 服务器(
node syncboard_server/src/server.ts)。 - 使用 ngrok 暴露服务器。
- 在 ChatGPT 中添加一个新的自定义应用,并指向 ngrok URL。
- 开始交互!尝试以下提示:
- “画一个蓝色矩形,宽 200 px,高 100 px。”
- “添加一个写着 ‘Sprint goals’ 的便利贴。”
ChatGPT 将调用相应的工具,MCP 服务器更新 Velt 文档,变化会即时出现在共享白板上。