figma-generate-design について
公開済みのデザインシステムのコンポーネント、変数、スタイルを組み合わせて、Figmaの画面全体を作成・更新するスキルです。Figmaからコードを生成するのではなく、ソースコードや説明をもとに画面を作る用途です。
主な機能
- 01再利用可能なコンポーネント、変数、スタイルを検索
- 02インポートしたデザインシステムの部品で画面を構成
- 03ページ枠と各セクションを段階的に作成
- 04コンポーネントのテキストプロパティを上書き
- 05作業中に構造と表示を検証
活用シーン
- 01アプリのソースコードからFigma画面を作成
- 02既存のデザインシステムを使って画面を更新
- 03ライブラリの部品で複数セクションのレイアウトを構成
MCP 対応
Figma MCP サーバーが必要で、`use_figma` を使って画面を構築します。`search_design_system` で設計リソースを探し、`get_metadata` と `get_screenshot` で結果を検証する方法も記載されています。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ openai/ skills --skill figma-generate-designインストール後、Claude Code で/figma-generate-designを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSE.TXTmaintainers.ymlagents/openai.yamlassets/figma-small.svgicon.svg詳細
デザインシステムから画面を構築/更新する
このスキルを使って、ハードコードされた値でプリミティブを描画するのではなく、公開済みのデザインシステム(コンポーネント、変数、スタイル)を再利用して、Figma でページ全体の画面を作成または更新します。重要なポイントは、Figma ファイルにはおそらく、コードベースの UI コンポーネントやトークンに対応するコンポーネント、カラー/間隔の変数、テキスト/エフェクトスタイルを備えた公開済みデザインシステムがあるということです。色付きの四角形を描くのではなく、それらを見つけて使ってください。
必須:use_figma を呼び出す前に、必ず figma-use も読み込んでください。このスキルには、作成するすべてのスクリプトに適用される重要なルール(色の範囲、フォントの読み込みなど)が含まれています。
このスキルの一部として use_figma を呼び出すときは、必ず skillNames: "figma-generate-design" を渡してください。 これはログ記録用のパラメーターであり、実行には影響しません。
スキルの適用範囲
- 成果物がデザインシステムのコンポーネントインスタンスで構成される Figma 画面(新規または更新)の場合は、このスキルを使います。
- ユーザーが Figma デザインからコードを生成したい場合は、figma-implement-design に切り替えます。
- ユーザーが 再利用可能な新しいコンポーネントやバリアントを作成したい場合は、figma-use を直接使います。
- ユーザーが Code Connect マッピングを記述したい場合は、figma-code-connect-components に切り替えます。
前提条件
- Figma MCP サーバーに接続されていること
- 対象の Figma ファイルに、コンポーネントを含む公開済みデザインシステムがあること(またはチームライブラリにアクセスできること)
- ユーザーから次のいずれかが提供されていること:
- 作業対象となる Figma ファイルの URL/ファイルキー
- または、対象ファイルに関する情報(エージェントがページを見つけられます)
- 構築/更新する画面のソースコードまたは説明
generate_figma_design を使った並行ワークフロー(Web アプリのみ)
ブラウザーでレンダリングできる Web アプリの画面を構築する場合は、両方の方法を並行して実行すると、最良の結果が得られます。
- 並行して実行:
- このスキルのワークフロー(use_figma + デザインシステムのコンポーネント)を使って画面の構築を開始します
generate_figma_designを実行し、稼働中の Web アプリのピクセル単位で正確なスクリーンショットを取得します
- 両方が完了したら:
generate_figma_designで取得したピクセル単位で正確なレイアウトに合うよう、use_figma の出力を更新します。キャプチャからは目指すべき正確な間隔、サイズ、視覚的な表現がわかり、use_figma の出力にはデザインシステムにリンクされ、適切に更新できるコンポーネントインスタンスがあります。 - 見た目に問題がないことを確認したら:
generate_figma_designの出力を削除します。これは視覚的な参照としてのみ使用したものです。
この方法を組み合わせることで、それぞれの利点を活かせます。generate_figma_design はピクセル単位で正確なレイアウトを実現し、use_figma はデザインシステムにリンクされた適切なコンポーネントインスタンスを作成します。
このワークフローは、generate_figma_design で稼働中のページをキャプチャできる Web アプリにのみ適用されます。 Web アプリ以外(iOS、Android など)や既存画面の更新では、以下の標準ワークフローを使ってください。
必須ワークフロー
次の手順に順番どおり従ってください。省略しないでください。
ステップ 1:画面を理解する
Figma に触れる前に、構築するものを把握してください。
- コードから構築する場合は、関連するソースファイルを読み、ページの構造、セクション、使用されているコンポーネントを把握します。
- 画面の主要なセクションを特定します(例:ヘッダー、ヒーロー、コンテンツパネル、料金プランのグリッド、FAQ アコーディオン、フッター)。
- 各セクションで使用する UI コンポーネント(ボタン、入力欄、カード、ナビゲーションピル、アコーディオンなど)を一覧にします。
ステップ 2:デザインシステムを調べる — コンポーネント、変数、スタイル
デザインシステムから必要なものは 3 つです。コンポーネント(ボタン、カードなど)、変数(色、間隔、角丸)、スタイル(テキストスタイル、影などのエフェクトスタイル)です。デザインシステムのトークンがある場合は、色の 16 進数やピクセル値をハードコードしないでください。
2a: コンポーネントを調べる
推奨:まず既存の画面を調べてください。 対象ファイルに同じデザインシステムを使用する画面がすでにある場合は、search_design_system を使わず、既存のインスタンスを直接調べてください。既存のフレームをたどる use_figma の呼び出しを1回行うだけで、正確で信頼できるコンポーネントマップを取得できます。
const frame = figma.currentPage.findOne(n => n.name === "Existing Screen");
const uniqueSets = new Map();
frame.findAll(n => n.type === "INSTANCE").forEach(inst => {
const mc = inst.mainComponent;
const cs = mc?.parent?.type === "COMPONENT_SET" ? mc.parent : null;
const key = cs ? cs.key : mc?.key;
const name = cs ? cs.name : mc?.name;
if (key && !uniqueSets.has(key)) {
uniqueSets.set(key, { name, key, isSet: !!cs, sampleVariant: mc.name });
}
});
return [...uniqueSets.values()];
参照できる既存の画面がファイルにない場合に限り、search_design_system を使ってください。使うときは、幅広く検索してください。複数の用語や類義語(例:「button」「input」「nav」「card」「accordion」「header」「footer」「tag」「avatar」「toggle」「icon」など)を試してください。コンポーネントに絞り込むには、includeComponents: true を指定します。
コンポーネントのプロパティをマップに含めてください。テキストを上書きする際に必要となる、各コンポーネントが公開する 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: 変数(色、間隔、角丸)を調べる
まず既存の画面を調べてください(コンポーネントの場合と同じです)。または、includeVariables: true を指定して search_design_system を使います。
警告:変数を調べる方法は2種類あります。混同しないでください。
figma.variables.getLocalVariableCollectionsAsync()を使用するuse_figmaは、現在のファイルで定義されているローカル変数のみを返します。結果が空でも、変数が存在しないという意味ではありません。リモートまたは公開済みライブラリの変数は、この API では見えません。includeVariables: trueを指定したsearch_design_systemは、リモートや公開済みのものを含め、リンクされたすべてのライブラリを検索します。デザインシステムの変数を調べるには、こちらが適切なツールです。
getLocalVariableCollectionsAsync()の結果が空であることだけを根拠に、「変数は存在しない」と判断しないでください。 独自の変数を作成すると決める前に、必ずincludeVariables: trueを指定したsearch_design_systemも実行し、ライブラリの変数を確認してください。
検索方法: search_design_system はカテゴリではなく、変数名(例:「Gray/gray-9」「core/gray/100」「space/400」)に一致します。複合クエリを1つ実行するのではなく、短くシンプルなクエリを複数並行して実行してください。
- プリミティブカラー:「gray」「red」「blue」「green」「white」「brand」
- セマンティックカラー:「background」「foreground」「border」「surface」「text」
- 間隔/サイズ:「space」「radius」「gap」「padding」
最初の検索で結果が空の場合は、より短い語句や異なる命名規則を試してください。ライブラリによって命名方法は大きく異なります(「grey」と「gray」、「spacing」と「space」、「color/bg」と「background」など)。
最も信頼できる結果を得るには、既存の画面にバインドされている変数を調べてください。
const frame = figma.currentPage.findOne(n => n.name === "Existing Screen");
const varMap = new Map();
frame.findAll(() => true).forEach(node => {
const bv = node.boundVariables;
if (!bv) return;
for (const [prop, binding] of Object.entries(bv)) {
const bindings = Array.isArray(binding) ? binding : [binding];
for (const b of bindings) {
if (b?.id && !varMap.has(b.id)) {
const v = await figma.variables.getVariableByIdAsync(b.id);
if (v) varMap.set(b.id, { name: v.name, id: v.id, key: v.key, type: v.resolvedType, remote: v.remote });
}
}
}
});
return [...varMap.values()];
ライブラリ変数(remote = true)は、キーを指定して figma.variables.importVariableByKeyAsync(key) でインポートしてください。ローカル変数は、figma.variables.getVariableByIdAsync(id) を直接使用してください。
バインドの方法については、variable-patterns.md を参照してください。
2c: スタイル(テキストスタイル、エフェクトスタイル)を調べる
includeStyles: true を指定した search_design_system と、「heading」「body」「shadow」「elevation」などの用語でスタイルを検索してください。または、既存の画面で使用されているスタイルを調べてください。
const frame = figma.currentPage.findOne(n => n.name === "Existing Screen");
const styles = { text: new Map(), effect: new Map() };
frame.findAll(() => true).forEach(node => {
if ('textStyleId' in node && node.textStyleId) {
const s = figma.getStyleById(node.textStyleId);
if (s) styles.text.set(s.id, { name: s.name, id: s.id, key: s.key });
}
if ('effectStyleId' in node && node.effectStyleId) {
const s = figma.getStyleById(node.effectStyleId);
if (s) styles.effect.set(s.id, { name: s.name, id: s.id, key: s.key });
}
});
return {
textStyles: [...styles.text.values()],
effectStyles: [...styles.effect.values()]
};
ライブラリのスタイルは figma.importStyleByKeyAsync(key) でインポートし、node.textStyleId = style.id または node.effectStyleId = style.id で適用してください。
詳しくは、text-style-patterns.md と effect-style-patterns.md を参照してください。
ステップ3:最初にページのラッパーフレームを作成する
セクションをページ直下の子として作成し、後から再親化しないでください。use_figma の呼び出しをまたいで appendChild() を使用してノードを移動すると、処理はエラーなしで失敗し、フレームが孤立します。代わりに、まずラッパーを作成し、各セクションをその内側に直接作成してください。
ページのラッパーは、専用の use_figma 呼び出しで作成してください。既存のコンテンツから離れた位置に配置し、その 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.createFrame();
wrapper.name = "Homepage";
wrapper.layoutMode = "VERTICAL";
wrapper.primaryAxisAlignItems = "CENTER";
wrapper.counterAxisAlignItems = "CENTER";
wrapper.resize(1440, 100);
wrapper.layoutSizingHorizontal = "FIXED";
wrapper.layoutSizingVertical = "HUG";
wrapper.x = maxX + 200;
wrapper.y = 0;
return { success: true, wrapperId: wrapper.id };
ステップ 4:ラッパー内に各セクションを作成する
これが最も重要なステップです。 use_figma を呼び出すたびに、1つのセクションだけを作成します。各スクリプトの冒頭で ID を使ってラッパーを取得し、新しいコンテンツをその中に直接追加します。
const createdNodeIds = [];
const wrapper = await figma.getNodeByIdAsync("WRAPPER_ID_FROM_STEP_3");
// Import design system components by key
const buttonSet = await figma.importComponentSetByKeyAsync("BUTTON_SET_KEY");
const primaryButton = buttonSet.children.find(c =>
c.type === "COMPONENT" && c.name.includes("variant=primary")
) || buttonSet.defaultVariant;
// Import design system variables for colors and spacing
const bgColorVar = await figma.variables.importVariableByKeyAsync("BG_COLOR_VAR_KEY");
const spacingVar = await figma.variables.importVariableByKeyAsync("SPACING_VAR_KEY");
// Build section frame with variable bindings (not hardcoded values)
const section = figma.createFrame();
section.name = "Header";
section.layoutMode = "HORIZONTAL";
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];
// Import and apply text/effect styles
const shadowStyle = await figma.importStyleByKeyAsync("SHADOW_STYLE_KEY");
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 };
各セクションの作成後、次に進む前に get_screenshot で検証します。テキストが切り取られていないか(行の高さによってコンテンツが欠けていないか)、要素が重なっていないかをよく確認してください。これらは最もよくある問題で、ざっと見ただけでは見落としやすいものです。
setProperties() でインスタンスのテキストを上書きする
コンポーネントのインスタンスには、プレースホルダーテキスト(「Title」「Heading」「Button」)が設定されています。ステップ 2 で確認したコンポーネントプロパティキーを使い、setProperties() でこれらを上書きしてください。node.characters を直接操作するよりも信頼性が高い方法です。詳しい方法は component-patterns.md を参照してください。
独自の TEXT プロパティを公開しているネストされたインスタンスでは、そのネストされたインスタンスに対して setProperties() を呼び出します。
const nestedHeading = cardInstance.findOne(n => n.type === "INSTANCE" && 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" であるかを調べます。誤った variant(たとえば Primary ではなく Neutral)を選ぶと、見た目が不正確になりますが、見落としやすいので注意してください。
手動で作成するものとデザインシステムからインポートするもの
| 手動で作成する | デザインシステムからインポートする |
|---|---|
| ページラッパーフレーム | コンポーネント:ボタン、カード、入力欄、ナビゲーションなど |
| セクションコンテナフレーム | 変数:色(塗り、線)、間隔(パディング、ギャップ)、角丸 |
| レイアウトグリッド(行、列) | テキストスタイル:見出し、本文、キャプションなど |
| エフェクトスタイル:シャドウ、ぼかしなど |
デザインシステムの変数がある場合、16進数カラーやピクセル単位の間隔をハードコードしないでください。間隔や角丸には setBoundVariable を、色には setBoundVariableForPaint を使用します。テキストスタイルには node.textStyleId を、エフェクトスタイルには node.effectStyleId を適用してください。
ステップ 5:画面全体を検証する
すべてのセクションを配置したら、ページ全体のフレームに対して get_screenshot を呼び出し、元の画面と比較します。問題があれば、対象を絞った use_figma 呼び出しで修正してください。画面全体を作り直す必要はありません。
ページ全体だけでなく、個々のセクションもスクリーンショットで確認してください。 解像度を下げたページ全体のスクリーンショットでは、テキストの切り詰め、色の誤り、上書きされていないプレースホルダーテキストが見えにくくなります。各セクションのノード ID を指定してスクリーンショットを撮り、次の問題を見つけてください。
- 切り取られたテキスト — 行の高さやフレームサイズによって、ディセンダー、アセンダー、または行全体が欠けている
- コンテンツの重なり — サイズ設定の誤りやオートレイアウトの不足により、要素が互いに重なっている
- プレースホルダーテキストが残っている(「Title」「Heading」「Button」)
- レイアウトサイズの不具合によるコンテンツの切り詰め
- コンポーネントの variant の誤り(たとえば Neutral と Primary のボタン)
ステップ 6:既存の画面を更新する
新規作成ではなく既存の画面を更新する場合は、次の手順に従います。
get_metadataを使って既存画面の構造を確認します。- 更新が必要なセクションと、そのまま残せるセクションを特定します。
- 変更が必要な各セクションについて、次の作業を行います。
- ID または名前で既存のノードを見つけます
- デザインシステムのコンポーネントが変更されている場合は、コンポーネントのインスタンスを置き換えます
- 必要に応じて、テキスト内容、variant プロパティ、またはレイアウトを更新します
- 非推奨のセクションを削除します
- 新しいセクションを追加します
- 各変更の後、
get_screenshotで検証します。
// Example: Swap a button variant in an existing screen
const existingButton = await figma.getNodeByIdAsync("EXISTING_BUTTON_INSTANCE_ID");
if (existingButton && existingButton.type === "INSTANCE") {
// Import the updated component
const buttonSet = await figma.importComponentSetByKeyAsync("BUTTON_SET_KEY");
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 のエラー復旧プロセスに従ってください。
- エラーが発生したら停止し、すぐに再試行しないでください。
- エラーメッセージを注意深く読み、何が問題だったのかを把握してください。
- エラーが不明瞭な場合は、
get_metadataまたはget_screenshotを呼び出して、現在のファイルの状態を確認してください。 - エラーメッセージに基づいてスクリプトを修正してください。
- 修正したスクリプトを再試行してください。失敗したスクリプトはアトミックに実行されるため(エラーが発生した場合は何も作成されません)、安全に再試行できます。
このスキルは段階的に(1 回の呼び出しにつき 1 セクション)動作するため、エラーの範囲は自然に単一のセクションに限定されます。成功した呼び出しで作成された前のセクションはそのまま残ります。
ベストプラクティス
- 作成する前に必ず検索してください。 必要なコンポーネント、変数、スタイルはデザインシステムにある可能性が高いです。手動での作成や値のハードコーディングは、例外としてください。
- 幅広く検索してください。 同義語や部分一致の語句を試してください。「NavigationPill」は「pill」、「nav」、「tab」、「chip」などで見つかる場合があります。変数については、「color」、「spacing」、「radius」などで検索してください。
- ハードコードした値よりデザインシステムのトークンを優先してください。 色、スペーシング、角丸には変数のバインドを使用してください。タイポグラフィにはテキストスタイルを使用してください。シャドウにはエフェクトスタイルを使用してください。これにより、画面をデザインシステムに連携した状態に保てます。
- 手動での作成よりコンポーネントインスタンスを優先してください。 インスタンスはソースコンポーネントとの連携を維持し、デザインシステムの進化に合わせて自動的に更新されます。
- セクションごとに作業してください。 1 回の
use_figma呼び出しで、複数の主要セクションを作成しないでください。 - すべての呼び出しでノード ID を返してください。 セクションを組み合わせるときや、エラーから復旧するときに必要になります。
- 各セクションの後に視覚的に検証してください。
get_screenshotを使用して、問題を早期に発見してください。 - 既存の規約に合わせてください。 ファイルにすでに画面がある場合は、名前、サイズ、レイアウトのパターンを合わせてください。