关于 prototype-to-figma
prototype-to-figma 是面向在代码中构建原型的设计师的技能,可将运行中的原型捕获为 Figma 文件,并整理为可审阅的设计稿。它使用无头浏览器保持视觉一致,并将元素映射到已发布的设计系统组件、变量和样式,同时标注关键交互。
主要功能
- 01无头渲染并捕获原型
- 02将界面元素整理到 Figma
- 03映射设计系统组件与变量
- 04标注状态变化和设计系统差异
- 05按客户端能力生成文件或说明文档
适用场景
- 01将本地运行的原型转为 Figma 稿
- 02让跨职能团队异步审阅界面
- 03检查原型与设计系统的一致性
- 04为界面流程标注关键交互
MCP 相关
该技能使用 Figma MCP 工具检查设计系统并写入或整理 Figma 文件,具体能力取决于客户端支持。原型捕获通过无头浏览器和 `generate_figma_design` 完成;没有写入能力时可生成 Markdown 原型说明文档。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ alima-max/ prototype-to-figma-skill --skill prototype-to-figma安装后在 Claude Code 中输入/prototype-to-figma确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.mdLICENSEfigma-patterns.md详细介绍
原型 → Figma
此技能可将可运行的 Claude Code 原型转换为结构化的 Figma 文件,供跨职能合作伙伴异步评审。输出有两个同等重要的目标:
- 真正做到 1:1 视觉一致——布局、颜色、间距、字体排印、内容和图标都与原型的实际渲染效果完全一致,因为基础内容由无头渲染 → 序列化(规则 0)生成,而非手动重建。整个过程都在终端中运行——不会打开可见的浏览器或标签页。
- 生成符合设计系统规范、便于评审的结果——在设计系统已发布到 Figma 的情况下,将捕获的元素与设计系统组件实例、绑定变量和文本样式进行协调(规则 2),并在每个节点上标注状态转换。
**此技能适用于所有 Figma MCP 客户端。**输出格式会适配客户端支持的功能——请参阅下方的客户端兼容性。
五条不可妥协的规则
规则 0:无头捕获(渲染 → 序列化),绝不打开可见浏览器;然后与 DS 对齐
要实现真正的 1:1,必须渲染代码——但渲染并不需要可见浏览器。使用无头浏览器(Playwright),让整个流程都在终端中完成:没有窗口,没有标签页。这正是目标用户所需要的——只使用代码工作的设计师,不能被迫离开 IDE。
有三种方案,只有一种正确:
- ❌ 读取源代码并手动构建(不渲染)。 让 LLM 逐个元素重新推导浏览器的布局/渲染引擎,会造成信息丢失、不完整,而且在任何非简单页面上都会出现 bug。它不是 1:1——只有在小型静态 UI 上看起来忠实,遇到真实页面就会严重偏离(网格折叠、元素缺失、SVG 只构建了一半)。不要把这说成 1:1。
- ❌ 可见捕获——
open "<url>#figmacapture=…"、应用内预览或 GUI Figma 扩展。保真度没问题,但会弹出窗口/标签页,把设计师从终端中拉走(而且单独使用扩展不会生成 DS 实例)。 - ✅ 无头捕获。 无头浏览器在后台渲染正在运行的应用,并将 DOM 1:1 直接序列化到 Figma(数据从浏览器直接传到 Figma,不经过模型,因此快速且成本低)。然后由模型添加设计系统层。原生支持终端、1:1、全程不可见。
“无头”=通过 --headless 启动的独立 Chrome 进程:没有窗口,没有标签页,屏幕上什么都没有。 它不会连接到设计师已打开的浏览器,也不要求 Chrome 必须打开——只需安装即可。它会在后台隐式启动,在内存中渲染 localhost 页面,序列化到 Figma,然后退出。设计师无需离开终端,浏览器中也看不到任何变化。
捕获(无头,仅限终端):
- 确保开发服务器正在运行——如有需要,在后台启动。根据代码库确定路由 URL。
- 从终端启动无头浏览器,并运行
generate_figma_design捕获脚本(导航到本地开发 URL → 移除 CSP → 注入capture.js→window.figma.captureForDesign( { captureId, endpoint, selector:'body' }))。优先使用机器上已安装的 Chrome (puppeteer-core、使用channel:'chrome'的 Playwright,或原始 CDP),这样就无需下载,也无需 MCP——Chrome 只需安装,不必打开。只有找不到 Chrome/Chromium 时,才回退到一次性下载捆绑的 Chromium(npx playwright install chromium/完整的puppeteer)。绝不启动新的可见实例,绝不连接到用户正在使用的浏览器,绝不使用open "<url>#figmacapture=…"或应用内预览——这些都会在屏幕上显示窗口/标签页。 - 轮询
generate_figma_design(fileKey + captureId),直到状态为completed。你会得到一个完整分层的 1:1 基础设计(框架/文本/矢量),并已绑定设计令牌(bindVariables=true)。
然后与 DS 对齐并添加注释(使用 use_figma,规则 2): 将捕获的重复元素替换为 DS 组件实例,在 DS 确实已发布到 Figma 的地方绑定变量/文本样式,并添加 Dev Mode 注释和流程箭头。这是成本低、范围精简的一层——只涉及少量组件,而非整个页面。
要求/如实说明:需要 (a) 一个无头浏览器——最好使用由无头模式驱动的机器上已安装的 Chrome(无需下载,也无需 MCP);捆绑版 Chromium 下载是备用方案;以及 (b) 可运行的开发服务器。不需要 Playwright MCP;但需要无头 Chrome 运行时。如果确实完全没有浏览器,请说明并停止——不要退而使用可见标签页,也不要根据源代码手动构建后称其为 1:1(它并不是)。如果设计系统未作为组件/变量发布到 Figma,那么对齐范围仅限于现有内容——请指出 DS 的缺口,不要换成其他库的组件。
规则 1:绝不创建新的 Figma 组件
不要调用 figma.createComponent() 或 figma.createComponentSet()。这会污染设计系统,加入不属于其中的组件。
如果原型元素在 DS 中没有任何类型的组件(判断标准见规则 2),则使用基础图形(figma.createFrame()、figma.createRectangle()、figma.createText())构建,添加一条 DS Drift 注释说明缺少什么,并在第 6 阶段的摘要中列出。
规则 2:只要存在 DS 组件/变量/样式,就始终使用——捕获不会放宽此规则
捕获(规则 0)保证一致性;本规则则确保文件采用原生设计系统。在逐个协调捕获的元素时,此规则始终适用——捕获的节点会告诉你位置、尺寸和外观,但只要 DS 中存在匹配项,结构就应来自 DS。遍历捕获的画框,并将每个元素与关联的库协调:
- 组件——始终使用实例,绝不仿制。 如果捕获的元素与某个 DS 组件匹配,就用实例替换它,并覆盖属性(填充、文本、尺寸),使其与捕获的像素一致。如果组件存在但没有完全匹配的变体,仍然要创建实例并覆盖属性,同时添加 DS Drift 注释。只有在没有匹配组件时,元素才保留为基础图形,并标记 DS Drift。对于重复元素尤其如此:60 个徽章 = 60 个实例,绝不是 60 个画框。即使像素完全一致,满是仿制真实组件的基础图形的画框也算失败。
- 颜色变量——始终绑定。 每个值与 DS 颜色变量匹配的填充/描边必须绑定该变量。只要存在颜色变量,就绝不能保留原始十六进制值。
- 数值变量——始终绑定。 每个与 DS 数值/尺寸变量匹配的间距、间隙、内边距、圆角半径、边框宽度、尺寸和字号必须绑定该变量。只要存在数值变量,就绝不能保留原始数值。
- 文本样式——始终应用。 正文/标签/标题文本应绑定到库中的文本样式,而不是使用原始的
fontSize/fontName。
用一句话概括:只要存在匹配项,就优先使用组件/颜色变量/数值变量/文本样式,而不是任何字面值。 原始十六进制值、临时数值和仿制组件的基础图形都属于设计偏离,而非一致性——即使外观正确也是如此。第 2 阶段会发现组件、变量和样式;第 4 阶段会将它们替换并绑定到捕获的基础内容上。
规则 3:绝不遗漏原型元素
每个可见元素都必须出现在 Figma 输出中——无论是 DS 实例还是基础图形。因为找不到 DS 匹配项就跳过元素,是输出不完整最常见的原因。
规则 4:注释必须附加到节点上,且只能与流程关键内容相关
注释能让这份输出真正便于审阅。 没有注释的画板只是一张静态图片。但如果给每个点击目标都加注释,就会产生噪声,掩盖实际流程。
请在实际图层上使用 node.annotations = [...] 添加注释——这样注释就会显示在 Figma Dev Mode 的正确元素上。切勿用悬浮文本框或单独的注释画板代替。 如果原生 API 失败,请回退到 figma-patterns.md 第 11 节。
仅有两类注释:
- 交互(蓝色)——状态转换、主要 CTA、分组控件
- DS 偏差(橙色)——缺少 DS 组件、缺少变体,或颜色/间距未绑定
添加注释(交互):
- 画板级——每个画板添加一条注释:说明当前状态,以及主要操作的作用/后续去向
- 推进状态的 CTA——触发状态变化的操作(例如,提交、确认、创建目标、移至已完成)
- 分组控件——只注释一次容器,而非每个项目(注释金额选择器行,而非每个选项;注释故事胶囊栏,而非每个胶囊)
- 不明显的点击目标——会打开新状态但看起来不像按钮的元素(例如,点击后会打开详情面板的目标卡片)
不要添加注释:
- 关闭/取消/忽略按钮
- 导航栏按钮和标签项
- 次要实用操作(设置、原型控制)
- 分组选择器中的单个选项或胶囊
- 背景遮罩和覆盖层
- 装饰元素
目标:每个画板添加 2–4 条交互注释。 审阅者应能在 30 秒内读完画板上的所有注释,并理解完整流程。
第 2 阶段中每个带有 DS 偏差说明的元素都必须添加 DS 偏差注释。
客户端兼容性
| 层级 | 检查 | 写入 | Code Connect | 输出 |
|---|---|---|---|---|
| 完整 | ✅ | ✅ | ✅ | 包含 DS 组件、原生注释和 Code Connect 链接的 Figma 文件 |
| 写入 | ✅ 或 ❌ | ✅ | ❌ | 包含原生注释的 Figma 文件 |
| 仅检查 | ✅ | ❌ | ❌ | 原型规格文档(markdown) |
| 无 | ❌ | ❌ | ❌ | 仅根据代码分析生成的原型规格文档 |
| 客户端 | 检查 | 写入 | Code Connect |
|---|---|---|---|
| Claude Code / Desktop / Cursor / VS Code / Copilot CLI / Augment / Factory | ✅ | ✅ | ✅ |
| Android Studio / Gemini CLI / Kiro / Amazon Q / Openhands | ✅ | ❌ | ❌ |
| Replit | ❌ | ✅ | ❌ |
Figma MCP 工具
检查: get_design_context(主要工具)、get_metadata(结构概览)、
search_design_system(组件 + 变量)、get_variable_defs(精确的令牌值)、
get_screenshot(仅在用户明确要求视觉预览时使用)。
捕获(主要路径——规则 0): 通过无头浏览器调用 generate_figma_design——
理想情况下,使用机器上已安装的 Chrome 以无头模式运行(puppeteer-core / Playwright
channel:'chrome' / CDP;无需下载、无需 MCP),并针对本地开发服务器操作。渲染内容会以 1:1 的形式序列化到 Figma,且不会出现可见的窗口/标签页。绝不可使用
打开标签页的流程或应用内预览(可见),也绝不可连接到用户已打开的浏览器。
写入: use_figma(将捕获的节点与 DS 实例 + 变量协调一致、添加注释、组装流程)、whoami、create_new_file。
Code Connect: get_code_connect_map、get_code_connect_suggestions、
get_context_for_code_connect、send_code_connect_mappings。
工作流
阶段 0:解析文件并检测能力
文件: 从用户提供的 URL(figma.com/design/:fileKey/...)中提取 fileKey。如果未提供
URL,则调用 whoami,然后调用 create_new_file——绝不能因缺少 URL 而阻塞。
能力: 尝试调用 get_metadata,确认是否具备 Inspect 工具。检查工具列表中是否有
use_figma(Write)和 get_code_connect_map(Code Connect)。告知用户当前具备哪些能力。
流程: 有 Write 工具 → 阶段 1–6。没有 Write 工具 → 阶段 1–3,然后参阅 原型规格文档。
阶段 1a:分析原型
在接触 Figma 之前,先阅读所有原型源文件。
组件清单——记录每个 UI 组件的名称、使用的 props/变体、视觉结构(包含哪些内容),以及它是否可交互。此清单将作为阶段 4 的完整性检查表。
交互流程——针对每个流程,梳理:触发条件 → 状态变化 → 变化前/后的状态 → 分支路径(成功 / 错误 / 边界情况)。注明状态数量。
布局结构——记录哪些内容固定、哪些内容可滚动、哪些内容会在不同状态间保留(导航、
页眉),以及视口尺寸。对于手机/设备框架:如果原型将屏幕包裹在 .phone、.device-frame 或类似外壳中,只提取内容尺寸,并将其用于 Figma 框架尺寸——不要在 Figma 中将外壳重新创建为包装框架。
阅读源文件(用于清单和结构,而非像素值)——阅读 CSS 模块、Tailwind 配置和内联样式,了解每个元素的结构、变体以及哪些元素可交互。不要将源 CSS 值视为像素的权威依据:响应式/计算后的 CSS(网格 fr、clamp()、min/max、vw、变换、主题作用域)解析后是公式,而非像素。像素的权威依据是运行中应用的计算测量值(规则 0 / 阶段 4)。阅读源文件仅用于了解要测量什么,以及如何与 DS 匹配。
阶段 1b:说明范围、获取选择并确认
如果原型包含的流程不超过 2 个,则跳过此阶段。 直接进入阶段 2,处理所有流程。
对于包含 3 个或更多流程的原型,按类别列出流程及其状态数量,询问“要处理哪些流程,以及需要多详细(主流程 / 所有状态)?”,并等待回复后再继续。开始阶段 2 之前,明确确认对用户选择的理解。
阶段 2:探索阶段——先映射到设计系统,再开始绘制
先对关联的库进行完整探索,然后映射每个元素。此表完成前,不要开始构建。默认使用实例,而非基础元素(规则 2)。
2a. 一次性枚举库内容。 在逐个组件搜索之前,先获取目录,了解现有内容:
- 组件: 使用宽泛查询调用
search_design_system(fileKey, includeComponents=true),并按类别检索("input"、"navigation"、"feedback"、"card"、"badge"、"avatar"、"table"),以呈现完整组件集——而非仅限于代码中实际使用的名称。 - 变量: 调用
search_design_system(..., includeVariables=true)和get_variable_defs,查找颜色、间距、圆角和边框宽度令牌。记录这些键。 - 文本样式: 从
search_design_system/get_variable_defs中收集库的排版样式(名称 → 字体、字号、字重、行高)。正文、标签和标题都必须绑定到这些样式——不要使用硬编码的十六进制颜色值和临时设置的fontSize。
2b. 为清单中的每个元素寻找匹配项(宣告“无匹配项”前,按以下顺序尝试):
search_design_system(fileKey, query="ComponentName", includeComponents=true)- 其他名称:Alert/Banner/Toast/Notification、Dropdown/Select/Menu、Tag/Chip/Badge、 Nav/Sidebar/TabBar、TextField/Input、TextArea/Multiline、Avatar/UserPill 等
- 视觉类别:"input"、"navigation"、"feedback"、"card"
- 父组件覆盖范围(例如,"Card" 覆盖
Card.Header) 对于找到的组件: 在第 4 阶段设置属性之前,调用get_context_for_code_connect获取准确的变体属性名称。
当组件存在但没有完全匹配的变体时: 不要退回到基础图元。实例化该组件,并按实例覆盖有差异的属性(填充、文本、尺寸),然后为缺失的变体添加 DS Drift 注释。只有完全找不到匹配组件的元素才使用基础图元。
构建映射表 — 每一行都需要填写构建方式和漂移说明:
| 代码组件 | DS 匹配项 | Key | 构建方式 | 漂移说明 |
|---|---|---|---|---|
<Button variant="primary"> | Button | abc123 | 导入 + setProperties | ✅ 完全匹配 |
<Badge tone="success"> | Badge | ghi789 | 导入 + 按实例覆盖填充 | ⚠️ 没有 success 变体 — 覆盖填充 |
<CustomCard> | — | — | 基础图元 | ⚠️ 没有 DS 匹配项 — 已搜索:Card、Panel、Tile |
<DataTable sortable> | Table | def456 | 导入 + setProperties | ⚠️ Figma 中没有 sortable 变体 |
还要为每个元素记录其在第 4 阶段应绑定的文本样式和颜色/间距/圆角/边框宽度变量。任何带有 ⚠️ 的行都必须在第 4 阶段添加 DS Drift 注释。标记为“基础图元”的行只有在 2b 未找到任何内容时才有效 — 不能因为缺少某个变体就使用基础图元。
2c. 解析主题化/运行时重新映射的 CSS 变量令牌 — 切勿相信原始 var()。
如果颜色、间距或圆角来自 CSS 自定义属性(var(--token-…)),且运行时主题提供程序会重新映射这些属性 — 例如 ThemeScope / data-theme / 基于类的提供程序会根据品牌或浅色/深色方案改变 --token-color-purple-100 的解析结果 — 那么原始 CSS 值并非渲染后的值。仅阅读样式表只能得到变量名称或文件顶部的默认值,而不是用户在该主题上下文中实际看到的内容。这会悄无声息地破坏一致性:最常见的症状是主题化表面(深色页脚、反色主视觉区域)在 Figma 中渲染成空白/白色,因为其填充从未被解析和设置。
解析渲染后的值,然后绑定它 — 按顺序执行以下三个步骤:
- 从运行中的应用获取真实值,而不是从源码获取。 在浏览器中读取元素的计算样式(
getComputedStyle/ 检查工具 →background-color、color、gap、border-radius等),使主题重新映射解析为具体的rgb()/px值。如果无法运行应用,请根据当前主题的模式手动解析变量链,而不是使用:root默认值。 - 将其匹配到原生 Figma 变量。 在关联的库中搜索(
search_design_system,使用includeVariables=true、get_variable_defs),查找在对应模式/主题下解析值与之相等的变量。如果找到,绑定该变量(第 4 阶段 §3.2),使节点保持对主题的感知 — 这始终优于使用字面值。 - 如果没有匹配的 Figma 变量,则将解析后的字面值用作基础图元值,并添加 DS Drift 注释。 代码中存在该令牌,但没有对应的设计系统变量 — 这是设计团队需要弥补的实际差距。在映射表中将其记录为 ⚠️ 行。
切勿让主题令牌保持未解析状态(原始 var() 名称、:root 默认值或未设置的填充)。“我从 CSS 中读取了它”并不足够,因为令牌与像素之间可能存在主题作用域。
第 3 阶段:规划页面结构
Page: "[Feature Name] — Prototype Flows"
Section: "Flow 1: [Flow Name]"
Frame: "1.1 — [State description]" ← left-to-right within a flow
Frame: "1.2 — [State description]"
Frame: "1.3a — Success"
Frame: "1.3b — Error" ← branches stacked vertically
Section: "Flow 2: [Flow Name]"
...
画框尺寸:匹配 CSS 测量的视口(例如,移动端 390×844,桌面端 1440×900)。对于可滚动状态,将画框高度设为完整内容高度 — 切勿在视口高度处裁切。在视口高度处添加折叠标记线。画框之间间隔约 200px,区段之间间隔约 400px。
第 4 阶段:无头捕获像素,然后与 DS 对齐
步骤 1 — 无头捕获(规则 0)。 确保开发服务器正在运行(必要时在后台启动),并从代码库中解析路由 URL。对于每个路由/状态,调用 generate_figma_design(fileKey)以获取 captureId 和捕获脚本,然后针对本地开发 URL 运行该脚本的 无头 Playwright 变体——导航、移除 CSP、注入 capture.js、执行 window.figma.captureForDesign({...})。不要使用 open,不要打开可见标签页,也不要使用应用内预览。 轮询 generate_figma_design(fileKey, captureId),直到状态为 completed。结果:每种状态都生成完整分层的 1:1 基础稿,并由浏览器直接发送到 Figma。
步骤 2 — 与 DS 对齐(规则 2)。 遍历每个捕获的画框,对于每个在第 2 阶段找到匹配项的元素,将其替换为 DS 组件实例(调整属性以匹配捕获的像素),并绑定颜色和数字变量,以及已发布到 Figma 的文本样式。没有匹配项的元素保留为捕获节点,并标记为 DS Drift。这是低成本的精细调整层——只涉及少量组件,而非整个页面。如果 DS 完全没有发布到 Figma,则保留原样捕获结果并标记。
步骤 3 — 组装并添加注释(第 5 阶段)。 将各状态画框按流程排列,添加箭头,并附加 Dev Mode 注释。
如果没有无头浏览器或没有开发服务器: 停止并告知用户缺少什么。不要改用可见标签页,也不要根据源代码手工构建后标记为 1:1。
放置: 先用 get_metadata 扫描目标页面。如果该功能已有匹配的画框/分区,则放在它们旁边。如果没有,则创建一个命名分区:
[Prototype] <feature name>。绝不要将画框放在任意的远处 Y 坐标而不在第 6 阶段摘要中报告坐标和深层链接。
DS 组件实例 — importComponentByKeyAsync + setProperties 的用法见 figma-patterns.md 第 3 节。
基础图形 — 见 figma-patterns.md 第 4 节。所有尺寸、圆角和颜色均使用计算得出的实测值(规则 0)。
固定尺寸的正方形/圆形容器(头像、数字徽标、图标芯片): 两个轴都设为固定尺寸,绝不要让自动布局采用适应内容的尺寸。适应内容的容器会收缩到字形的宽度,因此 32×32 的头像会呈现为高 32px、宽约 10px。执行 resize(size, size) 后,使用 primaryAxisSizingMode = 'FIXED' 和 counterAxisSizingMode = 'FIXED',或者跳过自动布局并手动将子元素居中。见 figma-patterns.md 第 4.1 节。
DS 变量和文本样式绑定 — 对于第 2 阶段找到变量键的每个填充、圆角、间距和边框宽度,都要绑定变量,而不是硬编码。将正文/标签/标题文本绑定到库中的文本样式,而不是设置原始的 fontSize/fontName。变量 API 位于 figma.variables.* 下(不是 figma 全局对象下),而 setBoundVariableForPaint 接受一个 paint 并返回一个新对象,必须重新赋值:
// Color fill → variable. setBoundVariableForPaint returns a NEW paint — reassign node.fills.
const colorVar = await figma.variables.importVariableByKeyAsync(colorVarKey);
let fills = node.fills;
if (fills && fills !== figma.mixed && fills.length && fills[0].type === 'SOLID') {
fills = [...fills]; // copy — assigning into the live array is a no-op
fills[0] = figma.variables.setBoundVariableForPaint(fills[0], 'color', colorVar);
node.fills = fills; // reassign — required
}
// Scalar fields (radius / border-width / spacing) → node.setBoundVariable
const radiusVar = await figma.variables.importVariableByKeyAsync(radiusVarKey);
node.setBoundVariable('cornerRadius', radiusVar); // fallback: pass radiusVar.id
const borderVar = await figma.variables.importVariableByKeyAsync(borderWidthVarKey);
node.setBoundVariable('strokeWeight', borderVar); // not a raw strokeWeight
// Typography → library text style (styles use figma.importStyleByKeyAsync, NOT the variables API)
const textStyle = await figma.importStyleByKeyAsync(textStyleKey);
await textNode.setTextStyleIdAsync(textStyle.id); // font/size/weight/lineHeight; fill stays separate
⚠
figma.importVariableByKeyAsync(...)(没有.variables)和node.setBoundVariableForPaint('fills', 0, ...)会在 Figma MCP 运行时中抛出异常——请使用上述形式。缓存导入结果(每个键只导入一次),然后绑定。
页面和表面的背景也必须绑定到表面/wash 颜色变量,绝不要使用原始的页面背景十六进制值。只有在第 2 阶段未找到对应角色的 DS 变量或文本样式时,才回退到原始 CSS 值(并将其记为偏差)。
注释——构建节点时附加,而不是之后再做
在第一次调用 use_figma 时,于开始阶段一次性设置两个注释类别:
let interactionCat = null, dsDriftCat = null;
try {
const existing = await figma.annotations.getAnnotationCategoriesAsync();
interactionCat = existing.find(c => c.label === 'Interaction')
?? await figma.annotations.addAnnotationCategoryAsync({ label: 'Interaction', color: 'blue' });
dsDriftCat = existing.find(c => c.label === 'DS Drift')
?? await figma.annotations.addAnnotationCategoryAsync({ label: 'DS Drift', color: 'orange' });
} catch(e) { /* native API unavailable — use layer name fallback below */ }
构建每个节点时,立即为其添加注释——不要推迟到单独的处理步骤。保留节点引用是将注释附加到正确图层的唯一可靠方式:
// Interaction annotation — on the node itself, right after creating it
const ctaButton = figma.createFrame(); // ...build it...
ctaButton.name = 'CTA: Submit';
ctaButton.annotations = [{
label: 'Tap → submits form; on 200 navigates to success screen; on 4xx shows inline error',
...(interactionCat ? { categoryId: interactionCat.id } : {})
}];
// DS Drift annotation — on any primitive or mismatched DS component
const customCard = figma.createFrame(); // ...build it...
customCard.name = 'Card: Goal (primitive)';
customCard.annotations = [{
label: 'DS Drift: no Card/Goal component found in library (searched: Card, Panel, Tile). DS gap for design team.',
...(dsDriftCat ? { categoryId: dsDriftCat.id } : {})
}];
// Fallback if native API failed: encode in layer name
if (!interactionCat) ctaButton.name += ' [Interaction: tap → submit form]';
if (!dsDriftCat) customCard.name += ' [DS Drift: no Card/Goal in DS]';
逐帧标注检查清单:
- 帧本身有一条标注:当前状态 + 主要操作的作用 / 跳转位置
- 每个推进状态的 CTA 都有一条标注(触发 → 结果)
- 成组的控件(选择器、胶囊选项栏、选项列表)每组标注一次,而非逐项标注
- 每个基础组件或不匹配的 DS 组件都有一条 DS Drift 标注
完整性检查:进入下一帧之前,确认 Phase 2 映射 表中属于此帧的每一行都已出现在图层树中。
Phase 5:添加流程概览帧
在页面顶部添加一个帧:
- 功能名称、流程列表、帧数
- 标注图例:蓝色 = Interaction,橙色 = DS Drift(可在 Dev Mode 中筛选)
- DS 缺口:列出所有基础组件和不匹配的组件,供设计团队查看
- 未决问题:标记任何有歧义的原型行为
- 如果省略了某些流程,添加范围说明(提供重新运行 skill 以补充这些流程的选项)
Phase 6:验证并呈现
6a. 完整性检查 — 通过对输出调用 get_metadata,验证:
- Phase 2 映射表中的每一行在正确的帧中都有一个命名图层
- 每个有 DS 匹配项的元素都是实例,而非基础组件 — 包括重复元素(徽章、导航、输入框、文本区域、头像)。仅当 Phase 2 确认某行没有匹配项时,才使用基础组件;每个此类基础组件都必须带有 DS Drift 标注。
- 帧尺寸与通过 CSS 测量的视口一致
- 本地资源中没有创建新的主组件
- DS 变量已绑定到颜色填充、边框半径和边框宽度;文本已绑定到库中的文本样式;页面 / 表面背景已绑定到表面变量
- 正方形 / 圆形容器渲染为正方形 — 宽度等于高度(没有因 hug 导致的尺寸收缩)
- 内联 SVG 均已保留 — 如果应用中有任何
<svg>(徽标、图标、装饰性图形),输出中就必须包含对应的 VECTOR 节点。帧中没有 VECTOR 节点,表示所有内联 SVG 都被丢弃了(徽标错误 / 占位、页脚为空、卡片插画缺少装饰图形)——返回并通过createNodeFromSvg添加。
如果有任何缺失,请在呈现之前通过后续的 use_figma 调用修复。
6b. Code Connect (可选) — get_code_connect_suggestions → 审核 → send_code_connect_mappings。
6c. 呈现给用户:
- Figma 文件 URL(始终提供)+ 如果不在画布原点,则提供指向该区段节点的深层链接
- 流程数、帧数
- 使用的 DS 实例与基础组件
- 完整列出供设计团队查看的 DS 缺口(基础组件)
- 与 CSS 测量值的任何偏差及其原因
- 因能力限制而跳过的步骤
原型规格文档 — 仅供检查的输出
Write 工具不可用时,使用 figma-patterns.md 第 12 节中的模板生成结构化 Markdown 文档。
重要原则
优先使用实例,最后才用基础图形。 这项技能的价值不在于手动重建。如果设计系统(DS)中有组件,即使没有完全匹配的变体,也应使用该组件并添加覆盖样式。将字体、颜色、间距、圆角和边框宽度绑定到 DS 样式和变量。即使基础图形拼出的画面像素级准确,只要它们只是仿造真实组件,这次执行仍然失败。
先渲染,再序列化——以无头方式进行。 真正的 1:1 还原,是通过无头浏览器渲染代码并将结果序列化到 Figma,而不是让大模型从源码重新推导布局(在任何真实页面上都会有信息损失),也不是进行可见截图(会让设计师离开终端)。无头模式 = 相同的保真度、不可见、原生适配终端。模型的工作是在此基础上叠加 DS 和注释层,而不是手动复现像素。
在节点上添加注释,而不是画布上。 node.annotations = [...] 会在 Dev Mode 中显示。悬浮文本框和单独的注释画框只是噪声,并非真正的注释。
为所有内容命名。 “Frame 47”毫无用处。“2.3a — Save success with toast”能让审阅者准确了解当前位置。
注释流程,而非点击目标。 目标是让审阅者在不到 30 秒内读完画框上的所有注释,并理解完整流程。注释状态转换,而非实现机制——在金额选择器这一行添加一条注释,胜过在其中每个选项上添加四条相同的注释。
明确说明 DS 的缺口。 在摘要中列出每个基础图形,让设计团队知道 DS 缺少哪些组件。这样一来,未匹配的元素就不再是无声的失败,而会成为可采取行动的信号。
参考:Figma Plugin API 模式
请参阅 figma-patterns.md,了解 Plugin API 模式,包括画框创建、组件导入、基础图形辅助函数、addNoDsMatchBadge、自动布局、文本节点、注释设置,以及 Prototype Spec Document 模板。首次调用 use_figma 前请先阅读。
(仅限写入级客户端。)