关于 penpot-build-screen
用于将需求简报转化为遵循现有设计系统的 Penpot 界面的技能。它逐段构建弹性布局,复用组件和语义令牌,并提供视觉检查与质量审计。
主要功能
- 01发现现有令牌与组件
- 02逐段构建界面
- 03复用组件与语义令牌
- 04采用弹性或网格布局
- 05导出检查点并审计质量
适用场景
- 01根据产品简报创建界面
- 02扩展现有 Penpot 设计系统
- 03检查布局、令牌与间距一致性
MCP 相关
该技能通过 `execute_code` 使用 Penpot MCP 工具,包括用 `export_shape` 创建视觉检查点,以及用 `penpotUtils.shapeStructure` 检查结构。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ penpot/ penpot-ai-kit --skill penpot-build-screen安装后在 Claude Code 中输入/penpot-build-screen确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/01-brief-analysis.md02-style-profiles.md03-layout-composition.md04-component-recipes.md05-critique-framework.md06-anti-rationalization.md07-error-recovery.mdscripts/assembleScreen.jsauditScreenQuality.jsbuildSection.jscreateScreenFrame.jssetupOrReuseSystem.js详细介绍
penpot-build-screen — 将简报转化为屏幕设计
1. 标题 + 工作原理
penpot-build-screen 将简报转化为精心设计的屏幕界面;所有变更都通过
execute_code 执行;使用 export_shape 进行视觉验证;使用
penpotUtils.shapeStructure 查看结构(完整工具列表:shared/penpot-mcp-tool-reference.md)。它会先
发现现有设计系统(通过 penpot-foundations / 本地库获取设计令牌和组件),然后在 Flex Board 中逐个分区构建屏幕,绑定设计令牌并复用
组件——绝不在一次调用中生成整个屏幕。
2. 最重要的一条规则
复用系统;逐步构建。 优先使用现有组件和语义设计令牌,而不是原始
图形。每次构建一个分区,使用 export_shape 创建检查点,然后继续。如果不存在设计系统,
则仅搭建最小化系统(较复杂的内容交由 penpot-foundations 处理)。
3. Penpot MCP 工具参考
完整工具列表:shared/penpot-mcp-tool-reference.md。主要调用:使用 penpot.createBoard()/addFlexLayout()
创建屏幕和分区;使用 penpot.library.local.components + comp.instance() 复用组件;
使用 shape.applyToken 绑定设计令牌;在检查点使用 export_shape('selection'|'page')。
4. Plugin API 要点
问题编号对应 shared/plugin-api-gotchas.md。
- 屏幕和分区均为采用 Flex 布局的 Board;通过追加顺序 + 间距 + 对齐/分布来组合。
- 使用
component.instance()复用组件;不要将系统组件重新绘制为原始图形。 - #3 文本自动调整大小——在任何
resize()(会强制设为fixed)之后,将growType设为auto-width/auto-height。 - #4 Flex 会覆盖子元素的 x/y——使用
layoutChild设置拉伸/边距。 - 将颜色/间距/圆角/字体绑定到语义设计令牌,绝不硬编码。
- #11 每个新建的 Board 都会带有不透明的白色填充——这是此技能的关键故障模式。
createBoard()默认设置fills = [{ fillColor: "#FFFFFF", fillOpacity: 1 }];如果保留此填充,结构包装层的方形白色角会在圆角子元素后方露出(导致圆角看起来失效),而保留纯白色的布局 Board 在深色模式下也不会切换(没有设计令牌,不符合系统规范)。**填充策略:**逐个 Board 决定——结构型 Board(仅用于布局的结构:分区、行、包装层)设置board.fills = [];表面型(屏幕背景、卡片、底板、按钮)绑定color.bg.*设计令牌,绝不使用纯色值。默认将布局容器设为透明(shared/modes-and-policies.md)。 - #13b 精确匹配字体——
penpot.fonts.all.find(f => f.name === "…");findByName会进行子字符串搜索。 - #15——仅在
appendChild之后设置layoutChild.*;openPage是异步的(两次调用协议:先创建并打开,然后断言currentPage.id,再执行任何createBoard)。 - #16——每个分区完成后都运行
clearFlip(填充尺寸的子元素可能会带着flipX = true返回;规范辅助函数见shared/visual-effects.md)。 - #17——读取几何信息前先执行
await board.waitForLayoutUpdate()(替代sleep-100ms的惯用写法)。 - #18——图像填充:
const img = await penpot.uploadMediaUrl(name, url); shape.fills = [{ fillOpacity: 1, fillImage: img }],在下一次调用中验证——参见shared/visual-effects.md。 - 对不熟悉的签名,先使用
penpot_api_info验证。
5. 感知令牌的简报契约
- 背景 — 产品、受众、平台、品牌氛围。
- 目标 — 单个屏幕及其主要用户目标。
- 输入 — 内容/版块、现有令牌和组件、风格配置、视口尺寸。
- 约束 — 使用现有组件;间距符合网格;仅使用语义令牌;禁止的模式;不得出现
shared/design-quality.md§7 中列出的任何问题;严格反低质模式开启时,不得使用方向步骤拒绝的任何键(shared/anti-slop.md§1)。 - 验收标准 — 层次清晰;遵循 4px 节奏;对比度达到 AA;复用系统;说明响应式设计意图;七个维度的设计质量评分均 ≥ 3(
shared/design-quality.md§8),或明确指出薄弱维度;严格反低质模式开启时,低质评分 ≤ 35(使用penpot-anti-slop诊断)。
请以资深产品/视觉设计师的身份行事,做出有意图的审美决策,而非泛泛而谈。
6. 强制工作流
**视觉自检(强制):**在每个展示视觉成果的 ✋ 检查点之前, 都要运行
shared/visual-self-review.md中的导出 → 查看 → 修正流程——导出刚完成的单元, 对照检查清单自行检查图像,修复可见缺陷(最多 2 轮),并展示同一份导出,同时指出仍存在的缺陷。
阶段 0 — 调研。 运行 high_level_overview;盘点令牌/组件(scripts/setupOrReuseSystem.js);分析简报(references/01-brief-analysis.md);选择风格配置(references/02-style-profiles.md)和一个有名称的屏幕骨架(shared/design-quality.md §5)——检查本次会话中之前屏幕的记录,并应用多样性规则(至少在 1 个维度上有所不同,并说明是哪个维度)。选择启用反低质模式:读取已存储的偏好(penpot-anti-slop → scripts/antiSlopPrefs.js);如果尚未设置,且简报未说明,则按照 shared/anti-slop.md §0 提问(使用用户的语言,每个文件仅询问一次),并存储答案。若设置为 on,则在选择风格配置和骨架之前运行方向步骤(penpot-anti-slop references/02-direction-playbook.md),并将其拒绝的键纳入约束。✋ 检查点:确认简报 + 风格 + 骨架 + 版块清单(+ 严格模式开启时的方向说明)。
阶段 1 — 画框。 使用 scripts/createScreenFrame.js 创建屏幕 Board(幂等;返回 id;绑定背景/间隙/内边距令牌)。设置视口尺寸。✋ 检查点。
阶段 2..N — 版块。 使用 scripts/buildSection.js 将每个版块构建为令牌化的弹性布局 Board,并复用组件。每次 execute_code 调用只处理一个版块。每个版块完成后进行 ✋ 检查点(export_shape)。
阶段 N+1 — 组装与评审。 scripts/assembleScreen.js 组合各版块;scripts/auditScreenQuality.js 检查布局覆盖(每个 board 都使用 flex/grid)、令牌绑定、网格间距和命名。boardsWithoutLayout 非空即表示未通过检查——在报告完成前,为每个标记的 board 添加布局。然后运行评分评审(references/05-critique-framework.md):依据 shared/design-quality.md §8 的七个维度,对最终导出评分(1–5);任何维度 < 3 时,进行针对性修订(最多 2 轮),然后输出设计质量报告(按照 shared/report-schemas/design-quality-report.schema.json 生成 Markdown + JSON,并同步到记录中)。**严格模式开启时:**对屏幕 Board 运行 penpot-anti-slop 诊断,并将低质评分纳入报告(该评分会影响 distinctiveness 维度);在工作流之外,评分 > 35 时应展示最重要的修正项,不得宣告完成。输出报告。
7. 关键规则
- 默认使用 Flex——每个容器都是一个布局 Board。 创建 Board 后,立即为其设置 flex(
addFlexLayout())或 grid(addGridLayout())布局,然后再添加子元素——屏幕根节点、每个区块,以及每个嵌套分组(卡片、行、列表、统计数据组、表单字段、按钮组)都要如此。绝不要用绝对x/y排列 UI 元素,也绝不要用普通 Group 布局 UI。没有布局的 Board 就是 bug;Phase N+1 审核(boardsWithoutLayout)会在存在任何此类 Board 时导致构建失败。 - 创建原始图形前,先复用现有组件。
- 绑定语义化令牌;绝不要硬编码颜色、间距、圆角或字体。
- 每次调用只处理一个区块;使用
export_shape创建检查点。 - 所有间距都遵循 4px 网格;保持节奏一致。
- 不要在这里搭建完整的设计系统——交由
penpot-foundations处理。 - 明确说明响应式意图(尺寸:fill/auto/fix)。
8. 领域架构
一个屏幕 = 根 flex Board(纵向)→ 区块 Board(每个区块各自使用 flex)→ 组件实例 + 令牌化图元。组合应遵循清晰的视觉层级:突出主要操作、归组内容、按间距比例留白、使用语义化字体令牌。
9. 模式与策略
默认使用 review。几何/布局更改始终需要检查点(shared/modes-and-policies.md)。
10. 状态管理
在 RUN_ID 下维护记录:phase、screenBoardId、sections:[{name,id,done}]、styleProfile、skeleton、designQuality(§8 报告对象)、antiSlop(pref、direction、reports[]——启用严格模式时)。选择加入本身是文件级插件数据 penpot-ai → prefs.antiSlop。恢复时重新读取结构。
11. 用户检查点
| 阶段之后 | 产物 | 询问 |
|---|---|---|
| 0(偏好未设置) | 反套路风格选择加入问题(shared/anti-slop.md §0) | 要避免千篇一律的 AI 风格吗? |
| 0 | 简述 + 风格 + 骨架 + 区块(严格模式下还包括方向说明) | 确认设计方向? |
| 1 | 空框架 export_shape | 确认框架/视口? |
| 每个区块 | 区块 export_shape | 确认区块? |
| 组装 | 完整屏幕 export_shape + 评分式评审(7 个维度) | 确认 / 迭代? |
12. 命名约定
shared/naming-conventions.md:图层使用语义化 HTML 名称(header、main、section、nav、button);屏幕 Board 按视图命名(Dashboard)。
13. 反合理化对照表
| 借口 | 错在哪里 | 应对措施(停止) |
|---|---|---|
| “我直接画个按钮吧,比用组件快。” | 原始图形会偏离设计系统。 | 实例化现有组件;复用胜过重新发明。 |
| “硬编码这个间距/颜色更快。” | 破坏节奏、主题和治理规范。 | 绑定语义化令牌;间距对齐到 4px。 |
| “一次性生成整个屏幕。” | 一次生成的结果千篇一律,也无法审查。 | 按区块构建,并设置检查点。 |
| “居中卡片 + 通用渐变看起来不错。” | 趋同会导致 UI 平庸且缺乏品牌特色。 | 采用明确的风格配置;说明美学选择的理由。 |
| “我跳过反套路问题吧,用户很忙。” | 严格模式由用户选择;擅自猜测启用或不启用都不对。 | 读取 prefs.antiSlop;若未设置,则询问一次(shared/anti-slop.md §0)。 |
| “我就在这里快速设置一下令牌。” | 基础体系应由对应技能负责。 | 任何超出简单操作的内容都交由 penpot-foundations 处理。 |
| “我直接用 x/y 定位这些元素,快一些。” | 绝对坐标无法随尺寸变化、重新排布或适配主题,也不符合系统规范。 | 将它们放入 flex/grid Board;通过添加顺序、间距和对齐进行排列。 |
| “用普通 Group 把这些元素归在一起就够了。” | Group 不负责布局——只负责包围元素。 | 使用 addFlexLayout() 创建 Board;审核会标记没有布局的 Board。 |
| “这个小容器不需要布局。” | 每个 UI 容器都需要布局,以保持节奏并支持响应式。 | 添加子元素前设置 flex/grid——没有例外。 |
14. 辅助代码片段
// Screen frame (Phase 1)
const screen = penpot.createBoard();
screen.name = "Dashboard";
screen.resize(1440, 1024);
const flex = screen.addFlexLayout();
flex.dir = "column";
flex.horizontalSizing = "fix"; flex.verticalSizing = "auto";
penpot.currentPage.root.appendChild(screen); // append first (#7); layoutChild only after append (#15)
// SPACING: bind tokens, never literals (#8: padding tokens bind on ≥ 2.17; numeric mirror + ledger exception otherwise)
const gap = penpotUtils.findTokenByName("spacing.24");
if (gap) screen.applyToken(gap, ["rowGap"]); else flex.rowGap = 24;
const pad = penpotUtils.findTokenByName("spacing.32");
const FLEX_PROP = { paddingTop: "topPadding", paddingBottom: "bottomPadding", paddingLeft: "leftPadding", paddingRight: "rightPadding" };
for (const side of Object.keys(FLEX_PROP)) {
try { if (!pad) throw new Error("no token"); screen.applyToken(pad, [side]); }
catch (e) { flex[FLEX_PROP[side]] = pad ? Number(pad.resolvedValue) : 32; } // record { kind: "padding-mirrors-token" } in the ledger
}
// FILL POLICY (gotchas #11): the screen root is THE one surface — bind its bg to a token so it flips in
// dark mode. Every section nested inside stays transparent (buildSection.js clears their default white).
screen.fills = []; // drop Penpot's default opaque #FFFFFF
const bg = penpotUtils.findTokenByName("color.bg.default");
if (bg) screen.applyToken(bg, ["fill"]); // bound surface, not a literal
storage.bs = { screenBoardId: screen.id };
return { screen: screen.id, bgBound: !!bg, gapBound: !!gap, padBound: !!pad };
15. 参考资源
penpot_api_info('Board')、penpot_api_info('LibraryComponent')、penpot_api_info('Text')。
16. 支持文件
references/:01-brief-analysis.md、02-style-profiles.md、03-layout-composition.md、04-component-recipes.md、05-critique-framework.md、06-anti-rationalization.md、07-error-recovery.md;效果、图像占位符、渐变:shared/visual-effects.md。
scripts/:setupOrReuseSystem.js、createScreenFrame.js(第 1 阶段画框:幂等、绑定令牌的背景/间距/内边距、记录簿)、buildSection.js、assembleScreen.js、auditScreenQuality.js。
规范路径。 在原生安装中,shared/… 和 policies/… 在此捆绑包内解析(由安装程序一并提供);在 Claude Code 插件安装中,它们位于插件根目录——${CLAUDE_PLUGIN_ROOT}/shared/…,即比此文件高两级的目录。