mcpField
B
building-canvases

building-canvases

github.com/posthog开发7963 次安装今天更新
代码仓库

关于 building-canvases

这是用于创建 PostHog 独立浏览器应用的技能,应用运行在沙盒 iframe 中。它涵盖画布选择、实现方式、可编辑组件、验证,以及通过 PostHog 工具发布。

主要功能

  1. 01在频道中选择或创建画布
  2. 02选择 React、HTML 和数据查询技能
  3. 03添加可编辑组件与参数
  4. 04验证项目能力声明和诊断
  5. 05通过版本保护发布编辑

适用场景

  1. 01构建 PostHog 仪表板或数据看板
  2. 02创建表单或轻量工作流
  3. 03制作文档或叙述式报告
  4. 04添加交互图形或动画

MCP 相关

该技能使用 PostHog 画布工具读取、编辑、验证和发布存储在 PostHog 中的画布源代码。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/posthog/skills --skill building-canvases

安装后在 Claude Code 中输入/building-canvases确认已加载。

附带文件references/blocks.md

详细介绍

构建画布

画布是在 PostHog 内部沙盒化 iframe 中运行的客户端浏览器应用。 其源代码存放在 PostHog 中,而非代码仓库里;你需要通过 canvas-* 工具读取和写入。切勿将画布写入本地文件;通过工具发布才会保存内容。

画布任务可以从任何常规任务开始。不需要专门的画布模式或预先创建画布。当用户要求创建 一个要放在 PostHog 中的看板、文档、表单、可视化内容或小型应用时,应将其视为画布请求并遵循 本技能。

本技能负责 freeform 画布(独立应用)。另外还有两种画布类型:grid 画布(小组件网格,包括用户的主页画布)和 component 画布(可供网格放置的可复用小组件)。 如果目标是网格或主页画布、放置操作,或可复用小组件/组件,请改为加载 composing-grid-canvases; 它负责管理从搜索资源库 → 配置 → 分叉 → 构建的流程,以及布局补丁循环。编写组件源代码仍需使用下面的实现配套技能。

确定目标画布

  • 如果任务指定了画布 ID(由画布发起的任务会指定),则该画布就是目标。不要另建画布。
  • 否则,目标频道就是创建任务时所在的频道——任务上下文(channel_context 块或生成指令)中会注明。 使用 canvas-list 列出该频道的画布(通过 channel 指定范围)。如果其中有一个明显符合请求——例如同一看板或工具的早期版本—— 就在其基础上构建,而不是创建一个近似重复项;并在回复中说明这一点,让用户知道结果保存在哪里。
  • 只有在没有合适的现有画布时,才在同一频道中使用 canvas-create 创建一个,并根据请求取一个简短且有描述性的标题——切勿使用“未命名画布”。
  • 切勿自行遍历频道来选择目标:仅当用户指定了频道、需要将其解析为 ID 时,才使用 channel-list。其列表会将个人 #me 频道排在首位,而 #me 绝不是默认选项——保存在此处的画布对其他人不可见。如果任务既未指定画布,也未指定频道,请询问应使用哪个频道,而不要猜测。

加载实现所需的配套技能

本技能负责画布选择和编写生命周期。配套技能包含实现规范。编写源代码前,加载所有适用的配套技能:

  • building-react-quill-canvases 用于仪表板、数据看板、表单、工具、带有应用状态的内容,或任何应采用 PostHog 原生外观的内容。它负责管理允许导入的内容、Quill 组合、主题、图表、加载和错误状态,以及日期选择器。
  • building-html-canvases 用于文档、文章、专注型实验、生成式图形、<canvas> 或 WebGL 工作,适用于应用组件无法提供有用结构的场景。它负责管理语义化标记、直接浏览器 API、动画清理和非 Quill 主题。
  • querying-canvas-data 适用于任何读取 PostHog 数据、捕获事件或进行导航的画布。它负责管理 ph SDK、已保存洞察的优先使用、结果形状、变量、日期范围、逐查询渐进式加载,以及已声明的数据功能。涉及数据时,应与任一实现技能一同加载。
  • validating-and-publishing-canvases 适用于所有画布。它负责管理项目结构、功能声明、验证诊断、受保护的发布、草稿、构建和冲突恢复。

适当时可以混合使用不同的实现方式:由 React 负责应用框架,由浏览器图形代码负责画布元素;或者在基本静态的页面中挂载一个交互式区域。

这是一个判断问题,而不是持久化模式——只有当选项会影响你无法推断的用户可见要求时,才向用户询问。

区块

画布可以包含预制区块:数字、目标、趋势、排行榜、漏斗、留存、已保存的洞察、实时事件流、SQL 表格、筛选器、比较和刷新控件,以及标注。 它们是 src/blocks/ 中的 React 组件,用户可以在桌面应用中将其拖入画布,因此也是你源码的一部分。 更改含有 src/blocks/runtime.tsx 的画布前,请先阅读 references/blocks.md。

参数

将用户可能想要更改的值公开为参数。这样,他们就能在桌面编辑器中更改这些值,而无需创建新任务。 参数是可选的,但请为每个包含值得更改的值的面板、卡片或工具添加参数:标题、文案、事件、属性、阈值、限制、颜色。 参数需要 React 组件。纯 HTML 画布没有参数。

编辑器如何使用 editable()

在桌面编辑器中,用户可以选择画布上的任意元素:标题、段落、区块。他们可以移动、复制或删除元素,也可以双击文本进行修改。无需调用 editable() 即可实现这些操作。

editable() 会将组件设为一个区块。编辑器随后会将该区块视为一个整体:

  • 单击会选中整个区块,而非区块内的元素。
  • 移动、复制和删除操作会作用于整个区块。
  • 侧边栏会将区块的参数显示为字段。更改后,新值会写入源码中该区块的 props。
  • 要访问区块内的元素,用户可以双击区块将其打开。

因此,请在用户认为是一个整体、并会作为一个整体进行配置的部分上使用 editable():例如卡片、图表、表格、表单。周围的页面布局则保留为普通 JSX。这样,用户既可以将卡片作为区块选中,也可以直接选中页面标题或区块。如果包含整个页面的组件使用了 editable(),整个页面就会成为一个区块,每次单击都会选中整个页面。

添加参数
  1. 将每个面板放在单独的组件中。组件通过 props 接收这些值,并为其设置默认值。
  2. 在组件的根元素上展开来自 @posthog/canvas-sdk 的 editable(name, props, params)。name 是组件名称。params 将每个 prop 名称映射到对应字段。
  3. 使用带字面量 props 的组件,例如 <SignupFunnel blockId="b-k3m9x2" title="Signup" windowDays={14} />。编辑器会将更改写入这些 props,因此不要在行内计算它们。
  4. 为每次使用提供唯一的 blockId prop,例如 <SignupFunnel blockId="b-k3m9x2" … />,这样用户就能指定某张卡片让 Agent 进行操作。只能使用字母、数字、_、-、. 和 :,否则编辑器会忽略该 ID。在列表中,根据条目的稳定键生成 ID:``blockId={kpi-${item.id}}`。
import { editable } from '@posthog/canvas-sdk'

export function SignupFunnel(props: { blockId?: string; title?: string; steps?: string[]; windowDays?: number }) {
  const { title = 'Signup funnel', steps = ['$pageview', 'signed_up'], windowDays = 14 } = props
  return (
    <Card
      {...editable('SignupFunnel', props, {
        title: { type: 'text', label: 'Title', default: 'Signup funnel' },
        steps: { type: 'events', label: 'Steps', default: ['$pageview', 'signed_up'] },
        windowDays: { type: 'number', label: 'Conversion window (days)', min: 1, max: 90, default: 14 },
      })}
    >
      …
    </Card>
  )
}

字段类型:text、longtext、number(min、max、step;同时设置 min 和 max 时,编辑器会显示滑块)、boolean、select(options:字符串或 { value, label })、event、events、property、insight(已保存洞察的短 ID)、color。每个字段还可以包含 description。 为每个字段设置与其 prop 默认值相同的 default,例如 { type: "boolean", label: "Show legend", default: true }。未设置 prop 时,编辑器会显示 default。 color 参数的默认值是 var(--primary) 之类的主题令牌,因此在用户于编辑器中选择十六进制颜色之前,画布会自动适配浅色和深色模式。 通过参数只传递 JSON 值(字符串、数字、布尔值、字符串数组)。不要将函数和查询结果放入其中。

图像

在画布中使用公开的媒体库 URL。先调用 posthog:media-images-list,并将 purpose="canvas" 作为参数;如果已有合适的图像,请重复使用。

添加本地图像:

  1. 调用 posthog:media-image-upload-start,并提供文件名和 purpose="canvas"。
  2. 在 shell 中,以 multipart 表单数据的形式将文件 POST 到返回的 upload_url。包含所有 返回的 form_fields 条目,并将文件部分放在最后。
  3. 调用 posthog:media-image-upload-complete,并提供返回的 id;然后使用其永久 url 作为图像的 src。
  4. 将 URL 的确切源添加到 project.capabilities.network.origins。画布验证会检查此声明,发布后的产物会在其内容安全策略中使用此声明。

画布媒体 URL 是公开的,无需身份验证。切勿上传密钥、凭据、客户数据或敏感截图。图像必须小于 4 MB,且可解码为 PNG、JPEG、GIF、WebP、AVIF 或 BMP。切勿将图像字节编码为 base64 后放入工具调用中。

常见请求模式

将这些模式用作路由示例,而非固定模板:

  • 产品仪表板、Web 分析看板或指标浏览器: React + Quill,加上数据查询。
  • 清单、表单或轻量级工作流: React + Quill;如果需要读取 PostHog 数据、捕获事件或导航,再加上数据查询。对于清单或运行手册,请从 building-react-quill-canvases(references/checklist-example.md)中的完整示例开始——通过每个步骤的 ph.state 键共享团队进度。不要暗示可用 API 不支持的持久化能力。
  • 文档或叙述性报告: 对于基本静态的阅读体验,使用 HTML;如果需要实时 PostHog 数据、筛选器或类似应用的交互,则使用 React + Quill,并加上数据查询。
  • 生成式图形或动画: 使用 HTML 和浏览器图形 API。仅当 React 能显著简化应用状态或界面元素时才添加 React。

当任务带有 dashboard 或 web-analytics 等旧版请求模式时,请应用上述对应模式。模式仅作提示;用户的实际请求始终优先。

迭代循环

  1. 使用 canvas-source-retrieve 读取当前源文件和版本指针。 记住 current_version_id——发布时必须以它为依据进行保护。
  2. 使用上文选定的实现伴侣编辑项目文件。对于画布中显示的任何 PostHog 数据, 请遵循 querying-canvas-data(通过 ph SDK 加载已保存的洞察——绝不自行获取数据或使用自己的 PostHog 客户端),确保每个数据都可验证——由洞察支持的指标需链接到 PostHog 中已保存的洞察,临时查询需显示实际运行的确切查询,具体遵循该技能的“可验证性”部分——并且 在 project.capabilities 中声明每次 ph 调用(洞察短 ID 放在 capabilities.posthog.insights 中,捕获的事件放在 captureEvents 中,临时查询需设置 inlineQueries: true,ph.agent.request 需设置 agentRequests: true)——宿主会在运行时强制执行这些要求,验证也会拒绝未声明的调用。
  3. 遵循 validating-and-publishing-canvases:根据需要多次使用 canvas-validate-create 进行验证,并修复所有错误级别的诊断。
  4. 通过发布来保存项目——发布是默认操作,会立即上线:
    • 首个版本(current_version_id 为 null):使用 canvas-publish-create 发布完整项目,并传入 expected_current_version_id: null。
    • 已上线(current_version_id 已设置):仅使用 canvas-edit-create 提交编辑;对于文件内的更改,使用 str_replace 操作。 将当前已上线的 current_version_id 作为 expected_current_version_id 传入。 只有在要替换整个项目时,才使用 canvas-publish-create 发布完整项目。
    • 仅当用户要求草稿、预览,或要求先审核再上线时,才使用 canvas-draft-create 暂存草稿。 遵循 validating-and-publishing-canvases 技能处理诊断和冲突恢复。
  5. 等待构建完成——草稿和发布都会排入一个构建。发布或编辑响应中已包含 build.build_status;如果状态为 ready 或 failed,请直接使用。否则,每隔几秒轮询一次 canvas-builds-retrieve(最多约 2 分钟),直到构建状态为 ready 或 failed。如果状态为 failed,请读取构建的错误诊断,修复项目并再次保存——不要以构建失败结束任务。

每次用户要求的更改只保存一次,待画布就绪后再保存——不要每次微小编辑后都保存。用户要求草稿时,请在回复结尾说明草稿已就绪,可以预览并升级;validating-and-publishing-canvases 技能介绍了草稿 → 构建 → 预览 → 升级流程。

回复结尾需指出画布所在的频道,并使用画布工具返回的 url 字段创建链接(canvas-create、canvas-list 以及发布/源文件响应都包含该字段)。该字段是画布唯一有效的链接——切勿自行构造链接;猜测的 URL(项目页面、网页路由)无法正常访问。

运行时记忆与操作

  • ph.state — 持久键值记忆:ph.state.get(key, { scope })、 ph.state.set(key, value, { scope })(null 值会删除该键)、ph.state.list({ scope })。 作用域 "user"(默认值)对每位查看者都是私有的;"shared" 则为每个画布保存一个值, 整个团队均可查看。请在 capabilities.posthog.state 中声明所用的作用域。 值为 JSON,序列化后上限为 64 KB,每个作用域最多 256 个键——请将大数据存储在 PostHog(洞察、数据仓库)中,并在此引用。切勿在状态中存放机密或查看者个人身份信息。

  • ph.actions.invoke(verb, payload) — 以查看者身份向 PostHog 写入数据。请在 capabilities.posthog.actions 中声明每个 verb;未声明或未注册的 verb 无法通过验证, 主机也会在运行时拒绝执行。请将操作绑定到明确的用户手势(查看者点击按钮),切勿在加载或渲染时触发。 注册表是唯一事实来源:使用 canvases-actions-retrieve 工具列出操作,并遵循每个 verb 的 usage(载荷/结果格式、行为以及相应的确认文案),再进行绑定。

  • ph.tools.read(tool, args) 和 ph.tools.call(tool, args):以查看者身份运行允许列表中的 PostHog MCP 工具,例如读取功能标志并更改其推出比例。请在 capabilities.posthog.tools 中声明每个 工具。read 接受只读工具;call 会更改数据,因此请将其绑定到点击操作,主机会要求查看者确认。 有关允许列表以及写入标志所需的版本处理,请参阅 querying-canvas-data。

  • ph.connectors.call(provider, tool, args) — 在查看时使用查看者自己的连接读取第三方实时数据 (GitHub 或任何 MCP 存储服务器)。切勿自行调用 GitHub、Calendly 或其他服务,再将结果粘贴到源代码中: 发布时该快照会过时,而且所有查看者都会看到作者的数据。请在 capabilities.connectors 中声明每个 provider 和工具;使用 canvas-connectors-retrieve 工具发现它们。有关结果和未连接时的处理,请参阅 querying-canvas-data。

  • ph.agent.request(prompt) — 在查看者批准后,请画布的创作 Agent 进行更改。请在 capabilities.posthog 中声明 agentRequests: true。仅在直接点击或提交表单时调用——主机会显示 完整提示词,并在消耗计算资源前征求查看者同意;渲染、挂载或轮询期间发起的调用会被拒绝。Agent 会将更改 发布为新版本;非创建者的请求会提交到创作任务的讨论串中,而不会启动一次运行。

源项目结构

  • 保留 index.html,将其作为源工具返回的入口外壳。
  • src/canvas.tsx 仍是常规的 React 入口组件,但可以从项目中导入其他相对路径的 TypeScript、TSX、JavaScript、JSON、SVG、CSS 和已准入的资源文件。
  • 可以使用 ./worker.ts?worker 导入独立模块 Worker。Worker 不得导入其他本地模块。
  • 图片请使用上文所述的公共媒体库流程。其他二进制资源应以 base64 内容和已准入的内容类型放在项目的 assets 映射中。支持 WOFF/WOFF2、WebAssembly 和通用 octet-stream 资源。
  • 请完整保留平台依赖映射,不要添加 npm 包;本地相对路径导入对应项目文件,而裸导入仍仅限于平台固定的集合。

评论

支持 Markdown