mcpField
F
figma-generate-design

figma-generate-design

github.com/figmaデザイン・UI2.1k6.0k 回インストール今日更新
リポジトリ

figma-generate-design について

figma-generate-designは、コードや説明をもとにFigmaの複合ビューを作成・更新するスキルです。公開済みデザインシステムのアセットを活用し、編集可能なレイヤーで構成することを重視します。

主な機能

  1. 01複合ビューの作成・更新
  2. 02デザインシステムのコンポーネントと変数の再利用
  3. 03Code Connectアセットの検索と適用
  4. 04Webアプリのキャプチャを参照に利用

活用シーン

  1. 01既存コードからビューを構築
  2. 02既存のFigma画面を更新
  3. 03デザインシステムを使った複数セクションの作成

MCP 対応

Figma MCPサーバーへの接続が必要で、Figmaツールの呼び出しにはfigma-useとの併用が求められます。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/figma/mcp-server-guide --skill figma-generate-design

インストール後、Claude Code で/figma-generate-designを入力して読み込まれたか確認します。

同梱ファイルreferences/componentization.mdreferences/discover-product-font.md

詳細

デザインシステムを使用した画面とビューの作成・更新

必須成果物の条件: コードからデザインを生成する際は、UIを編集可能なテキスト、コンポーネント、アイコン、階層構造で再現する必要があります。 スクリーンショットやUI全体をフラット化したレンダリングは、あくまで視覚的な参考資料としてのみ扱ってください。リポジトリ内に存在する場合や、よりピクセル単位で正確に見える場合であっても、ラッパーの塗りや子ノードとしてなど、成果物にアップロードまたはインポートしてはいけません。完了前に結果を確認し、UIの大部分が編集可能なレイヤーで構成されていない場合は、意味のある構造で再構築するか、失敗を報告してください。

このスキルは、ハードコードされた値でプリミティブを描画するのではなく、公開済みのデザインシステム(コンポーネント、変数、スタイル)を再利用して、Figmaで画面、ビュー、複数セクションから成るUIコンテナーを作成または更新するために使用します。対象には、ページ全体、モーダル、ダイアログ、ドロワー、サイドバー、パネル、複数のセクションで構成されるビューが含まれます。重要なのは、FigmaファイルにコードベースのUIコンポーネントやトークンに対応するコンポーネント、色・間隔の変数、テキスト・エフェクトスタイルを含む公開済みデザインシステムがある可能性が高いという点です。16進数カラーのボックスを描画するのではなく、それらを見つけて使用してください。

必須: use_figma を呼び出す前に、必ず figma-use も読み込んでください。このスキルには、色の範囲やフォントの読み込みなど、作成するすべてのスクリプトに適用される重要なルールが含まれています。

利用可能な場合は、ファイルの読み取りや編集を行う前に、fileKey と description を指定して create_session を呼び出してください(必要であれば、最初にファイルを作成します)。その後、返された sessionId は変更せず、フォローアップや複数ファイルにまたがる作業を含め、sessionId を受け付けるすべての呼び出しに渡してください。

このスキルの一環として use_figma を呼び出す場合、カンマ区切りの skillNames パラメーターには、必ず figma-generate-design を含めてください。このスキルを MCP リソース経由で読み込んだ場合は、名前に必ず resource: を付けてください(例:resource:figma-generate-design)。これはログ用のパラメーターであり、実行には影響しません。

HTML-to-Figma の例外

次の場合は、初回作成に html_to_figma を使用してください。

  • 入力が既存の未加工または静的な HTML ドキュメントの場合は、そのまま html_to_figma に渡してください。
  • 新しいデザインの作成を求められていて、再現対象となるレンダリング済みUIの実装がない場合は、自己完結型のHTMLドキュメントを作成して html_to_figma に渡してください。

html_to_figma を利用できない場合は、以下の既存のワークフローに従ってください。

スキルの適用範囲

  • 成果物がデザインシステムのコンポーネントインスタンスを使って構築する複合的なFigmaビュー(新規または更新)の場合は、このスキルを使用してください。フォーム、ダッシュボード、リスト、テーブル、カード、ヘッダー、パネル、ダイアログ、メッセージプレビュー、その他の複数セクションから成るコンテナーが対象です。ユーザーが複合ビューをコンポーネントと呼ぶ場合でも適用されます。
  • 主な成果物が、バリアント、トークン、公開を目的とする再利用可能なライブラリのプリミティブまたは基盤の場合は、figma-use とともに figma-generate-library を使用してください。
  • Code Connect のマッピングを作成する場合は、figma-code-connect に切り替えてください。

前提条件

  • Figma MCP サーバーに接続されていること
  • 対象のFigmaファイルに、公開済みのデザインシステムとコンポーネントがあること(またはチームライブラリにアクセスできること)
  • ユーザーが対象のFigmaファイル(URLまたは fileKey)を指定していること。まだ指定されていない場合は、まず /figma-create-new-file を呼び出す(または create_new_file を呼び出す)ことでファイルを作成し、返された file_key を再利用してください。use_figma と generate_figma_design のどちらにも、既存の fileKey が必要です。
  • 作成または更新する画面/ビューのソースコードまたは説明

generate_figma_design を使った並行ワークフロー(Web アプリのみ)

ブラウザーでレンダリングできる Web アプリの画面を作成する場合は、両方のアプローチを並行して実行すると、最良の結果が得られます。

  1. 並行して実行します:
    • このスキルのワークフロー(use_figma + デザインシステムのコンポーネント)を使って、対象の Figma ファイル(fileKey)に画面を作成します。
    • generate_figma_design を同じ fileKey に対して実行し、実行中の Web アプリのピクセル単位で正確なスクリーンショットをそのファイルに取り込みます。generate_figma_design では常に fileKey が必要です。ユーザーがまだ Figma ファイルを持っていない場合は、まず /figma-create-new-file を呼び出す(または MCP ツールの create_new_file を呼び出す)ことでファイルを取得し、このスキルとキャプチャの両方で同じ file_key を再利用します。
  2. 両方が完了したら: use_figma の出力を更新し、generate_figma_design のキャプチャにあるピクセル単位で正確なレイアウトに合わせます。キャプチャは目標とする正確な余白、サイズ、視覚的な処理を示します。一方、use_figma の出力にはデザインシステムにリンクされた適切なコンポーネントインスタンスがあります。キャプチャに画像が含まれている場合は、キャプチャの画像塗りつぶしから imageHash の値をコピーして、use_figma の出力に転送します(詳細はステップ 5 を参照)。
  3. 見た目に問題がないことを確認したら: generate_figma_design の出力を削除します。これは視覚的な参照としてのみ使用したものです。

この方法では、両方の利点を活用できます。generate_figma_design はピクセル単位で正確なレイアウトを実現し、use_figma はデザインシステムにリンクされ、更新可能な適切なコンポーネントインスタンスを実現します。

アプリで使用する写真、アバター、ロゴ、アイコンなどの独立したコンテンツ画像がソースに含まれている場合、この並行ワークフローは必須です。スクリーンショットや UI 全体をフラット化したレンダリングは視覚的な参照であり、コンテンツ画像ではありません。 use_figma Plugin API は外部画像 URL を取得できず、ファイル内のノードから imageHash の値をコピーすることでしか画像塗りつぶしを設定できません。generate_figma_design は表示されているすべての画像を Figma にラスタライズし、必要なハッシュを提供します。こうしたコンテンツ画像があるのにキャプチャを省略すると、その画像フレームは空白になります。

Web アプリ以外(iOS、Android など)や既存の画面を更新する場合は、以下の標準ワークフローを使用してください。

必須のワークフロー

以下の手順を順番に実行してください。手順を省略しないでください。

必ず守ること:

  • 成果物を変更する前に、Code Connect の検出を完了し、対象のライブラリを選択します。検出のみを目的としたインポートや一時インスタンスの作成は可能ですが、一時インスタンスはすぐに削除してください。
  • 選択した各アセットは、インポートした場所に適用します。インポートに失敗した場合は、手動で代替する前に、適用可能な次の完全一致の結果を試してください。
ステップ 1:成果物を把握する

Figma を操作する前に、作成するものを把握してください。

  1. コードから作成する場合は、関連するソースファイルを読み、構造、セクション、使用されているコンポーネントを把握します。
  2. ビューの主要なセクションを特定します(例:ページの場合はヘッダー、ヒーロー、コンテンツパネル、フッター、モーダルの場合はタイトルバー、フォームセクション、アクションバー、サイドバーの場合はナビゲーション、コンテンツ領域、フッターアクション)。
  3. 各セクションに含まれる UI コンポーネント(ボタン、入力欄、カード、ナビゲーションピル、アコーディオンなど)を一覧にします。
  4. ソースから製品のフォントファミリーを特定します。Inter をデフォルトにしないでください。 スクリプトを書く前に、製品でどの書体が使われているかを確認します。確認する場所(CSS 変数、コンポーネントファイル)や、複雑な Figma のフォント名を解決する方法については、references/discover-product-font.md を参照してください。
  5. ビューに画像が含まれているか確認します(例:<img>、<Image>、背景画像、製品写真、アバター、URL から読み込まれるアイコン)。画像が含まれていて Web アプリの場合は、並行する generate_figma_design のキャプチャワークフローを必ず実行してください。コンポーネントを検出している間にキャプチャが実行されるよう、ステップ 2 と同時にすぐ開始します。上記の「generate_figma_design を使った並行ワークフロー」を参照してください。
ステップ 2:コンポーネント、変数、スタイルを収集する

デザインシステムから必要なものは 3 つあります。コンポーネント(ボタン、カードなど)、変数(色、間隔、角丸)、スタイル(テキストスタイル、影などのエフェクトスタイル)です。デザインシステムのトークンが存在する場合は、16 進数の色コードやピクセル値をハードコードしないでください。

2a:コンポーネントを見つける

2a-i — 必須:必要なコンポーネントの Code Connect を確認します。 ステップ 1 で作成したコンポーネント一覧をもとに、各コンポーネントに対応する Code Connect ファイルがコードベース内にあるか確認します。Code Connect ファイルはコンポーネントのソースと同じ場所にあり、プラットフォームごとに次の名前が付けられています。

  • TypeScript/JS:*.figma.ts、*.figma.js
  • React(パーサーベース):*.figma.tsx
  • Kotlin/Compose:@FigmaConnect を含む .kt ファイル
  • Swift:FigmaConnect を含む .swift ファイル

必要な各コンポーネント(例:Button、Card、Input)について、その Code Connect ファイルを検索します。コンポーネント名で glob または grep を使用します(例:**/Button.figma.tsx、**/Card.figma.ts)。実際に必要なコンポーネントに一致するファイルだけを読み取ってください。

一致した各 Code Connect ファイルから、Figma コンポーネントの URL を抽出します。URL から fileKey と nodeId を解析します(ハイフンをコロンに変換します:123-456 → 123:456)。次に、use_figma を使ってコンポーネントキーを解決します。

例: Code Connect ファイルに // url=https://figma.com/design/ABC123/File?node-id=609-35535 が含まれている場合、fileKey = ABC123、nodeId = 609:35535 と解析します。キーを解決するには、ライブラリファイル(対象ファイルではなく、fileKey ABC123)を対象に use_figma を実行します。

const node = await figma.getNodeByIdAsync("609:35535");
const set = node?.parent?.type === "COMPONENT_SET" ? node.parent : node;
if (set?.type === "COMPONENT_SET") {
  return { assetType: "component_set", componentSetKey: set.key };
}
if (set?.type === "COMPONENT") {
  return { assetType: "component", componentKey: set.key };
}
throw new Error("Expected a component or component set");

複数の検索は 1 回の呼び出しにまとめてください。ステップ 4 で各項目の assetType に応じて、返されたキーを importComponentByKeyAsync() または importComponentSetByKeyAsync() で使用します。

解決済みのコンポーネントに印を付け、未解決のコンポーネントを続けて確認します。

2a-ii — 必須:ライブラリの範囲を選択し、ビュー全体を検索して調査します。 get_libraries を呼び出します。ユーザーが 1 つ以上のライブラリを指定した場合は、それらが libraries_added_to_file と libraries_available_to_add のどちらに表示されているかにかかわらず、正確なキーを使用します。そうでない場合は、libraries_added_to_file のすべてのライブラリをまとめて検索します。選択したキーは、すべての検索で includeLibraryKeys に渡します。未解決の不足項目に適切な候補がない場合に限り、libraries_available_to_add から関連性の高いライブラリを追加して、その未解決のクエリを再試行します。無関係な利用可能ライブラリまで検索範囲を広げないでください。最初の search_design_system のバッチ呼び出しには、ソースまたは Code Connect の調査ですでに判明している未解決項目のクエリと合わせて、要求されたビューまたはフローに対するコンポーネントクエリを 1 つ含めます。ビュー全体のクエリには、目的とコンテナを示す名前を付けます(例:billing settings drawer)。最有力候補を調査します。候補が要求されたセクションを 2 つ以上カバーしている場合は、それを基盤として選択します。そうでない場合は、ビュー全体を対象とした複合候補を使わずに続けます。

2a-iii — 既存の画面を調査します。 対象ファイルに、同じデザインシステムを使用する画面がすでに含まれているか確認します。読み取り専用の use_figma 呼び出しを 1 回実行すると、既存のフレーム内のコンポーネントキー、バインドされた変数、テキストスタイル、エフェクトスタイルを、信頼できる一度の処理で一覧化できます。ここで 1 回だけ実行し、フレームを再走査するのではなく、その結果を 2b と 2c でも再利用します。

const frame = figma.currentPage.findOne(n => n.name === "Existing Screen");
const components = new Map();
const styles = { text: new Map(), effect: new Map() };
const variableIds = new Set();

// boundVariables and style ids can sit on any scene node, so walk them all.
for (const node of frame?.findAll(() => true) ?? []) {
  if (node.type === "INSTANCE") {
    const mc = node.mainComponent;
    const cs = mc?.parent?.type === "COMPONENT_SET" ? mc.parent : null;
    const key = cs ? cs.key : mc?.key;
    if (key && !components.has(key)) {
      components.set(key, { name: cs ? cs.name : mc.name, key, isSet: !!cs, sampleVariant: mc.name });
    }
  }
  for (const b of Object.values(node.boundVariables ?? {}).flat()) {
    if (b?.id) variableIds.add(b.id);
  }
  for (const [prop, bucket] of [["textStyleId", "text"], ["effectStyleId", "effect"]]) {
    if (prop in node && typeof node[prop] === "string" && node[prop]) {
      const s = await figma.getStyleByIdAsync(node[prop]);
      if (s) styles[bucket].set(s.id, { name: s.name, id: s.id, key: s.key });
    }
  }
}
const vars = await Promise.all([...variableIds].map(id => figma.variables.getVariableByIdAsync(id)));

return {
  components: [...components.values()],
  variables: vars.filter(Boolean).map(v => ({ name: v.name, id: v.id, key: v.key, type: v.resolvedType, remote: v.remote })),
  textStyles: [...styles.text.values()],
  effectStyles: [...styles.effect.values()],
};

components を未解決のコンポーネントと照合します。2a-i で取得した Code Connect のキーは引き続き正とします。新たに解決できた項目に印を付けます。

2a-iv — 構築に必要な不足項目だけを検索します。 Code Connect、ビュー全体の検出、既存画面の調査を終えたら、未解決のコンポーネントと、デザインに必要なトークンを検索します。独立した目的ごとに項目をまとめ、includeLibraryKeys は選択したライブラリの範囲に限定し、選択したキーは構築時に引き継ぎます。未解決の役割をすべて網羅的に検索するために、構築を遅らせないでください。

// Step 1: Discover available libraries
get_libraries({ fileKey })
// Returns: {
//   libraries_added_to_file: [...],
//   libraries_available_to_add: [...],
//   libraries_available_to_add_next_offset: number | null
// }

// Step 2: Search within a specific library using its libraryKey
search_design_system({ queries: [{ entity: "component", query: "button" }], fileKey, includeLibraryKeys: ["lk-abc123..."] })

libraries_available_to_add 内の組織ライブラリは、1 ページあたり 20 件でページ分割されています。libraries_available_to_add_next_offset が null 以外の場合は、組織ライブラリがまだあります。offset にその値を指定して get_libraries を再度呼び出し、次のページを取得してください。コミュニティ UI キットは最初のページにのみ表示されます。ユーザーが指定したライブラリが現在のページに見当たらない場合は、諦める前にさらにページを取得してください。

これは、ファイルに多数のライブラリがあり、対象を絞った結果を得たい場合に特に役立ちます(たとえば、すべてのライブラリから一致するものを取得するのではなく、「iOS 26」または「Material 3」のみを検索する場合)。

クエリごとにインテントは 1 つにしてください。 search_design_system は OR 検索を適用しないため、複数の候補や同義語を 1 つの文字列に詰め込まないでください(「Button IconButton icon」では有用な結果が得られません)。判明している場合は、デザインシステムの正確な名前またはコンポーネントの種類を指定してください。そうでない場合は、「archive action icon」や「primary submit button」のように、アセットの UI 上の役割で検索してください。 選択したキーはすべて、セクションまたはプロパティに対応付けてください。該当する複合コンポーネントの子孫を再利用し、並行する代替要素を作成しないでください。例やテンプレートのラッパーだけを切り離す必要がある場合を除き、ネストされたインスタンスはそのまま保持してください。

コンポーネントのプロパティをマップに含めてください。各コンポーネントがテキストの上書きに使用できる TEXT プロパティを把握する必要があります。一時的なインスタンスを作成して、その componentProperties(およびネストされたインスタンスの componentProperties)を読み取り、その後、一時インスタンスを削除してください。

プロパティ情報を含むコンポーネントマップの例:

Component Map:
- Button → key: "abc123", type: COMPONENT_SET
  Properties: { "Label#2:0": TEXT, "Has Icon#4:64": BOOLEAN }
- PricingCard → key: "ghi789", type: COMPONENT_SET
  Properties: { "Device": VARIANT, "Variant": VARIANT }
  Nested "Text Heading" has: { "Text#2104:5": TEXT }
  Nested "Button" has: { "Label#2:0": TEXT }
2b: 変数を特定する(色、間隔、角丸)

まず既存の画面を調べてください。 2a-iii のインベントリにある variables を再利用してください。この手順を省略した場合は、既存の画面があるときにここでインベントリを実行してください。未解決の変数については、entity が "variable" のエントリを queries に指定して search_design_system を使用してください。

WARNING:変数を特定する 2 つの異なる方法を混同しないでください。

  • use_figma の figma.variables.getLocalVariableCollectionsAsync() は、現在のファイル内で定義されたローカル変数のみを返します。結果が空でも、変数が存在しないとは限りません。リモート/公開済みライブラリの変数は、この API からは見えません。
  • entity: "variable" のクエリエントリを指定した search_design_system は、リモートおよび公開済みのライブラリ変数を検索します。各クエリのスコープは、2a-ii で選択したライブラリキーに限定し、includeLibraryKeys を指定してください。

getLocalVariableCollectionsAsync() が空を返したことだけを根拠に、「変数は存在しない」と判断しないでください。 独自に変数を作成すると決める前に、必ず search_design_system の変数クエリエントリも実行し、ライブラリ変数を確認してください。

クエリの方針: search_design_system はカテゴリではなく、変数名(「Gray/gray-9」、「core/gray/100」、「space/400」など)を対象に照合します。1 つの複合クエリではなく、短く簡潔な検索語を複数まとめて 1 回の queries 呼び出しで指定してください。配列の各エントリは必ず { "entity": "variable", "query": "..." } オブジェクトにしてください。文字列だけの値は指定しないでください。

  • プリミティブカラー: { "entity": "variable", "query": "gray" }、{ "entity": "variable", "query": "red" } など。
  • セマンティックカラー: { "entity": "variable", "query": "background" }、{ "entity": "variable", "query": "surface" } など。
  • 間隔/サイズ: { "entity": "variable", "query": "space" }、{ "entity": "variable", "query": "radius" } など。

最初の検索で結果が空の場合は、より短い語句や異なる命名規則を試してください。ライブラリによって命名規則は大きく異なります(「grey」と「gray」、「spacing」と「space」、「color/bg」と「background」など)。

ライブラリ変数(remote = true)は、キーを指定して figma.variables.importVariableByKeyAsync(key) でインポートしてください。ローカル変数には、figma.variables.getVariableByIdAsync(id) を直接使用してください。

バインディングのパターンについては、variable-patterns.md を参照してください。

2c:スタイルを確認する(テキストスタイル、エフェクトスタイル)

2a-iii または 2b のインベントリから textStyles と effectStyles を再利用します。インベントリがない場合は、同じスクリプトで利用可能な画面を調べます。再利用可能な塗り/線、タイポグラフィ、エフェクトの役割が未解決のままハードコードする前に、entity: "style" を指定して、たとえば「surface」、「border」、「heading」、「body」、「shadow」、「elevation」など、対象を絞った search_design_system エントリーを実行します。独立したエントリーはまとめて検索しますが、選択したコンポーネントまたは既存画面のスタイルでカバーされる役割を網羅的に検索しないでください。まだ見つかっていないスタイルを検索します。

ライブラリのスタイルは figma.importStyleByKeyAsync(key) でインポートし、node.textStyleId = style.id または node.effectStyleId = style.id で適用します。

詳しくは、text-style-patterns.md と effect-style-patterns.md を参照してください。

ステップ 3:ラッパーフレームを作成する

セクションをトップレベルのページの子として作成し、後から親を変更しないでください — use_figma の呼び出しをまたいで appendChild() を使ってノードを移動すると、サイレントに失敗し、孤立したフレームが生成されます。まず変更可能なラッパーフレームを作成し、その中に各セクションを直接構築します。

選択したビュー全体を表すコンポジットがあれば、インポートしてラッパー内にインスタンス化します。そのコンポジットがカバーする子孫をカスタマイズし、不足しているセクションはラッパーに追加します。インスタンスに直接子を追加してはいけません。ラッパーは既存のコンテンツから離れた位置に配置し、その ID を返します。

// Find clear space
let maxX = 0;
for (const child of figma.currentPage.children) {
  maxX = Math.max(maxX, child.x + child.width);
}

const wrapper = figma.createAutoLayout("VERTICAL");

// --- Size the wrapper based on container type ---
// Full page:       wrapper.resize(1440, 100); wrapper.name = "Homepage";
// Modal/dialog:    wrapper.resize(640, 100);  wrapper.name = "Settings Modal";
// Drawer/sidebar:  wrapper.resize(360, 100);  wrapper.name = "Navigation Drawer";
// Panel:           wrapper.resize(400, 100);  wrapper.name = "Details Panel";
// Adapt width to match the source code's actual dimensions.

wrapper.name = "VIEW_NAME";
wrapper.primaryAxisAlignItems = "CENTER";
wrapper.counterAxisAlignItems = "CENTER";
wrapper.resize(WIDTH, 100);
wrapper.layoutSizingHorizontal = "FIXED";
wrapper.x = maxX + 200;
wrapper.y = 0;

return { success: true, wrapperId: wrapper.id };
ステップ 4:カバー済みのセクションをカスタマイズし、不足しているセクションを構築する

これが最も重要なステップです。 選択したコンポジットから始め、そのコンポジットがすでにカバーしている子孫をカスタマイズし、不足しているセクションだけを構築します。再試行に対応できる構築フェーズで作業し、安全な場合は関連するセクションをまとめて処理します。ページコンテキストの境界、復旧が難しい部分実行、または失敗後の対象を絞った再試行のためにのみ分割してください。検証チェックポイントを作るだけの目的で分割しないでください。各スクリプトの開始時に、ID を使って変更可能なラッパーフレームを取得します。新しいコンテンツはそのフレームに追加し、コンポーネントインスタンスには追加しないでください。

const createdNodeIds = [];

// Resolve the wrapper and import every design system dependency in parallel.
// Sequential awaits here serialize N independent IPC round-trips at the top
// of every section build; one Promise.all is dramatically faster.
const [wrapper, buttonSet, bgColorVar, spacingVar, shadowStyle] = await Promise.all([
  figma.getNodeByIdAsync("WRAPPER_ID_FROM_STEP_3"),
  figma.importComponentSetByKeyAsync("BUTTON_SET_KEY"),
  figma.variables.importVariableByKeyAsync("BG_COLOR_VAR_KEY"),
  figma.variables.importVariableByKeyAsync("SPACING_VAR_KEY"),
  figma.importStyleByKeyAsync("SHADOW_STYLE_KEY"),
]);
const primaryButton = buttonSet.children.find(c =>
  c.type === "COMPONENT" && c.name.includes("variant=primary")
) || buttonSet.defaultVariant;

// Build section frame with variable bindings (not hardcoded values)
const section = figma.createAutoLayout();
section.name = "Header";
section.setBoundVariable("paddingLeft", spacingVar);
section.setBoundVariable("paddingRight", spacingVar);
const bgPaint = figma.variables.setBoundVariableForPaint(
  { type: 'SOLID', color: { r: 0, g: 0, b: 0 } }, 'color', bgColorVar
);
section.fills = [bgPaint];

// Apply the effect style imported above
section.effectStyleId = shadowStyle.id;

// Create component instances inside the section
const btnInstance = primaryButton.createInstance();
section.appendChild(btnInstance);
createdNodeIds.push(btnInstance.id);

// Append section to wrapper
wrapper.appendChild(section);
section.layoutSizingHorizontal = "FILL"; // AFTER appending

createdNodeIds.push(section.id);
return { success: true, createdNodeIds };

各呼び出しで、作成したノード ID と、関連する件数、名前、境界ボックスを返します。これを標準の構造検証として使用してください。必要な情報が不足している場合、または関連する変更によって情報が無効になった場合に限り、別途構造を読み取ります。視覚的な確認はステップ 5 で行います。

setProperties() でインスタンスのテキストを上書きする

コンポーネントインスタンスには、プレースホルダーテキスト(「Title」、「Heading」、「Button」)が設定されています。ステップ 2 で見つけたコンポーネントプロパティキーを使い、setProperties() で上書きします。これは node.characters を直接操作するよりも確実です。詳しいパターンについては、component-patterns.md を参照してください。

独自の TEXT プロパティを公開するネストされたインスタンスでは、ネストされたインスタンスに対して setProperties() を呼び出します。

// Use the type-indexed criteria for the type filter, then narrow by name.
const nestedHeading = cardInstance
  .findAllWithCriteria({ types: ["INSTANCE"] })
  .find(n => n.name === "Text Heading");
if (nestedHeading) {
  nestedHeading.setProperties({ "Text#2104:5": "Actual heading from source code" });
}

コンポーネントプロパティで管理されていないテキストに限り、フォールバックとして node.characters を直接操作します。

ソースコードのデフォルト値を注意深く確認する

コードコンポーネントを Figma インスタンスに変換するときは、明示的に渡された値だけでなく、ソースコードでコンポーネントのデフォルトの prop 値を確認してください。たとえば、variant prop が指定されていない <Button size="small">Register</Button> の場合は、コンポーネント定義を調べ、デフォルトが variant = "primary" であることを確認します。誤ったバリアント(たとえば Primary ではなく Neutral)を選ぶと、見落としやすい視覚的な不整合が生じます。

手動で作成するものとデザインシステムからインポートするもの
手動で作成デザインシステムからインポート
ラッパーフレームコンポーネント:ボタン、カード、入力欄、ナビゲーションなど
セクションコンテナーフレーム変数:色(塗り、線)、間隔(パディング、間隔)、角丸
レイアウトグリッド(行、列)テキストスタイル:見出し、本文、キャプションなど
エフェクトスタイル:影、ぼかしなど

デザインシステムの変数がある場合は、16進数の色やピクセル単位の間隔をハードコードしないでください。間隔や角丸には setBoundVariable を、色には setBoundVariableForPaint を使用してください。テキストスタイルは node.textStyleId で、エフェクトスタイルは node.effectStyleId で適用してください。

繰り返し使用できる要素をコンポーネント化する(必須)

コンポーネント化は任意の追加作業ではなく、標準のワークフローの一部です。最初の段階でコンポーネント化された構造を作成してください。一度きりのフレームを並べたフラットなツリーを出力し、2回目の「今度はコンポーネント化してください」というプロンプトを待つのはやめてください。

  • デザインシステムのインスタンスは、すでにコンポーネント化されています(ステップ 2)。優先して使用してください。
  • デザインシステムでカバーされない要素でも、繰り返し使用される場合、または再利用可能なソースコンポーネントに対応する場合は、figma.createComponent() でローカルコンポーネントを一度作成してインスタンスを配置してください。よく似たフレームを N 個、個別に手作りするのは避けてください。1 つのソースコンポーネントは、1 つの Figma メインコンポーネントに対応します。

一度作成してインスタンスを配置するパターンとコードについては、references/componentization.md を参照してください。

アイコン:SVG をインポートし、回転したプリミティブから再構築しない

アイコンは、上記の手動作成とインポートの区分における主な例外です。デザインシステムにアイコンがコンポーネントとして用意されている場合は、そのインスタンスを使用してください(アイコンごとにバリアントを作るのではなく、単一の INSTANCE_SWAP プロパティを使用します)。そうでない場合、特にコードベースからアイコンを取得して Figma に配置または置き換える場合は、アイコンのSVG ソースを直接ベクターノードとしてインポートしてください。これがアイコンの基本かつ標準的な方法です。描き直さないでください。

  1. コードベースから SVG を取得します。 インラインの <svg>、インポートされた .svg アセット、またはアイコンライブラリのエントリーからアイコンのソースを読み取り、その SVG 文字列をそのまま渡します。手作業で作成するのではなく、コードベースにある SVG を優先してください。
  2. figma.createNodeFromSvg(svgString) でインポートします。 編集可能なベクターパスを含む FrameNode が返されます。SVG 文字列には viewBox と明示的な width/height(例:<svg width="24" height="24" viewBox="0 0 24 24" ...>)を必ず含めてください。width/height がない場合は viewBox のサイズが使用されますが、これはスロットより小さいことが多く、「アイコンのサイズが適切でない」問題の一般的な原因です。
  3. スロットに合わせてサイズを調整します。 createNodeFromSvg が作成するフレームはリサイズ時に内容も拡大縮小するため、icon.resize(size, size) でアイコン全体(線の太さを含む)を対象のボックスに合わせられます。同様に、作成時に width/height を対象サイズと同じ値に設定する方法もあります。ソースのアイコンサイズに合わせてください。一般的には 16/20/24px です。
  4. 回転した線/四角形/楕円のプリミティブからアイコンを再構築しないでください。 use_figma のコンテキストでは Figma の線の回転は信頼性が低く、アイコンが崩れたり、回転がずれたりします(山形記号が塊になったり、矢印の先端が軸から外れたりします)。SVG をインポートする方が、信頼性も編集のしやすさも優れています。
// Place / replace an icon from a codebase SVG into a 24px slot
const icon = figma.createNodeFromSvg(
  '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">' +
  '<path d="m9 18 6-6-6-6" stroke="#1A1A1A" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
);
icon.name = "icon/chevron-right";
icon.resize(24, 24);          // scales the whole icon to the slot
slotFrame.appendChild(icon);

コードベースの SVG では、通常 currentColor が使われています(例:stroke="currentColor"/fill="currentColor")。createNodeFromSvg でインポートすると、これは黒として扱われ、親の色は継承されません。インポート後に目的の色を設定してください。インポート前に SVG 文字列内の色を明示的な値に置き換えるか、setBoundVariableForPaint を使って、インポートしたベクターの塗りや線をデザインシステムの色変数にバインドします(他のペイントと同様です)。インポートした SVG を再利用可能なアイコンコンポーネント(INSTANCE_SWAP 用)にする方法については、figma-generate-library → アイコンコンポーネントの作成 と INSTANCE_SWAP パターンを参照してください。

ステップ 5:全体表示を検証して画像を転送する

視覚的な検証を行う前に、use_figma を使ってラッパーを読み戻し、子孫ノードの総数、存在する子孫ノードの種類ごとの数、および画像で塗りつぶされたすべてのノードの ID、名前、ノードタイプ、寸法を返します。これらの数は証拠であり、数値による合格基準ではありません。スクリーンショットから編集可能かどうかを推測したり、完全な UI のラスター画像の上に編集可能なトークンノードが重ねられている状態を受け入れたりしないでください。完全な UI のスクリーンショットまたはフラット化されたレンダリングがラッパー内のどこかに含まれている場合は、それを削除して UI をセマンティックに再構築するか、失敗を報告してください。完了したと主張してはいけません。

すべてのセクションを配置したら、ラッパーフレームの全体表示の構成スクリーンショットを 1 枚撮影し、ソースと比較します。意味のある視覚上の不具合が見つかった場合は、use_figma で対象を絞って修正してください。ビュー全体を作り直してはいけません。その後、修正後のスクリーンショットを1 枚撮影します。最新の合格スクリーンショットを最終確認とします。変更のない「最終」スクリーンショットを追加で撮影したり、セクションごとにスクリーンショットを撮影したりしないでください。

視覚的な修正を行う前に、ラッパーのインスタンス、スタイル、バインドされた変数のキーをステップ 2 のマップと比較します。該当するアセットはすべて出力に含まれている必要があります。完了前に、手動で作成した代替要素や生の値を置き換えてください。

構成スクリーンショットで次の点を確認します。

  • テキストの切り取り/クリッピング — 行の高さやフレームのサイズによって、ディセンダー、アセンダー、または行全体が切れていないか
  • コンテンツの重なり — サイズの誤りやオートレイアウトの欠落によって、要素が重なっていないか
  • 「Title」、「Heading」、「Button」などのプレースホルダーテキストが残っていないか
  • レイアウトのサイズ設定の不具合によって、コンテンツが途中で切れていないか
  • コンポーネントのバリアントが間違っていないか(例:Primary ボタンではなく Neutral ボタン)
  • フォントファミリーの誤り — テキストが製品で使用されているものとは異なる書体で描画されていないか(例:製品では SF Pro を使用しているのに Inter が使われている)。スクリプトがエラーなく実行されたため、一見しただけでは気づけません。明示的に確認してください(下記の「フォントファミリーが正しいことを確認する」を参照)。
  • 空の画像プレースホルダー — 画像が欠落している場合は、プレースホルダー生成のために generate_image を検討する前に、generate_figma_design のキャプチャから画像を転送してください(下記の「generate_figma_design のキャプチャから画像を転送する」を参照)。
フォントファミリーが正しいことを確認する

描画されたテキストが、ステップ 1 で特定した製品のフォントを使用していることを、必ず明示的に確認してください。不一致があれば、検証失敗として扱います。フォントの読み込みに成功したからといって、それが正しいフォントだと判断してはいけません。製品が SF Pro を使用しているのに Inter を読み込んだ場合、エラーが発生しなくても失敗です。参照ソース(実行中の Web アプリ、デザインモック、または generate_figma_design のキャプチャ)がある場合は、描画したスクリーンショットも必ず比較してください。適切なファミリーでもスタイルがわずかに異なると、ファミリーの確認には合格しても見た目が誤っている可能性があります。

読み戻し用スクリプト(個別に修正する自由配置テキストと、フラグを立てるデザインシステム管理テキストを区別します)とスクリーンショットの比較手順については、references/discover-product-font.md を参照してください。

generate_figma_design のキャプチャから画像を転送する

generate_figma_design を並行して実行した場合は、アプリで使用されている個別のコンテンツアセットのみをデザインシステムの出力に転送してください。キャプチャのルート、または完全な UI のスクリーンショットやフラット化されたレンダリングは、絶対にアップロードまたは転送しないでください。

  1. type === "IMAGE" の塗りつぶしを検索して、キャプチャ出力内のすべての画像ノードを見つけます。
    const capture = await figma.getNodeByIdAsync("CAPTURE_NODE_ID");
    const imageNodes = capture.findAll(() => true).flatMap(n => {
      if (!Array.isArray(n.fills)) return [];
      const imageFill = n.fills.find(f => f.type === "IMAGE");
      return imageFill ? [{ name: n.name, id: n.id, imageHash: imageFill.imageHash }] : [];
    });
    return imageNodes;
    
  2. キャプチャした各画像を、use_figma の出力内にある対応するフレームと照合します(位置、名前、または順序を基準にします)。
  3. 画像ハッシュを対象のフレームに適用します。
    targetFrame.fills = [{ type: "IMAGE", imageHash: "hash_from_capture", scaleMode: "FILL" }];
    
  4. すべての画像を転送したら、generate_figma_design のキャプチャ出力を削除します。
プレースホルダー画像の生成

まず、利用可能なソース画像、キャプチャ画像、ライブラリ画像を再利用します。プレースホルダーが残っている場合は、Figma の generate_image ツールを呼び出します。画像を生成した後、Figma AI のクレジットを使用して生成したことをユーザーに伝えます。

Figma AI が利用できない場合、または AI クレジットの上限に達した場合は、代替の画像生成ツールを使用してよいかユーザーに確認します。upload_assets でアップロードするのは、これらの代替プロバイダーの画像のみです。

ステップ 6:既存のビューの更新

ゼロから作成するのではなく既存のビューを更新する場合:

  1. get_metadata を使用して、既存の画面構成を調べます。
  2. 更新が必要なセクションと、そのまま残せるセクションを特定します。
  3. 変更が必要な各セクションについて:
    • ID または名前で既存のノードを特定します
    • デザインシステムのコンポーネントが変更されている場合は、コンポーネントインスタンスを入れ替えます
    • 必要に応じて、テキストコンテンツ、バリアントプロパティ、またはレイアウトを更新します
    • 非推奨のセクションを削除します
    • 新しいセクションを追加します
  4. ステップ 4〜5 と同じエビデンスとスクリーンショットの頻度に従います。構造の検証には、返された ID に加えて、関連する件数、名前、境界情報を使用します。その後、更新完了後にビュー全体のスクリーンショットを 1 枚撮影します(対象を絞った視覚的な修正が必要な場合に限り、修正後のスクリーンショットを 1 枚追加します)。
// Example: Swap a button variant in an existing screen.
// Batch the node lookup and component-set import in parallel — they are
// independent and awaiting them sequentially serializes two IPC round-trips.
const [existingButton, buttonSet] = await Promise.all([
  figma.getNodeByIdAsync("EXISTING_BUTTON_INSTANCE_ID"),
  figma.importComponentSetByKeyAsync("BUTTON_SET_KEY"),
]);
if (existingButton && existingButton.type === "INSTANCE") {
  const newVariant = buttonSet.children.find(c =>
    c.name.includes("variant=primary") && c.name.includes("size=lg")
  ) || buttonSet.defaultVariant;
  existingButton.swapComponent(newVariant);
}
return { success: true, mutatedNodeIds: [existingButton.id] };

参考ドキュメント

API の詳しいパターンや注意点については、必要に応じて figma-use のリファレンスを読み込んでください。

  • component-patterns.md — キーによるインポート、バリアントの検索、setProperties、テキストのオーバーライド、インスタンスの操作
  • variable-patterns.md — 変数の作成とバインド、ライブラリ変数のインポート、スコープ、エイリアス設定、既存の変数の検出
  • text-style-patterns.md — テキストスタイルの作成と適用、ライブラリのテキストスタイルのインポート、タイポグラフィの段階
  • effect-style-patterns.md — エフェクトスタイル(シャドウ)の作成と適用、ライブラリのエフェクトスタイルのインポート
  • gotchas.md — レイアウトの落とし穴(HUG/FILL の相互作用、counterAxisAlignItems、サイズ設定の順序)、塗りや色の問題、ページコンテキストのリセット

エラーからの復旧

figma-use のエラーからの復旧 に従ってください。

  • safeToRetryWithoutCanvasRead が true の場合は、エラーを修正して再試行します。
  • false の場合は、キャンバスを読み取り、変更された内容を確認してから変更を加えます。

このスキルでは再試行しても安全な構築フェーズで作業するため、エラーの影響は現在のフェーズに自然に限定されます。以前の呼び出しで成功した内容はそのまま保持されます。

ベストプラクティス

  • 作成する前に必ず検索してください。 必要なコンポーネント、変数、スタイルは、デザインシステムにすでに用意されている可能性があります。手作業での作成や値のハードコードは、例外にとどめてください。
  • 未解決の不足項目を、1つの検索意図につき1つのクエリで検索してください。 同義語や部分一致の語句は、1つの文字列にまとめず、1回の queries 呼び出しで個別の { entity, query } エントリーとして試してください。「NavigationPill」は「pill」、「nav」、「tab」、「chip」のいずれかで見つかる可能性があるため、コンポーネントエントリーを4つ渡します。変数を検索する場合は、entity: "variable" を指定し、「color」、「spacing」、「radius」などをクエリに使ってください。未解決の作成上の不足項目に限って検索し、適切なアセットが見つかったら終了してください。
  • ハードコードした値より、デザインシステムのトークンを優先してください。 色、スペーシング、角丸には変数バインディングを使用してください。タイポグラフィにはテキストスタイルを、シャドウにはエフェクトスタイルを使用してください。これにより、画面をデザインシステムに連携した状態に保てます。
  • 手作業での構築より、コンポーネントのインスタンスを優先してください。 インスタンスはソースコンポーネントとの連携を維持し、デザインシステムの進化に合わせて自動的に更新されます。
  • 原則としてコンポーネント化してください。 繰り返し使う要素や再利用可能な要素は、いったんコンポーネントとして作成してからインスタンスを配置します。後から「コンポーネント化する」作業が必要になる、単発のフレームだけで構成されたフラットなツリーは作成しないでください。
  • 安全に再試行できる構築フェーズで作業してください。 スクリプトを安全に再試行できる場合は、関連するセクションを1回の use_figma 呼び出しにまとめてください。ページコンテキストの境界、復旧が難しい変更、または実際の失敗後に対象を絞って再試行する場合に限り、分割してください。
  • 各呼び出しからノード ID と検証の根拠を返してください。 作成した ID に加えて、関連する件数、名前、境界情報を返してください。これを標準的な構造検証とし、セクションの構成やエラーからの復旧にも ID を使います。
  • 全体構成のスクリーンショットを1枚使って、視覚的に検証してください。 構成後に全体表示のスクリーンショットを1枚撮影し、対象を絞った視覚的な修正を行った場合にのみ、もう1枚撮影してください。最後に合格したスクリーンショットを最終版とします。
  • 読み込みが成功したかだけでなく、フォントファミリーを確認してください。 スクリプトがエラーなく実行されても、誤ったフォントを読み込んでいる可能性があります。構築後に、描画されたテキストでStep 1で特定したプロダクトのフォントが使われていることを確認してください(Step 5を参照)。
  • 既存の規約に合わせてください。 ファイルに画面がすでに含まれている場合は、その命名、サイズ、レイアウトのパターンに合わせてください。

コメント