penpot-build-screen

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

penpot-build-screen — brief to on-system screen

penpot-build-screen — 从需求说明到符合系统规范的界面

1. Title + How it works

1. 标题与工作原理

penpot-build-screen
turns a brief into a crafted, on-system screen; every mutation goes through
execute_code
; validate visually with
export_shape
; read structure with
penpotUtils.shapeStructure
(full tool surface:
shared/penpot-mcp-tool-reference.md
). It first discovers the existing design system (tokens + components via
penpot-foundations
/ the local library), then builds the screen section by section inside flex Boards, binding tokens and reusing components — never generating an entire screen in one call.
penpot-build-screen
可将需求说明转化为精心制作的、符合系统规范的界面;所有修改都通过
execute_code
执行;使用
export_shape
进行视觉验证;通过
penpotUtils.shapeStructure
读取结构(完整工具说明见:
shared/penpot-mcp-tool-reference.md
)。它首先发现现有设计系统(通过
penpot-foundations
/ 本地库获取 tokens + 组件),然后在 flex Board 中逐段构建界面,绑定 tokens 并复用组件——绝不会在一次调用中生成整个界面。

2. The One Rule That Matters Most

2. 最重要的核心规则

Reuse the system; build incrementally. Prefer existing components and semantic tokens over raw shapes. Build one section, checkpoint with an
export_shape
, then continue. If no system exists, bootstrap only a minimal one (hand off to
penpot-foundations
for anything substantial).
复用系统,增量构建。 优先使用现有组件和语义 tokens,而非原始形状。构建一个段落,用
export_shape
设置检查点,然后继续。如果不存在设计系统,仅搭建最小化版本(任何实质性的系统搭建都交由
penpot-foundations
处理)。

3. Penpot MCP Tool Reference

3. Penpot MCP 工具参考

Full surface:
shared/penpot-mcp-tool-reference.md
. Key calls:
penpot.createBoard()
/
addFlexLayout()
for the screen and sections;
penpot.library.local.components
+
comp.instance()
to reuse components;
shape.applyToken
for token binding;
export_shape('selection'|'page')
at checkpoints.
完整接口说明:
shared/penpot-mcp-tool-reference.md
。核心调用:
  • penpot.createBoard()
    /
    addFlexLayout()
    :用于创建界面和段落
  • penpot.library.local.components
    +
    comp.instance()
    :复用组件
  • shape.applyToken
    :绑定 tokens
  • 检查点使用
    export_shape('selection'|'page')

4. Plugin API Essentials

4. 插件 API 核心要点

Gotcha numbers refer to
shared/plugin-api-gotchas.md
.
  • Screen and sections are Boards with flex layout; compose with append order + gaps + align/justify.
  • Reuse components via
    component.instance()
    ; don't redraw system parts as raw shapes.
  • #3 text auto-sizing — set
    growType
    to
    auto-width
    /
    auto-height
    AFTER any
    resize()
    (which forces
    fixed
    ).
  • #4 flex overrides child x/y — use
    layoutChild
    for stretch/margins.
  • Bind colors/spacing/radius/type to semantic tokens, never hardcoded.
  • #11 every new Board is born with an OPAQUE WHITE fill — this skill's critical failure mode.
    createBoard()
    ships
    fills = [{ fillColor: "#FFFFFF", fillOpacity: 1 }]
    ; left in place, a structural wrapper's square white corners poke out behind rounded children (radius looks broken), and layout boards keeping the literal white never flip in dark mode (no token, off-system). Fill policy: decide per board — a structural board (layout-only chrome: sections, rows, wrappers) gets
    board.fills = []
    ; a surface (screen bg, card, sheet, button) binds a
    color.bg.*
    token, never a literal. Default layout containers to transparent (
    shared/modes-and-policies.md
    ).
  • #13b exact font match —
    penpot.fonts.all.find(f => f.name === "…")
    ;
    findByName
    is a substring search.
  • #15 — set
    layoutChild.*
    only AFTER
    appendChild
    ;
    openPage
    is async (two-call protocol: create+open, then assert
    currentPage.id
    before any
    createBoard
    ).
  • #16 — run
    clearFlip
    after every section (fill-sized children can come back with
    flipX = true
    ; canonical helper in
    shared/visual-effects.md
    ).
  • #17 —
    await board.waitForLayoutUpdate()
    before reading geometry (replaces the sleep-100ms idiom).
  • #18 — image fills:
    const img = await penpot.uploadMediaUrl(name, url); shape.fills = [{ fillOpacity: 1, fillImage: img }]
    , verified in the next call — see
    shared/visual-effects.md
    .
  • Verify unfamiliar signatures with
    penpot_api_info
    first.
注意事项编号对应
shared/plugin-api-gotchas.md
中的条目。
  • 界面和段落都是带有 flex 布局的 Board;通过追加顺序 + 间距 + 对齐/分布来组合。
  • 通过
    component.instance()
    复用组件;不要将系统组件重绘为原始形状。
  • #3 文本自动调整大小 — 在任何
    resize()
    操作(会强制设为固定大小)之后,将
    growType
    设置为
    auto-width
    /
    auto-height
    。
  • #4 flex 布局会覆盖子元素的 x/y 坐标 — 使用
    layoutChild
    来设置拉伸/边距。
  • 将颜色/间距/圆角/字体绑定到语义 tokens,绝对不要硬编码。
  • #11 每个新 Board 默认带有不透明白色填充——这是本技能的关键失败点。
    createBoard()
    默认会设置
    fills = [{ fillColor: "#FFFFFF", fillOpacity: 1 }]
    ;如果保留这个设置,结构包装器的白色方角会从圆角子元素后面露出来(圆角看起来像坏了),而且布局 Board 保持字面白色的话,在深色模式下不会切换(没有 token 绑定,不符合系统规范)。填充策略: 按 Board 类型决定——结构型 Board(仅用于布局的容器:段落、行、包装器)设置
    board.fills = []
    ;表面型 Board(界面背景、卡片、面板、按钮)绑定
    color.bg.*
    类型的 token,绝对不要用字面量值。布局容器默认设为透明(参考
    shared/modes-and-policies.md
    )。
  • #13b 精确字体匹配 — 使用
    penpot.fonts.all.find(f => f.name === "…")
    ;
    findByName
    是子字符串搜索。
  • #15 — 仅在
    appendChild
    之后设置
    layoutChild.*
    ;
    openPage
    是异步的(两步协议:创建+打开,然后在任何
    createBoard
    操作前断言
    currentPage.id
    )。
  • #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. Token-Aware Brief Contract

5. 支持 Token 的需求说明规范

  • Context — product, audience, platform, brand mood.
  • Objective — the single screen and its primary user goal.
  • Inputs — content/sections, existing tokens & components, style profile, viewport size.
  • Constraints — use existing components; on-grid spacing; semantic tokens only; forbidden patterns; none of the named tells in
    shared/design-quality.md
    §7; with strict anti-slop on, none of the keys the direction step refused (
    shared/anti-slop.md
    §1).
  • Acceptance Criteria — clear hierarchy; 4px rhythm; AA contrast; reuses system; responsive intent stated; design-quality score ≥ 3 on all seven axes (
    shared/design-quality.md
    §8) or the weak axes explicitly presented; with strict anti-slop on, slop score ≤ 35 (
    penpot-anti-slop
    diagnose).
Act as a senior product/visual designer who makes deliberate aesthetic decisions, not generic ones.
  • 背景 — 产品、受众、平台、品牌调性。
  • 目标 — 单个界面及其主要用户目标。
  • 输入 — 内容/段落、现有 tokens 与组件、风格配置、视口大小。
  • 约束 — 使用现有组件;间距对齐网格;仅使用语义 tokens;禁用模式;不得出现
    shared/design-quality.md
    第7节中列出的问题;开启严格 anti-slop 时,不得包含方向步骤拒绝的关键词(
    shared/anti-slop.md
    第1节)。
  • 验收标准 — 清晰的层级;4px 网格节奏;AA 级对比度;复用设计系统;明确说明响应式意图;所有七个维度的设计质量评分 ≥ 3(
    shared/design-quality.md
    第8节),否则需明确说明薄弱维度;开启严格 anti-slop 时,slop 评分 ≤ 35(通过
    penpot-anti-slop
    诊断)。
扮演资深产品/视觉设计师的角色,做出深思熟虑的美学决策,而非泛泛之选。

6. Mandatory Workflow

6. 强制工作流

Visual self-review (mandatory): before every ✋ checkpoint that shows visual work, run the export → look → fix loop from
shared/visual-self-review.md
— export the unit you just built, inspect the image yourself against the checklist, fix visible defects (max 2 iterations), and present that same export with any remaining defects named.
Phase 0 — Discovery.
high_level_overview
; inventory tokens/components (
scripts/setupOrReuseSystem.js
); analyze the brief (
references/01-brief-analysis.md
); pick a style profile (
references/02-style-profiles.md
) and a named screen skeleton (
shared/design-quality.md
§5) — check the ledger for prior screens this session and apply the variety rule (differ on ≥ 1 axis, say which). Anti-slop opt-in: read the stored preference (
penpot-anti-slop
→
scripts/antiSlopPrefs.js
); if it is unset and the brief doesn't answer it, ask the question in
shared/anti-slop.md
§0 (user's language, once per file) and store the answer. When it is
on
, run the direction step (
penpot-anti-slop
references/02-direction-playbook.md
) before choosing profile and skeleton, and fold its refused keys into the Constraints. ✋ Checkpoint: confirm brief + style + skeleton + section list (+ the direction block when strict mode is on).
Phase 1 — Frame. Create the screen Board with
scripts/createScreenFrame.js
(idempotent; returns ids; binds bg/gap/padding tokens). Set viewport size. ✋ Checkpoint.
Phase 2..N — Sections. Build each section as a tokenized flex Board reusing components (
scripts/buildSection.js
). One section per
execute_code
call. ✋ Checkpoint after each (
export_shape
).
Phase N+1 — Assemble & critique.
scripts/assembleScreen.js
composes sections;
scripts/auditScreenQuality.js
checks layout coverage (every board has flex/grid), token binding, on-grid spacing, naming. A non-empty
boardsWithoutLayout
fails the gate — add a layout to each flagged board before reporting done. Then run the scored critique (
references/05-critique-framework.md
): score the final export 1–5 on the seven axes of
shared/design-quality.md
§8; any axis < 3 → targeted revision (max 2 passes), then emit the design-quality report (Markdown + JSON per
shared/report-schemas/design-quality-report.schema.json
, mirrored to the ledger). Strict mode on: run
penpot-anti-slop
diagnose on the screen board and include its slop score in the report (it feeds the
distinctiveness
axis); outside a workflow, a score > 35 means presenting its top fixes, not declaring done. Report.
视觉自查(强制要求): 在每个展示视觉成果的 ✋ 检查点之前, 执行
shared/visual-self-review.md
中的导出 → 检查 → 修复循环——导出你刚构建的单元, 对照检查清单自行检查图片,修复可见缺陷(最多2次迭代), 然后提交该导出结果,并说明剩余的缺陷。
阶段 0 — 调研发现。 生成
high_level_overview
;盘点 tokens/组件(
scripts/setupOrReuseSystem.js
);分析需求说明(
references/01-brief-analysis.md
);选择风格配置(
references/02-style-profiles.md
)和指定的界面骨架(
shared/design-quality.md
第5节)——检查本次会话的台账中之前的界面,应用多样性规则(至少在1个维度上有所不同,并说明是哪个维度)。Anti-slop 启用: 读取存储的偏好设置(
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;绑定背景/间距/内边距 tokens)。设置视口大小。✋ 检查点。
阶段 2..N — 段落构建。 将每个段落构建为绑定 token 的 flex Board,复用组件(
scripts/buildSection.js
)。每次
execute_code
调用仅构建一个段落。每个段落完成后设置 ✋ 检查点(使用
export_shape
)。
阶段 N+1 — 组装与评审。
scripts/assembleScreen.js
组合各个段落;
scripts/auditScreenQuality.js
检查布局覆盖率(每个 Board 都有 flex/grid 布局)、token 绑定、网格对齐间距、命名规范。如果
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
诊断,并将 slop 评分纳入报告(它会影响「独特性」维度);在工作流之外,评分 > 35 意味着需要展示主要修复方案,而非宣布完成。提交报告。

7. Critical Rules

7. 关键规则

  1. Flex by default — every container is a layout Board. The instant you create a Board, give it a flex (
    addFlexLayout()
    ) or grid (
    addGridLayout()
    ) layout before appending children — the screen root, every section, AND every nested grouping (card, row, list, stat cluster, form field, button group). NEVER arrange UI elements with absolute
    x
    /
    y
    , and NEVER use a plain Group to lay out UI. A Board without a layout is a bug; the Phase N+1 audit (
    boardsWithoutLayout
    ) fails the build if any exist.
  2. Reuse existing components before creating raw shapes.
  3. Bind to semantic tokens; never hardcode color/spacing/radius/type.
  4. One section per call; checkpoint with
    export_shape
    .
  5. All spacing on the 4px grid; consistent rhythm.
  6. Don't bootstrap a full design system here — hand off to
    penpot-foundations
    .
  7. State responsive intent (sizing: fill/auto/fix) explicitly.
  1. 默认使用 flex 布局——每个容器都是带布局的 Board。 创建 Board 的瞬间,就要在追加子元素之前为其添加 flex(
    addFlexLayout()
    )或 grid(
    addGridLayout()
    )布局——界面根容器、每个段落、以及每个嵌套分组(卡片、行、列表、统计集群、表单字段、按钮组)都是如此。绝对不要用绝对
    x
    /
    y
    坐标排列 UI 元素,也绝对不要用普通 Group 来布局 UI。没有布局的 Board 就是 bug;阶段 N+1 的审计(
    boardsWithoutLayout
    )如果发现任何无布局的 Board,会判定构建失败。
  2. 优先复用现有组件,再考虑创建原始形状。
  3. 绑定语义 tokens;绝对不要硬编码颜色/间距/圆角/字体。
  4. 每次调用仅构建一个段落;用
    export_shape
    设置检查点。
  5. 所有间距对齐 4px 网格;保持一致的节奏。
  6. 不要在这里搭建完整的设计系统——交由
    penpot-foundations
    处理。
  7. 明确说明响应式意图(大小模式:fill/auto/fix)。

8. Domain Architecture

8. 领域架构

A screen = a root flex Board (column) → section Boards (each its own flex) → component instances + tokenized primitives. Composition follows a clear visual hierarchy: primary action prominent, content grouped, whitespace on the spacing scale, type from the semantic type tokens.
界面 = 根 flex Board(纵向排列)→ 段落 Board(每个都有自己的 flex 布局)→ 组件实例 + 绑定 token 的基础元素。组合遵循清晰的视觉层级:主要操作突出,内容分组,留白遵循间距尺度,字体使用语义字体 tokens。

9. Modes & Policies

9. 模式与策略

Default review. Geometry/layout changes always require a checkpoint (
shared/modes-and-policies.md
).
默认评审模式。几何/布局变更始终需要设置检查点(
shared/modes-and-policies.md
)。

10. State Management

10. 状态管理

Ledger under
RUN_ID
:
phase
,
screenBoardId
,
sections:[{name,id,done}]
,
styleProfile
,
skeleton
,
designQuality
(the §8 report object),
antiSlop
(
pref
,
direction
,
reports[]
— when strict mode is on). The opt-in itself is file-wide plugin data
penpot-ai
→
prefs.antiSlop
. Resume by re-reading structure.
RUN_ID
下的台账:
phase
、
screenBoardId
、
sections:[{name,id,done}]
、
styleProfile
、
skeleton
、
designQuality
(第8节的报告对象)、
antiSlop
(
pref
、
direction
、
reports[]
—— 严格模式开启时)。启用设置本身是文件级的插件数据
penpot-ai
→
prefs.antiSlop
。通过重新读取结构来恢复进度。

11. User Checkpoints

11. 用户检查点

After phaseArtifactsAsk
0 (pref unset)the anti-slop opt-in question (
shared/anti-slop.md
§0)
Avoid the generic-AI look?
0brief + style + skeleton + sections (+ direction block if strict)Approve direction?
1empty frame
export_shape
Approve frame/viewport?
each sectionsection
export_shape
Approve section?
assemblefull screen
export_shape
+ scored critique (7 axes)
Approve / iterate?
阶段完成后产出物询问内容
0(偏好未设置)anti-slop 启用问题(
shared/anti-slop.md
第0节)
是否要避免通用AI风格?
0需求说明 + 风格 + 骨架 + 段落(严格模式下含方向块)是否确认设计方向?
1空框架
export_shape
导出图
是否确认框架/视口?
每个段落完成后段落
export_shape
导出图
是否确认该段落?
组装完成完整界面
export_shape
导出图 + 评分评审(7个维度)
是否确认 / 需要迭代?

12. Naming Conventions

12. 命名规范

shared/naming-conventions.md
: layers semantic HTML (
header
,
main
,
section
,
nav
,
button
); screen Board named for the view (
Dashboard
).
参考
shared/naming-conventions.md
:图层使用语义 HTML 命名(
header
、
main
、
section
、
nav
、
button
);界面 Board 以视图命名(如
Dashboard
)。

13. Anti-Rationalization Table

13. 反合理化对照表

ExcuseWhy it's wrongCountermeasure (halt)
"I'll draw a quick button instead of using the component."Raw shapes drift from the system.Instantiate the existing component; reuse beats reinvention.
"Hardcode this spacing/color, faster."Breaks rhythm/theming/governance.Bind to semantic tokens; snap spacing to 4px.
"Generate the whole screen in one go."One-shot output is generic and unauditable.Build section by section with checkpoints.
"Centered cards + generic gradient looks fine."Distributive convergence → bland, off-brand UI.Apply a deliberate style profile; justify aesthetic choices.
"I'll skip the anti-slop question, the user is busy."Strict mode is the user's choice; guessing either way is wrong.Read
prefs.antiSlop
; unset → ask once (
shared/anti-slop.md
§0).
"I'll set up tokens here real quick."Foundations belong in their skill.Hand off to
penpot-foundations
for anything beyond trivial.
"I'll just position these with x/y, it's faster."Absolute coords don't resize, reflow, or theme; off-system.Wrap them in a flex/grid Board; order by append + gaps/align.
"A plain Group is enough to bunch these together."Groups don't lay out — they only bound.Use a Board with
addFlexLayout()
; the audit flags layout-less boards.
"This little container doesn't need a layout."Every UI container needs one for rhythm + responsiveness.Add flex/grid before appending children — no exceptions.
借口错误原因应对措施(立即停止)
“我就快速画个按钮,不用组件了。”原始形状会偏离设计系统。实例化现有组件;复用胜于重造。
“硬编码这个间距/颜色更快。”破坏节奏/主题/治理规范。绑定语义 tokens;间距对齐 4px 网格。
“一次性生成整个界面就行。”一次性输出的内容泛化且不可审计。逐段构建,设置检查点。
“居中卡片 + 通用渐变看起来不错。”趋同设计 → 平淡、不符合品牌的 UI。应用明确的风格配置;为美学决策提供依据。
“用户很忙,我就跳过 anti-slop 问题了。”严格模式是用户的选择;擅自猜测是错误的。读取
prefs.antiSlop
;未设置 → 询问一次(
shared/anti-slop.md
第0节)。
“我很快就能在这里搭好 tokens。”基础系统属于对应技能的范畴。任何非琐碎的系统搭建都交由
penpot-foundations
处理。
“我用 x/y 定位这些元素更快。”绝对坐标无法自适应大小、重排或主题切换;不符合系统规范。将它们包裹在 flex/grid Board 中;通过追加顺序 + 间距/对齐来排列。
“用普通 Group 把这些元素组在一起就行。”Group 不负责布局——仅做边界包裹。使用带有
addFlexLayout()
的 Board;审计会标记无布局的 Board。
“这个小容器不需要布局。”每个 UI 容器都需要布局以保证节奏和响应式能力。在追加子元素前添加 flex/grid 布局——没有例外。

14. Helper Code Snippets

14. 辅助代码片段

js
// 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 };
js
// 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. Reference Resources

15. 参考资源

  • penpot_api_info('Board')
    ,
    penpot_api_info('LibraryComponent')
    ,
    penpot_api_info('Text')
    .
  • penpot_api_info('Board')
    、
    penpot_api_info('LibraryComponent')
    、
    penpot_api_info('Text')
    。

16. Supporting Files

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
; effects, image placeholders, gradients:
shared/visual-effects.md
. scripts/:
setupOrReuseSystem.js
,
createScreenFrame.js
(Phase 1 frame: idempotent, token-bound bg/gap/padding, ledger),
buildSection.js
,
assembleScreen.js
,
auditScreenQuality.js
.
Doctrine paths.
shared/…
and
policies/…
resolve inside this bundle in native installs (vendored by the installer); in a Claude Code plugin install they live at the plugin root —
${CLAUDE_PLUGIN_ROOT}/shared/…
, two directories up from this file.
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框架:幂等、绑定 token 的背景/间距/内边距、台账记录)、
buildSection.js
、
assembleScreen.js
、
auditScreenQuality.js
。
文档路径说明。
shared/…
和
policies/…
在原生安装中位于此包内(由安装程序内置);在 Claude Code 插件安装中,它们位于插件根目录——
${CLAUDE_PLUGIN_ROOT}/shared/…
,即此文件的上两级目录。