figma-codegen

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

figma-codegen

figma-codegen

Turn a Figma selection into code that looks like the rest of the project: reuse the components and tokens that already exist, only build what's genuinely missing. The grounded tools do the heavy lifting so you are not guessing from a screenshot. This file is the router; deep detail lives in
references/
— load a reference when its step is in play.
将Figma选中内容转换为与项目其余部分风格一致的代码:重用已有的组件和令牌,仅构建真正缺失的部分。基于事实的工具会完成繁重的工作,让你无需从截图中猜测。本文件是路由;详细内容位于
references/
目录下——当执行到对应步骤时加载参考文档。

When to use

使用场景

  • The user pastes a Figma URL/selection and asks for code ("code this", "build this component").
  • The user wants to extend an existing component to match a Figma frame.
  • 用户粘贴Figma URL/选中内容并要求生成代码(“把这个转为代码”、“构建这个组件”)。
  • 用户希望扩展现有组件以匹配Figma框架。

Workflow

工作流程

Run the grounded tools against the selection, then generate — trust them over the rendered image.
  1. get_design_context
    (detail
    full
    ,
    dedupeComponents: true
    ) → the structural tree with tokens resolved to names (
    Primary/500
    ,
    spacing/4
    ), styles deduped into
    globalVars
    , and each instance's
    mainComponent
    /
    componentProperties
    . This is the layout + binding source of truth. Keep
    dedupeComponents: true
    and don't depth-limit a subtree you'll build from. → How to read the tree, the per-node fidelity catalog (effects, per-side borders, stroke align, per-corner radius, blend, masks, gradients, image-fit, auto-layout/grid, aspect-ratio, scroll/sticky, stack & stroke-space), Dev Mode annotations as ground truth, and grounding a page too big for one call:
    references/grounding.md
    .
  2. component_map
    → every Figma component grouped to a local code component with a
    status
    (high / medium / low / unmapped),
    candidate.filePath
    , and
    matchedProps
    .
    • high
      /
      medium
      : reuse that component (import from
      candidate.filePath
      ), don't regenerate. Never invent a component name
      component_map
      didn't report.
    • candidate.ambiguousWith
      (a capped list of
      { name, filePath }
      ): the Figma name matched two or more code components nearly equally and the join couldn't confidently pick — a verify-me pick, not a confident reuse (the analogue of
      token_map
      's
      ambiguousWith
      ). Check which of the winning
      candidate
      + these runner-ups is the right component for this context before importing (a wrong reuse is a silent visual bug), then record the confirmed one in the map file so the next run is certain. Absent when the pick was unambiguous.
    • Wire each entry's
      instances[].props
      (resolved variant / boolean / text values) onto the reused component — one element per instance, with its own props.
    • candidate.unmatchedProps
      : Figma axes the component has no prop for (a leading icon, a
      required
      flag, an active state) → surface as component-extension TODOs, never fake them with ad-hoc markup.
    • unmapped
      : build it new in the project's style. For a repeated unmapped component (
      instanceCount > 1
      ), build from its first instance's subtree; if that came back
      deduped
      /
      truncated
      , drill
      get_design_context
      on
      instances[0].nodeId
      once — don't rebuild a repeated component by eye.
    • When you're emitting a component's own definition (its prop types, not just rendering it),
      get_component_api
      on the component/instance returns the full property API — every VARIANT option and each BOOLEAN/TEXT/INSTANCE_SWAP prop with its default — so the prop space is grounded, not inferred from the instances you happened to see.
  3. token_map
    → every Figma variable joined to a project token with
    status
    +
    ref
    +
    matchedBy
    . A document's shared paint styles (single solid color styles — the token mechanism of pre-variables files) join the same way, marked
    source: 'style'
    .
    • mapped: reference
      candidate.ref
      (
      bg-primary-500
      ,
      var(--color-primary-500)
      ) — never the raw hex/px
      get_design_context
      resolved.
      matchedBy: ['name']
      on a colour (value drifted): use it but flag the mismatch.
    • candidate.ambiguousWith
      (several project tokens share that exact value and the name couldn't split them): a capped, verify-me pick — choose the semantically right sibling for the context (or keep the value and flag the gap), never treat it as a confirmed reuse.
    • On a document with few or no variables (most real-world files),
      get_design_context
      's own
      projectTokens
      map is the fallback: any raw color in the payload that exactly equals a project token's value is annotated there (
      { "#6266F0": { ref, name, matchedBy: ["value"] } }
      ). Before hardcoding a hex, look it up and emit the
      ref
      when it fits the context semantically.
      matchedBy: ["value"]
      marks the entry as name-blind value-equality evidence — a hypothesis to verify, not a resolved binding: an entry with
      candidates
      lists same-value tokens to choose between by meaning, a semantically wrong token is worse than the raw value (keep the raw value and note the gap instead), and a bound Figma variable always outranks a raw-value match.
    • framework-builtin
      (Tailwind built-in scale step, e.g.
      spacing/4
      ,
      line-height/7
      ,
      weight/Bold
      ): carries
      builtin: { scale, step }
      — compose the utility (
      p-4
      /
      gap-4
      ,
      leading-7
      ,
      font-bold
      ), not an arbitrary
      p-[16px]
      . This is not a gap.
    • unmapped
      : use the value but call out the gap (offer to add it to the token source); don't hardcode silently.
    • figmaModes
      (
      { Light: …, Dark: … }
      , with the file's theme axes on
      themedCollections
      ): the token is theme-dependent
      figmaValue
      is only the default mode, never the whole story. Mapped: emit
      candidate.ref
      and confirm the project token itself switches per theme (
      .dark
      /
      [data-theme]
      /
      prefers-color-scheme
      / a
      dark:
      story); if the project defines only one value, wire the other mode's value into that mechanism or surface a theme gap. Unmapped: the default mode is the base, other modes ride the project's dark-mode mechanism (
      dark:
      variants /
      prefers-color-scheme
      ). Themes encoded without native modes — paired collections or name groups (
      Color/Light/*
      +
      Color/Dark/*
      , a plan-limited workaround) — get the same treatment.
  4. Export the assets grounding can't carry — logos, photos, icons have no pixels and otherwise render as grey blocks.
    save_image_fills
    for
    IMAGE
    -fill nodes (the original asset, not a clipped re-render),
    icon_map
    first for icons (reuse curated
    .svg
    s),
    get_screenshot
    only for the composited look. → Full asset/icon/svg/colour-contract workflow:
    references/assets-and-icons.md
    .
Then emit code in the detected stack (the profile comes back on
component_map
/
token_map
; you do not call
analyze_project
yourself): compose the reused components, wrap unmapped pieces, and apply token references for colour/spacing/radius/typography.
针对选中内容运行基于事实的工具,然后生成代码——优先信任工具结果而非渲染截图
  1. get_design_context
    (详情级别
    full
    dedupeComponents: true
    )→ 已解析令牌名称(如
    Primary/500
    spacing/4
    )的结构树,样式已去重为
    globalVars
    ,每个实例包含
    mainComponent
    /
    componentProperties
    。这是布局与绑定的事实来源。保持
    dedupeComponents: true
    ,不要限制你将构建的子树深度。 → 如何读取结构树、每个节点的保真度目录(效果、单边边框、描边对齐、圆角半径、混合模式、遮罩、渐变、图片适配、自动布局/网格、宽高比、滚动/粘性定位、堆叠与描边间距)、作为事实依据的Dev Mode注释,以及处理超出单次调用范围的大型页面:
    references/grounding.md
  2. component_map
    → 每个Figma组件与本地代码组件分组对应,包含
    status
    (high / medium / low / unmapped)、
    candidate.filePath
    matchedProps
    • high
      /
      medium
      重用该组件(从
      candidate.filePath
      导入),不要重新生成。绝不要使用
      component_map
      未报告的组件名称。
    • candidate.ambiguousWith
      (一组有限的
      { name, filePath }
      ):Figma名称近乎匹配多个代码组件,无法确定最优选择——这是一个需要验证的选项,而非可信任的重用(类似于
      token_map
      中的
      ambiguousWith
      )。在导入前确认获胜的
      candidate
      与备选组件中哪个更适合当前上下文(错误的重用会导致隐性视觉bug),然后将确认的组件记录到映射文件中,以便下次运行时能确定选择。当选择明确时该字段不存在。
    • 将每个条目的
      instances[].props
      (已解析的变体/布尔/文本值)关联到重用组件——每个实例对应一个元素,拥有独立属性。
    • candidate.unmatchedProps
      :Figma组件轴中没有对应属性的部分(如前置图标、
      required
      标记、激活状态)→ 作为组件扩展的待办事项列出,绝不要用临时标记伪造。
    • unmapped
      :按照项目风格全新构建。对于重复出现的未映射组件(
      instanceCount > 1
      ),基于其第一个实例的子树构建;如果该子树返回
      deduped
      /
      truncated
      ,则针对
      instances[0].nodeId
      调用一次
      get_design_context
      ——不要凭视觉重建重复组件。
    • 当你输出组件的自身定义(其属性类型,而非仅渲染它)时,对组件/实例调用
      get_component_api
      会返回完整的属性API——每个VARIANT选项以及每个BOOLEAN/TEXT/INSTANCE_SWAP属性及其默认值——确保属性空间基于事实,而非从你恰好看到的实例中推断。
  3. token_map
    → 每个Figma变量与项目令牌关联,包含
    status
    +
    ref
    +
    matchedBy
    。文档的共享填充样式(单一纯色样式——预变量文件的令牌机制)以相同方式关联,标记为
    source: 'style'
    • 已映射:引用
      candidate.ref
      (如
      bg-primary-500
      var(--color-primary-500)
      )——绝不要使用
      get_design_context
      解析的原始十六进制/像素值。颜色的
      matchedBy: ['name']
      (值已偏移):可以使用,但要标记不匹配。
    • candidate.ambiguousWith
      (多个项目令牌共享完全相同的值,名称无法区分):一组有限的需要验证的选项——根据上下文选择语义正确的令牌(或保留值并标记缺口),绝不要将其视为已确认的重用。
    • 对于变量很少或没有变量的文档(大多数真实场景文件),
      get_design_context
      自身的
      projectTokens
      映射是备选方案: payload中任何与项目令牌值完全匹配的原始颜色都会在其中标注(如
      { "#6266F0": { ref, name, matchedBy: ["value"] } }
      )。在硬编码十六进制值前,先查找该映射,当语义符合上下文时输出
      ref
      matchedBy: ["value"]
      表示该条目是基于值相等的无名称匹配证据——一个需要验证的假设,而非已解决的绑定:带有
      candidates
      的条目列出了具有相同值的令牌,需根据含义选择;语义错误的令牌比原始值更糟(此时应保留原始值并记录缺口),且绑定的Figma变量始终优先于原始值匹配。
    • framework-builtin
      (Tailwind内置刻度步骤,如
      spacing/4
      line-height/7
      weight/Bold
      ):包含
      builtin: { scale, step }
      ——组合实用类(如
      p-4
      /
      gap-4
      leading-7
      font-bold
      ),不要使用任意值
      p-[16px]
      。这不属于缺口。
    • unmapped
      :使用该值但需指出缺口(建议将其添加到令牌源);不要静默硬编码。
    • figmaModes
      { Light: …, Dark: … }
      ,文件的主题轴位于
      themedCollections
      ):令牌依赖主题——
      figmaValue
      仅为默认模式,而非全部内容。已映射:输出
      candidate.ref
      并确认项目令牌本身会随主题切换(如
      .dark
      /
      [data-theme]
      /
      prefers-color-scheme
      /
      dark:
      规则);如果项目仅定义了一个值,则将其他模式的值关联到该机制或指出主题缺口。未映射:默认模式为基础,其他模式遵循项目的暗色模式机制(如
      dark:
      变体 /
      prefers-color-scheme
      )。未使用原生模式编码的主题——配对集合或名称组(如
      Color/Light/*
      +
      Color/Dark/*
      ,受计划限制的变通方案)——采用相同处理方式。
  4. 导出无法通过事实工具传递的资源——标志、照片、图标没有像素,否则会渲染为灰色块。对
    IMAGE
    填充节点使用
    save_image_fills
    (原始资源,而非裁剪后的重渲染),先对图标使用
    icon_map
    (重用经过整理的
    .svg
    文件),仅对合成外观使用
    get_screenshot
    。 → 完整的资源/图标/SVG/颜色约定工作流程:
    references/assets-and-icons.md
然后根据检测到的技术栈生成代码(配置文件来自
component_map
/
token_map
;无需自行调用
analyze_project
):组合重用的组件,包装未映射的部分,并为颜色/间距/圆角/排版应用令牌引用。

Keep code in sync as the design changes

随设计变更保持代码同步

Codegen is rarely one-shot — the design keeps moving. To make the second pass an incremental edit instead of a regeneration:
  • After you generate,
    design_diff
    on the section/component
    nodeId
    saves a baseline (its
    get_design_context
    ) under
    .figwright/snapshots/
    . Committing that file lets teammates share the baseline; the tool never touches git.
  • When asked to re-sync ("the design changed, update the component"),
    design_diff
    the same
    nodeId
    again: it returns the per-node, per-property delta —
    added
    /
    removed
    /
    changed
    nodes with resolved values (a fill, a padding, a text string, a token rebind), each with a readable
    path
    (
    Card / Header / Title
    ). Edit only the code those nodes map to; don't regenerate the screen. Ground each changed value the usual way (it's a
    get_design_context
    slice), then
    design_diff
    with
    update: true
    to accept the new design as the baseline.
  • Scope it by the same
    nodeId
    unit you coded from.
    no-changes
    means the design is untouched since the baseline — nothing to do.
代码生成很少是一次性的——设计会持续更新。为了让第二次迭代成为增量编辑而非重新生成:
  • 生成代码后,对区块/组件的
    nodeId
    调用
    design_diff
    ,将基线(其
    get_design_context
    )保存到
    .figwright/snapshots/
    目录下。提交该文件可让团队成员共享基线;工具绝不会触碰git。
  • 当要求重新同步时(“设计已变更,更新组件”),再次对相同的
    nodeId
    调用
    design_diff
    :它会返回每个节点、每个属性的差异——
    added
    /
    removed
    /
    changed
    节点及已解析的值(如填充、内边距、文本字符串、令牌重新绑定),每个都带有可读的
    path
    (如
    Card / Header / Title
    )。仅编辑这些节点映射到的代码;不要重新生成整个页面。按照常规方式验证每个变更的值(这是
    get_design_context
    的切片),然后调用
    design_diff
    并设置
    update: true
    以接受新设计作为基线。
  • 按照你编码时使用的相同
    nodeId
    单元限定范围。
    no-changes
    表示自基线以来设计未被修改——无需执行任何操作。

Record verified mappings (so the next run reuses, not re-guesses)

记录已验证的映射关系(让下次运行重用而非重新猜测)

The joins re-derive from scratch every run. A mapping you confirmed — reused a component and it rendered right, resolved an ambiguous colour to the semantically correct token — is worth recording so the next run treats it as ground truth instead of re-guessing. Two append-only map files, each read back by its join as highest authority:
  • docs/figma-component-map.md
    — rows
    | FigmaName | code/path |
    (or
    FigmaName -> path
    ).
    component_map
    then returns that component as
    source: 'map-file'
    , confidence 1.
  • docs/figma-token-map.md
    — rows
    | FigmaName | ref |
    .
    token_map
    returns it as
    matchedBy: ['map-file']
    , confidence 1. The
    ref
    is what you'd emit — a utility (
    bg-primary-500
    ), a
    var(--color-primary-500)
    , or the bare token name.
  • A recorded row OVERRIDES the fuzzy join on every future run — so record proof, not a pick. The gate is your own verify step (§ Responsive & verify): only after you rendered the result and it matched the Figma node do you record the mapping you proved. A wrong row doesn't fail loudly — it silently mis-maps that component/token in every future generation until a human notices, which is worse than no record at all. If you're not certain, don't record it; a re-guess next run is recoverable, a confidently-wrong recorded row is not.
  • Record only the mappings the join was unsure of — a
    low
    /
    medium
    component match you confirmed, an
    unmapped
    component you built (record its new file), or a token that came back
    ambiguousWith
    /
    matchedBy: ['value']
    /
    unmapped
    and you resolved by meaning. Skip the already-
    high
    deterministic matches; they re-derive correctly and a row for them is just noise.
  • These files are committed project docs — treat a row like a line of code you're asserting is correct, not a scratch note. One figma name → one target per row; keep them reviewable.
  • Keep the files healthy. When
    component_map
    /
    token_map
    report
    staleOverrides
    (a recorded target that no longer resolves — the file/token was renamed or deleted), the join has already degraded to the fuzzy result; fix that row to the new target or delete it.
每次运行都会重新推导关联关系。你已确认的映射——重用组件且渲染正确,将模糊的颜色解析为语义正确的令牌——值得记录,以便下次运行将其视为事实依据而非重新猜测。两个仅追加的映射文件,每个都会被其关联工具作为最高优先级读取:
  • docs/figma-component-map.md
    —— 行格式为
    | FigmaName | code/path |
    (或
    FigmaName -> path
    )。
    component_map
    会将该组件返回为
    source: 'map-file'
    ,置信度为1。
  • docs/figma-token-map.md
    —— 行格式为
    | FigmaName | ref |
    token_map
    会将其返回为
    matchedBy: ['map-file']
    ,置信度为1。
    ref
    是你要输出的内容——实用类(如
    bg-primary-500
    )、
    var(--color-primary-500)
    或令牌名称。
  • 已记录的行会覆盖未来每次运行的模糊关联——因此要记录已验证的结果,而非随意选择。 门槛是你自己的验证步骤(§ 响应式设计与验证):只有在你渲染结果并确认其与Figma节点匹配后,才记录你已验证的映射。错误的行不会明显报错——它会在未来每次生成中静默错误映射该组件/令牌,直到有人发现,这比没有记录更糟糕。如果你不确定,不要记录;下次运行重新猜测是可恢复的,但自信记录的错误行则不然。
  • 仅记录关联工具不确定的映射——你已确认的
    low
    /
    medium
    组件匹配、你构建的
    unmapped
    组件(记录其新文件),或者返回
    ambiguousWith
    /
    matchedBy: ['value']
    /
    unmapped
    且你已根据含义解决的令牌。跳过已确定的
    high
    匹配;它们会被正确重新推导,记录这些行只是冗余信息。
  • 这些文件是已提交的项目文档——将每一行视为你断言正确的代码,而非临时笔记。每个Figma名称对应一个目标;保持文件可审阅。
  • 保持文件有效。当
    component_map
    /
    token_map
    报告
    staleOverrides
    (已记录的目标无法解析——文件/令牌已重命名或删除)时,关联工具已降级为模糊结果;将该行修复为新目标或删除它。

Responsive & verify

响应式设计与验证

  • Responsive by default — root is
    w-full
    , never the artboard's fixed width; ground breakpoints from the file's other-width frames. →
    references/responsive.md
    .
  • Verify visually before you call it done — render with the project's toolchain, screenshot at the design's viewport, diff against the Figma node, fix at the source. →
    references/verify.md
    .
  • 默认支持响应式 —— 根元素为
    w-full
    ,绝不要使用画板的固定宽度;从文件的其他宽度框架中确定断点。→
    references/responsive.md
  • 完成前先进行视觉验证 —— 使用项目的工具链渲染,在设计的视口截图,与Figma节点对比差异,从源头修复。 →
    references/verify.md

Motion (animation)

动效(动画)

When
get_design_context
(full detail) tags a node with a
motion
summary — applied animation-style presets, animated property fields, a timeline duration — carry it into the project's animation mechanism (CSS
@keyframes
/
transition
, Framer Motion, GSAP, Vue
<transition>
) instead of emitting a static component.
get_node_motion
returns the full keyframe detail when the summary isn't enough. Dropping a frame's animation is a fidelity miss, the same class as dropping a shadow. →
references/motion.md
.
get_design_context
(完整详情)为节点标记
motion
摘要时——应用的动画样式预设、动画属性字段、时间线时长——将其转换为项目的动画机制(如CSS
@keyframes
/
transition
、Framer Motion、GSAP、Vue
<transition>
),而非输出静态组件。当摘要不够详细时,
get_node_motion
会返回完整的关键帧详情。忽略框架的动画是保真度缺失,与忽略阴影属于同一类问题。 →
references/motion.md

Rules

规则

  • Ground every section — never eyeball a value off the screenshot. Every px size, colour, font-size, radius, and spacing comes from
    get_design_context
    , for every section. The screenshot is visual intent only; guessing "the easy sections" is the cardinal miss. On a page too big to ground at once, scope by section
    nodeId
    — never depth-cap the whole page, never retry an oversized call.
  • Reuse beats regenerate. A
    high
    /
    medium
    component_map
    candidate must be imported and used.
  • Reference tokens, not literals. Emit a mapped variable's
    ref
    ; reserve raw values for
    unmapped
    gaps, and surface those gaps rather than burying them.
  • Carry every visual property, don't drop fidelity. Effects, per-side borders +
    strokeAlign
    , per-corner radius, blend mode, masks, gradients, image
    scaleMode
    , and auto-layout/grid spacing are all in the context — translate each (the catalog is in
    references/grounding.md
    ). Dropping any is a grounding miss, not a simplification.
  • Export visual assets, don't fake them. A grey box or a hand-typed wordmark is a miss.
  • Match the project, not a house style. Mirror the existing import style, file layout, and naming.
  • Render and verify before you call it done. (See
    references/verify.md
    .)
  • Never write a config file or wizard prompt; everything is inferred from the project + the tools.
  • 每个部分都基于事实——绝不要从截图中目测取值。 每个像素尺寸、颜色、字体大小、圆角和间距都来自
    get_design_context
    ,覆盖所有部分。截图仅用于视觉参考;猜测“简单部分”是最严重的错误。对于单次调用无法处理的大型页面,按区块
    nodeId
    划分范围——绝不要限制整个页面的深度,绝不要重试超出范围的调用。
  • 重用优先于重新生成。
    component_map
    中的
    high
    /
    medium
    候选组件必须被导入并使用。
  • 引用令牌,而非字面量。 输出已映射变量的
    ref
    ;仅为
    unmapped
    缺口保留原始值,并指出这些缺口而非隐藏它们。
  • 保留所有视觉属性,不要降低保真度。 效果、单边边框 +
    strokeAlign
    、圆角半径、混合模式、遮罩、渐变、图片
    scaleMode
    以及自动布局/网格间距都包含在上下文中——逐一转换(目录位于
    references/grounding.md
    )。忽略任何一项都是基于事实的工具使用失误,而非简化。
  • 导出视觉资源,不要伪造。 灰色框或手动输入的标志是失误。
  • 匹配项目风格,而非通用风格。 镜像现有的导入风格、文件布局和命名方式。
  • 完成前先渲染并验证。(参见
    references/verify.md
    。)
  • 绝不要编写配置文件或向导提示;所有内容都从项目和工具中推断。