prototype-to-figma について
prototype-to-figmaは、コードでプロトタイプを作るデザイナー向けのスキルで、実行中の画面をレビュー可能なFigmaファイルに変換します。ヘッドレス描画で見た目を保ち、公開済みのデザインシステムのコンポーネント、変数、スタイルに対応付け、主要な操作を注釈します。
主な機能
- 01ヘッドレス描画によるプロトタイプの取得
- 02画面要素のFigma上での構成
- 03デザインシステムのコンポーネントと変数への対応付け
- 04状態変化とデザインシステムとの差異の注釈
- 05クライアント機能に応じたファイルや文書の生成
活用シーン
- 01ローカルで動くプロトタイプをFigmaデザインに変換
- 02チーム間で画面を非同期レビュー
- 03プロトタイプとデザインシステムの整合性確認
- 04画面フローの主要な操作に注釈
MCP 対応
このスキルはFigma MCPツールを使い、クライアントの機能に応じてデザインシステムを調査し、Figmaファイルを編集・整理します。プロトタイプの取得にはヘッドレスブラウザーと`generate_figma_design`を使い、書き込み機能がない場合はMarkdownのプロトタイプ仕様書を作成できます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ alima-max/ prototype-to-figma-skill --skill prototype-to-figmaインストール後、Claude Code で/prototype-to-figmaを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.mdLICENSEfigma-patterns.md詳細
プロトタイプ → Figma
このスキルでは、動作する Claude Code のプロトタイプから、部門横断のパートナーが非同期でレビューできる、構造化された Figma ファイルを作成します。出力には、同等に重要な目標が 2 つあります。
- 真の 1:1 のビジュアル一致 — レイアウト、色、間隔、タイポグラフィ、コンテンツ、アイコンを、レンダリングされたプロトタイプと完全に一致させます。手作業で再構築するのではなく、ヘッドレスレンダリング → シリアライズ(ルール 0)でベースを作成するためです。すべてターミナル内で実行され、画面に表示されるブラウザーやタブは使いません。
- デザインシステムに準拠した、レビュー可能な成果物 — キャプチャした要素を、Figma で公開されているデザインシステムのコンポーネントインスタンス/バインドされた変数/テキストスタイルに照合します(ルール 2)。また、すべての状態遷移をそのノードに注釈として記録します。
このスキルは、すべての Figma MCP クライアントで動作します。 出力形式は、クライアントがサポートする機能に合わせて調整されます。詳しくは、以下のクライアント互換性をご覧ください。
絶対に守るべき 5 つのルール
ルール 0:ヘッドレスでキャプチャする(レンダリング → シリアライズ)。表示ブラウザーは開かず、その後 DS と照合する
真の 1:1 を実現するには、コードをレンダリングする必要があります。ただし、レンダリングに表示ブラウザーは必要ありません。ヘッドレスブラウザー(Playwright)を使えば、ウィンドウもタブも開かず、実行全体をターミナル内で完結できます。これが対象ユーザーにとって重要な点です。コードのみで作業するデザイナーを IDE から引き離してはいけません。
選択肢は 3 つあります。正しいのは 1 つだけです。
- ❌ ソースを読み、手作業で構築する(レンダリングなし)。 LLM がブラウザーのレイアウト/レンダリングエンジンを要素ごとに再現する方法は、情報が失われ、不完全で、少しでも複雑なページでは不具合が起きます。これは 1:1 ではありません。小規模で静的な UI では忠実に見えるだけで、実際の UI では大きく崩れます(グリッドが折りたたまれる、要素が欠落する、SVG が途中までしか構築されないなど)。これを 1:1 だと偽ってはいけません。
- ❌ 表示状態でのキャプチャ —
open "<url>#figmacapture=…", アプリ内プレビュー、GUI の Figma 拡張機能。忠実度は正しいものの、ウィンドウ/タブが開き、デザイナーをターミナルから引き離します(また、拡張機能単体では DS インスタンスが得られません)。 - ✅ ヘッドレスキャプチャ。 ヘッドレスブラウザーで実行中のアプリをバックグラウンドでレンダリングし、DOM を 1:1 で Figma に直接シリアライズします(データはブラウザーから Figma に渡され、モデルを経由しないため、高速で低コストです)。その後、モデルがデザインシステムのレイヤーを追加します。ターミナル内で完結し、1:1 で、画面には何も表示されません。
「ヘッドレス」とは、--headless を指定して起動する別プロセスの Chrome のことです。ウィンドウもタブもなく、画面には何も表示されません。 デザイナーが開いているブラウザーには接続せず、Chrome を開いておく必要もありません。必要なのはインストールされていることだけです。画面に見えない状態で起動し、localhost のページをメモリ上でレンダリングして Figma にシリアライズした後、終了します。デザイナーがターミナルを離れることはなく、ブラウザー上でも何も起こりません。
キャプチャ(ヘッドレス、ターミナルのみ):
- 開発サーバーが実行中であることを確認します。必要ならバックグラウンドで起動します。コードベースからルート URL を特定します。
- ターミナルからヘッドレスブラウザーを起動し、
generate_figma_designのキャプチャスクリプトを実行します(ローカルの開発 URL に移動 → CSP を除去 →capture.jsを挿入 →window.figma.captureForDesign( { captureId, endpoint, selector:'body' }))。マシンにすでにインストールされている Chrome を優先してください(puppeteer-core、またはchannel:'chrome'を指定した Playwright、または生の CDP)。これならダウンロードも MCP も不要です。Chrome はインストールされていればよく、開いている必要はありません。Chrome/Chromium が見つからない場合に限り、一度だけバンドル版 Chromium をダウンロードする方法(npx playwright install chromium/フル版のpuppeteer)に切り替えます。新しい表示状態のインスタンスを起動してはいけません。 ユーザーの使用中ブラウザーに接続したり、open "<url>#figmacapture=…"やアプリ内プレビューを使ったりしてはいけません。いずれも画面にウィンドウ/タブが表示されます。 fileKeyとcaptureIdを使ってgenerate_figma_designをポーリングし、completedになるまで待ちます。トークンがバインドされた(bindVariables=true)完全なレイヤー構造の 1:1 ベース(フレーム/テキスト/ベクター)が得られます。
その後、DS と照合し、注釈を追加します(use_figma、ルール 2): 繰り返しキャプチャされた要素を DS コンポーネントのインスタンスに置き換え、Figma に実際に公開されている DS の変数/テキストスタイルをバインドし、Dev Mode の注釈とフロー矢印を追加します。これは低コストで対象を絞ったレイヤーであり、ページ全体ではなく、少数のコンポーネントだけを変更します。
必要条件/誠実さ: (a) ヘッドレスブラウザー(理想的にはマシンにインストール済みの Chrome をヘッドレスで操作します。ダウンロードも MCP も不要です。バンドル版 Chromium のダウンロードは代替手段です)、(b) 実行可能な開発サーバーが必要です。Playwright の MCP は必要ありませんが、ヘッドレス Chrome ランタイムは必要です。ブラウザーが本当にまったくない場合は、その旨を伝えて停止してください。表示タブに切り替えたり、ソースから手作業で構築して 1:1 と呼んだりしてはいけません(1:1 にはなりません)。デザインシステムがコンポーネント/変数として Figma に公開されていない場合、照合は存在するものに限られます。その DS の不足を明示し、外部ライブラリのコンポーネントで置き換えてはいけません。
ルール 1:Figma コンポーネントを新規作成しないでください
figma.createComponent() や figma.createComponentSet() を呼び出さないでください。デザインシステムに属さないコンポーネントが追加されてしまいます。
プロトタイプの要素に、デザインシステム内でどのような種類のコンポーネントもない場合(基準についてはルール 2 を参照)は、プリミティブ(figma.createFrame()、figma.createRectangle()、figma.createText())で構築し、不足していたものを説明する DS Drift 注釈を追加して、フェーズ 6 の概要に記載してください。
ルール 2:デザインシステムのコンポーネント/変数/スタイルがある場合は必ず使用してください — キャプチャを理由に例外にすることはできません
キャプチャ(ルール 0)によってパリティが保たれますが、このルールによってファイルがデザインシステムに準拠したものになります。キャプチャした各要素を調整する際に適用してください。キャプチャしたノードからは「どこにあるか」「どのくらいの大きさか」「どのように見えるか」がわかりますが、一致するものがあれば、構造にはデザインシステムを使用してください。キャプチャしたフレームを確認し、すべての要素をリンク済みライブラリと照合してください。
- コンポーネント — 必ずインスタンスを使い、模倣しないでください。 キャプチャした要素がデザインシステムのコンポーネントに一致する場合は、インスタンスに置き換え、キャプチャしたピクセルに一致するようプロパティ(塗り、テキスト、サイズ)をオーバーライドしてください。コンポーネントは存在するものの完全に一致するバリアントがない場合も、インスタンスを使ってオーバーライドし、DS Drift 注釈を追加してください。一致するコンポーネントがない場合に限り、その要素はプリミティブのままにし、DS Drift として記録します。特に繰り返し出てくる要素では、バッジが 60 個ならインスタンスも 60 個にしてください。フレームで代用するのはやめてください。実際のコンポーネントを模倣したプリミティブで埋め尽くされたフレームは、ピクセルが完璧でも失敗です。
- カラー変数 — 必ずバインドしてください。 値がデザインシステムのカラー変数と一致するすべての塗り/線は、その変数にバインドする必要があります。カラー変数がある場合に、16 進数値を直接指定したままにしないでください。
- 数値変数 — 必ずバインドしてください。 デザインシステムの数値/寸法変数と一致するすべての間隔、ギャップ、パディング、角丸、線幅、サイズ、フォントサイズは、その変数にバインドする必要があります。数値変数がある場合に、数値を直接指定したままにしないでください。
- テキストスタイル — 必ず適用してください。 本文/ラベル/見出しのテキストは、生の
fontSize/fontNameではなく、ライブラリのテキストスタイルにバインドします。
このルールを一言で表すと、一致するものがある場合は、リテラル値よりもコンポーネント/カラー変数/数値変数/テキストスタイルを優先してください。 生の 16 進数値、場当たり的な数値、模倣したプリミティブは、見た目が正しくてもパリティではなく、デザインシステムからの逸脱です。フェーズ 2 でコンポーネント、変数、スタイルを特定し、フェーズ 4 でキャプチャしたベースに置き換え、バインドします。
ルール 3:プロトタイプの要素を省略しないでください
表示されるすべての要素を、デザインシステムのインスタンスまたはプリミティブとして Figma の出力に含めてください。デザインシステムで一致するものが見つからないことを理由に要素を省略するのは、出力が不完全になる最も一般的な原因です。
ルール 4:注釈はノードに付け、フローに不可欠なものだけにする
注釈を付けることで、この出力はレビューに役立つものになります。 注釈のないフレームは、ただの静止画像です。しかし、タップできる要素すべてに注釈を付けると、ノイズが増えて実際のフローが埋もれてしまいます。
実際のレイヤーで node.annotations = [...] を使用して注釈を付けます。これにより、Figma の Dev Mode で正しい要素に注釈が表示されます。代わりに、浮動テキストボックスや個別の注釈用フレームを作成してはいけません。 ネイティブ API が失敗した場合は、figma-patterns.md のセクション 11 に記載された方法に切り替えてください。
カテゴリは次の 2 つだけです。
- インタラクション(青)— 状態遷移、主要な CTA、グループ化されたコントロール
- DS の差異(オレンジ)— DS コンポーネントまたはバリアントが存在しない、あるいは色や間隔が未バインド
注釈を付ける対象(インタラクション):
- フレームレベル — 1 フレームにつき注釈を 1 つ付けます。この状態が何か、主要なアクションによって何が起きるか、または次にどこへ進むかを記します
- 状態を進める CTA — 状態変化を引き起こすアクション(例:送信、確定、目標を作成、完了に移動)
- グループ化されたコントロール — 各項目ではなく、コンテナに 1 回だけ注釈を付けます(チップごとではなく金額選択行に、各ピルではなくストーリーピルの列に注釈を付けます)
- 分かりにくいタップ対象 — ボタンには見えないものの、新しい状態を開く要素(例:詳細シートを開く目標カード)
注釈を付けない対象:
- 閉じる/キャンセル/閉じるボタン
- ナビゲーションバーのボタンとタブ項目
- 二次的なユーティリティ操作(設定、プロトタイプのコントロール)
- グループ化された選択 UI 内の個々のチップやピル
- 背景幕やオーバーレイ
- 装飾要素
目安:1 フレームにつきインタラクション注釈を 2~4 個。 レビュー担当者が 30 秒以内にフレーム上のすべての注釈を読み、フロー全体を理解できるようにします。
フェーズ 2 で DS の差異に関する注記が付いたすべての要素には、DS の差異の注釈を付ける必要があります。
クライアントの互換性
| ティア | 検査 | 書き込み | Code Connect | 出力 |
|---|---|---|---|---|
| フル | ✅ | ✅ | ✅ | DS コンポーネント、ネイティブ注釈、Code Connect リンクを含む Figma ファイル |
| 書き込み | ✅ または ❌ | ✅ | ❌ | ネイティブ注釈を含む Figma ファイル |
| 検査のみ | ✅ | ❌ | ❌ | プロトタイプ仕様書(markdown) |
| なし | ❌ | ❌ | ❌ | コード分析のみから作成したプロトタイプ仕様書 |
| クライアント | 検査 | 書き込み | Code Connect |
|---|---|---|---|
| Claude Code / Desktop / Cursor / VS Code / Copilot CLI / Augment / Factory | ✅ | ✅ | ✅ |
| Android Studio / Gemini CLI / Kiro / Amazon Q / Openhands | ✅ | ❌ | ❌ |
| Replit | ❌ | ✅ | ❌ |
Figma MCP ツール
検査: get_design_context(主要)、get_metadata(構造の概要)、
search_design_system(コンポーネント + 変数)、get_variable_defs(正確なトークン値)、
get_screenshot(ユーザーが視覚的なプレビューを明示的に求めた場合のみ)。
キャプチャ(主要な方法 — ルール 0): ヘッドレスブラウザーを使用して
generate_figma_design を実行します。理想的には、マシンにインストール済みの Chromeをヘッドレスで実行し
(puppeteer-core / Playwright の channel:'chrome' / CDP を使用。ダウンロードも MCP も不要)、フォールバックとしてのみ
バンドル済み Chromium を使用して、ローカル開発サーバーを対象にします。表示ウィンドウやタブを開かずにレンダリングし、
1:1 で Figma にシリアライズします。open でタブを開くフローやアプリ内プレビュー(表示される)は絶対に使用せず、
ユーザーが開いているブラウザーに接続してはいけません。
書き込み: use_figma(キャプチャしたノードを DS インスタンスと変数に対応付け、注釈を付け、
フローを組み立てます)、whoami、create_new_file。
Code Connect: get_code_connect_map、get_code_connect_suggestions、
get_context_for_code_connect、send_code_connect_mappings。
ワークフロー
フェーズ 0:ファイルを特定し、機能を確認する
ファイル: ユーザーが指定した URL(figma.com/design/:fileKey/...)から fileKey を抽出します。URL が指定されていない場合は、whoami を呼び出してから create_new_file を呼び出します。URL がないことを理由に処理を中断してはいけません。
機能: get_metadata を試して、Inspect ツールが利用可能か確認します。ツール一覧で use_figma(書き込み)と get_code_connect_map(Code Connect)を確認します。利用できる機能を知らせます。
進行ルート: 書き込みツールが利用可能 → フェーズ 1〜6。書き込みツールが利用不可 → フェーズ 1〜3 の後、プロトタイプ仕様書へ進みます。
フェーズ 1a:プロトタイプを分析する
Figma に触れる前に、プロトタイプのソースファイルをすべて読みます。
コンポーネント一覧 — すべての UI コンポーネントについて、名前、使用されている props/バリアント、視覚的な構造(内部にあるもの)、インタラクティブかどうかを記録します。この一覧をフェーズ 4 の完全性チェックリストとして使います。
インタラクションフロー — 各フローについて、トリガー → 状態変化 → 変更前/変更後の状態 → 分岐経路(成功/エラー/エッジケース)を整理します。状態数も含めます。
レイアウト構造 — 固定要素とスクロール可能な要素、状態をまたいで保持される要素(ナビゲーション、ヘッダー)、ビューポートの寸法を記録します。スマートフォン/デバイスのフレームについて、プロトタイプが画面を .phone、.device-frame などのシェルで囲んでいる場合は、コンテンツの寸法だけを抽出し、Figma のフレームサイズに使用します。Figma でシェルをラッパーフレームとして再現してはいけません。
ソースの読み取り(一覧と構造の把握のため。ピクセル値の取得には使用しない) — CSS モジュール、Tailwind の設定、インラインスタイルを読み、各要素の構造、バリアント、インタラクティブな要素を把握します。ソース CSS の値をピクセル値の信頼できる基準として扱ってはいけません。レスポンシブ/計算済み CSS(グリッドの fr、clamp()、min/max、vw、変換、テーマスコープ)は、ピクセル値ではなく計算式に解決されます。ピクセル値の信頼できる基準は、実行中のアプリから取得する計算済みの測定値です(ルール 0/フェーズ 4)。ソースの読み取りは、測定対象とデザインシステムとの一致方法を把握するためだけに使用します。
フェーズ 1b:対象範囲を提示し、選択を受けて確認する
プロトタイプのフローが 2 つ以下の場合はスキップします。 すべてのフローを対象にして、フェーズ 2 に直接進みます。
フローが 3 つ以上ある場合は、状態数を含むカテゴリ別のフロー一覧を提示し、「どのフローを、どの程度詳しく(基本パス/すべての状態)扱いますか?」と尋ね、返答があるまで待ちます。フェーズ 2 を開始する前に、解釈内容を明示して確認します。
フェーズ 2:探索 — 作成前にデザインシステムとの対応付けを行う
まずリンク先のライブラリを徹底的に探索してから、すべての要素を対応付けます。この表ができるまで作成を開始してはいけません。デフォルトはプリミティブではなくインスタンスです(ルール 2)。
2a. 最初にライブラリを一度列挙する。 コンポーネントごとに検索する前にカタログを取得し、何があるかを把握します。
- コンポーネント:
search_design_system(fileKey, includeComponents=true)を幅広いクエリで実行し、さらにカテゴリ別の検索(「input」、「navigation」、「feedback」、「card」、「badge」、「avatar」、「table」)を行って、コードで使われている名前だけではなく、すべての項目を洗い出します。 - 変数:
search_design_system(..., includeVariables=true)とget_variable_defsを使って、色、間隔、角丸、ボーダー幅のトークンを取得します。キーを記録します。 - テキストスタイル:
search_design_system/get_variable_defsから、ライブラリのタイポグラフィスタイル(名前 → フォント、サイズ、ウェイト、行の高さ)を取得します。本文、ラベル、見出しは、ハードコードした hex 値と場当たり的なfontSizeではなく、これらに紐付ける必要があります。
2b. 一覧の各要素を照合する(「該当なし」と判断する前に、次の順で試します)。
search_design_system(fileKey, query="ComponentName", includeComponents=true)- 別名:Alert/Banner/Toast/Notification、Dropdown/Select/Menu、Tag/Chip/Badge、Nav/Sidebar/TabBar、TextField/Input、TextArea/Multiline、Avatar/UserPill など
- 視覚カテゴリ:「input」、「navigation」、「feedback」、「card」
- 親コンポーネントでの対応(例:「Card」で
Card.Headerを対応付ける) 見つかったコンポーネントの場合: Phase 4 でプロパティを設定する前に、get_context_for_code_connectを呼び出して正確なバリアントのプロパティ名を取得します。
コンポーネントは存在するが、正確なバリアントがない場合: プリミティブに置き換えてはいけません。 コンポーネントをインスタンス化し、異なるプロパティ(塗り、テキスト、サイズ)をインスタンスごとに上書きしてから、不足しているバリアントについて DS Drift アノテーションを追加します。完全に一致するコンポーネントがない要素のみ、プリミティブにします。
マッピングテーブルを作成します — すべての行に構築方法と Drift の注記が必要です:
| コードコンポーネント | DS マッチ | キー | 構築方法 | Drift の注記 |
|---|---|---|---|---|
<Button variant="primary"> | Button | abc123 | インポート+setProperties | ✅ 一致 |
<Badge tone="success"> | Badge | ghi789 | インポート+インスタンスごとに塗りを上書き | ⚠️ success バリアントなし — 塗りを上書き |
<CustomCard> | — | — | プリミティブ | ⚠️ DS マッチなし — 検索対象:Card、Panel、Tile |
<DataTable sortable> | Table | def456 | インポート+setProperties | ⚠️ Figma に sortable バリアントなし |
各要素について、Phase 4 でバインドするテキストスタイルとカラー/スペーシング/角丸/線幅の変数も記録します。⚠️ が付いた行には、Phase 4 で DS Drift アノテーションが必要です。「プリミティブ」と記載できるのは、2b で何も見つからなかった場合のみです。バリアントが不足していることを理由にしてはいけません。
2c. テーマ設定や実行時に再マッピングされる CSS 変数トークンを解決します — 生の var() を信頼してはいけません。
カラー、スペーシング、角丸が CSS カスタムプロパティ(var(--token-…))に由来し、実行時のテーマプロバイダーがその値を再マッピングする場合 — たとえば、ブランドやライト/ダークの配色に応じて --token-color-purple-100 の解決結果を変更する ThemeScope/data-theme/クラスベースのプロバイダー — 生の CSS 値はレンダリング結果ではありません。スタイルシートだけを読んでもわかるのは変数の名前かファイル先頭のデフォルト値であり、そのテーマコンテキストでユーザーに実際に見える値ではありません。これはパリティをひそかに損なう原因になります。最もよくある症状は、テーマが適用されたサーフェス(暗いフッター、反転したヒーローなど)の塗りが解決・設定されていないために、Figma で空白/白になることです。
レンダリングされた値を解決してからバインドします。次の 3 つの手順を順番に実行します。
- ソースではなく、実行中のアプリから正確な値を取得します。 ブラウザーで要素の計算済みスタイル(
getComputedStyle/検査ツール →background-color、color、gap、border-radiusなど)を読み取り、テーマによる再マッピングを具体的なrgb()/pxの値に解決します。実行中のアプリを利用できない場合は、:rootのデフォルト値ではなく、アクティブなテーマのモードを通じて変数の連鎖を手動で解決します。 - ネイティブ Figma 変数と照合します。 リンク済みライブラリで(
includeVariables=trueを指定したsearch_design_system、get_variable_defsを使用して)対応するモード/テーマで解決した値が一致する変数を検索します。見つかった場合は、ノードがテーマに対応した状態を保てるように変数をバインドします(Phase 4 §3.2)。リテラル値よりも常にこちらを優先します。 - 一致する Figma 変数がない場合は、解決したリテラル値をプリミティブ値として適用し、DS Drift アノテーションも追加します。 トークンはコードに存在しますが、対応するデザインシステム変数がありません。これはデザインチームが解消すべき実際の不足です。マッピングテーブルに ⚠️ の行として記録します。
テーマ付きトークンを未解決のままにしてはいけません(生の var() 名、:root のデフォルト値、塗りが未設定の状態)。テーマスコープがトークンとピクセルの間にある場合、「CSS から読み取りました」だけでは不十分です。
Phase 3: ページ構造を計画する
Page: "[Feature Name] — Prototype Flows"
Section: "Flow 1: [Flow Name]"
Frame: "1.1 — [State description]" ← left-to-right within a flow
Frame: "1.2 — [State description]"
Frame: "1.3a — Success"
Frame: "1.3b — Error" ← branches stacked vertically
Section: "Flow 2: [Flow Name]"
...
フレームサイズ:CSS で測定したビューポートに合わせます(例:モバイルは 390×844、デスクトップは 1440×900)。スクロール可能な状態では、フレームの高さをコンテンツ全体の高さに設定します。ビューポートの高さで切り取ってはいけません。ビューポートの高さに折り返し位置を示す線を追加します。フレーム間は約 200px、セクション間は約 400px の間隔を空けます。
Phase 4: ヘッドレスでピクセルをキャプチャし、DS と照合する
Step 1 — ヘッドレスでキャプチャする(ルール 0)。 開発サーバーが起動していることを確認し(必要ならバックグラウンドで起動します)、コードベースからルート URL を解決します。ルート/状態ごとに generate_figma_design (fileKey) を呼び出して captureId とキャプチャスクリプトを取得し、そのスクリプトの ヘッドレス Playwright 版をローカルの開発 URL に対して実行します。ナビゲートし、CSP を除去し、capture.js を挿入して、window.figma.captureForDesign({...}) を実行します。open は使用せず、表示中のタブもアプリ内プレビューも使いません。 generate_figma_design(fileKey, captureId) をポーリングし、completed になるまで待ちます。結果:状態ごとにレイヤー構造を完全に保持した 1:1 のベースができ、ブラウザーから Figma に直接送信されます。
Step 2 — DS に合わせて調整する(ルール 2)。 キャプチャした各フレームを確認し、Phase 2 で一致するものが見つかった要素はすべて DS コンポーネントインスタンスに置き換えます(キャプチャしたピクセルに合うようにオーバーライドします)。Figma で公開されている DS については、カラー変数、数値変数、テキストスタイルをバインドします。一致するものがない要素はキャプチャしたノードのままにし、DS Drift としてフラグを付けます。これは変更を最小限に抑える層で、ページ全体ではなく少数のコンポーネントだけを扱います。DS が Figma にない場合は、キャプチャした状態を維持してフラグを付けます。
Step 3 — 組み立てて注釈を付ける(Phase 5)。 状態フレームをフローに沿って配置し、矢印を追加して、Dev Mode の注釈を付けます。
ヘッドレスブラウザーがない場合、または開発サーバーがない場合: 作業を中止して、不足しているものをユーザーに伝えてください。表示中のタブへのフォールバックや、ソースから手作業で構築して 1:1 と表示することは絶対にしないでください。
配置: まず get_metadata で対象ページを確認します。この機能に対応するフレーム/セクションがある場合は、その隣に挿入します。ない場合は、名前付きセクション [Prototype] <feature name> を作成します。任意の遠い Y 座標にフレームを配置する場合は、Phase 6 の概要に座標とディープリンクを記載してください。
DS コンポーネントインスタンス — importComponentByKeyAsync と setProperties については、figma-patterns.md の Section 3 を参照してください。
プリミティブ — figma-patterns.md の Section 4 を参照してください。すべての寸法、角丸、カラーには、計測された算出済みの値(ルール 0)を使用してください。
固定サイズの正方形/円形コンテナー(アバター、番号バッジ、アイコンチップ): 両方の軸を固定サイズに設定し、オートレイアウトの内容に合わせる設定は使用しないでください。内容に合わせるコンテナーはグリフの幅まで縮むため、32×32 のアバターは高さが 32px でも幅が約 10px になってしまいます。resize(size, size) の後に primaryAxisSizingMode = 'FIXED' と counterAxisSizingMode = 'FIXED' を設定するか、オートレイアウトを使わずに子要素を手動で中央揃えにしてください。figma-patterns.md の Section 4.1 を参照してください。
DS 変数とテキストスタイルのバインド — Phase 2 で変数キーが見つかった塗り、角丸、間隔、境界線の幅はすべて、値をハードコードせずにバインドしてください。本文/ラベル/見出しのテキストは、fontSize/fontName の生の値を設定するのではなく、ライブラリのテキストスタイルにバインドしてください。変数 API は figma.variables.* の下にあります(figma グローバルではありません)。また、setBoundVariableForPaint は paint を受け取り、新しい paint を返すため、再代入が必要です。
// Color fill → variable. setBoundVariableForPaint returns a NEW paint — reassign node.fills.
const colorVar = await figma.variables.importVariableByKeyAsync(colorVarKey);
let fills = node.fills;
if (fills && fills !== figma.mixed && fills.length && fills[0].type === 'SOLID') {
fills = [...fills]; // copy — assigning into the live array is a no-op
fills[0] = figma.variables.setBoundVariableForPaint(fills[0], 'color', colorVar);
node.fills = fills; // reassign — required
}
// Scalar fields (radius / border-width / spacing) → node.setBoundVariable
const radiusVar = await figma.variables.importVariableByKeyAsync(radiusVarKey);
node.setBoundVariable('cornerRadius', radiusVar); // fallback: pass radiusVar.id
const borderVar = await figma.variables.importVariableByKeyAsync(borderWidthVarKey);
node.setBoundVariable('strokeWeight', borderVar); // not a raw strokeWeight
// Typography → library text style (styles use figma.importStyleByKeyAsync, NOT the variables API)
const textStyle = await figma.importStyleByKeyAsync(textStyleKey);
await textNode.setTextStyleIdAsync(textStyle.id); // font/size/weight/lineHeight; fill stays separate
⚠
figma.importVariableByKeyAsync(...)(.variablesなし)およびnode.setBoundVariableForPaint('fills', 0, ...)は、Figma MCP ランタイムでエラーになります。上記の形式を使用してください。インポートはキャッシュしてください(キーごとに 1 回)。その後、バインドします。
ページとサーフェスの背景も、サーフェス/ウォッシュカラーの変数にバインドしてください。ページ背景の hex 値を直接指定してはいけません。Phase 2 でその役割に対応する DS 変数またはテキストスタイルが見つからなかった場合に限り、CSS の生の値をフォールバックとして使用し、ドリフトとして記録してください。
注釈 — 後からではなく、構築中にノードに付ける
最初の use_figma 呼び出しの冒頭で、注釈カテゴリを 2 つ設定します。
let interactionCat = null, dsDriftCat = null;
try {
const existing = await figma.annotations.getAnnotationCategoriesAsync();
interactionCat = existing.find(c => c.label === 'Interaction')
?? await figma.annotations.addAnnotationCategoryAsync({ label: 'Interaction', color: 'blue' });
dsDriftCat = existing.find(c => c.label === 'DS Drift')
?? await figma.annotations.addAnnotationCategoryAsync({ label: 'DS Drift', color: 'orange' });
} catch(e) { /* native API unavailable — use layer name fallback below */ }
各ノードを構築したら、すぐに注釈を付けてください。注釈を別の処理に後回しにしないでください。ノード参照をスコープ内に保持することが、正しいレイヤーに注釈を付ける唯一の確実な方法です。
// Interaction annotation — on the node itself, right after creating it
const ctaButton = figma.createFrame(); // ...build it...
ctaButton.name = 'CTA: Submit';
ctaButton.annotations = [{
label: 'Tap → submits form; on 200 navigates to success screen; on 4xx shows inline error',
...(interactionCat ? { categoryId: interactionCat.id } : {})
}];
// DS Drift annotation — on any primitive or mismatched DS component
const customCard = figma.createFrame(); // ...build it...
customCard.name = 'Card: Goal (primitive)';
customCard.annotations = [{
label: 'DS Drift: no Card/Goal component found in library (searched: Card, Panel, Tile). DS gap for design team.',
...(dsDriftCat ? { categoryId: dsDriftCat.id } : {})
}];
// Fallback if native API failed: encode in layer name
if (!interactionCat) ctaButton.name += ' [Interaction: tap → submit form]';
if (!dsDriftCat) customCard.name += ' [DS Drift: no Card/Goal in DS]';
フレームごとのアノテーションチェックリスト:
- フレーム自体にアノテーションが1つある:現在の状態と、主要なアクションの内容/遷移先
- 状態を進める各 CTA にアノテーションがある(トリガー → 結果)
- グループ化されたコントロール(ピッカー、ピル型の選択肢、オプションリスト)には、項目ごとではなくグループ全体に1つのアノテーションがある
- すべてのプリミティブまたは DS と一致しないコンポーネントに、DS Drift アノテーションがある
完全性の確認:次のフレームに進む前に、Phase 2 のマッピング表のうち、このフレームに該当するすべての行がレイヤーツリーに含まれていることを確認します。
Phase 5:フロー概要フレームを追加する
ページの先頭にフレームを1つ追加します。
- 機能名、フローの一覧、フレーム数
- アノテーションの凡例:青 = Interaction、オレンジ = DS Drift(Dev Mode でフィルター可能)
- DS の不足項目:デザインチーム向けに、すべてのプリミティブと一致しないコンポーネントを一覧表示します
- 未解決の質問:プロトタイプの動作が曖昧な場合は明記します
- フローを省略した場合は対象範囲について注記します(フローを追加するためのスキルの再実行を提案します)
Phase 6:確認して提示する
6a. 完全性の確認 — 出力に対して get_metadata を実行し、次の点を確認します。
- Phase 2 のマッピング表のすべての行に、正しいフレーム内の名前付きレイヤーがある
- DS に一致する要素はすべてプリミティブではなくインスタンスである — バッジ、ナビゲーション、入力欄、テキストエリア、アバターなど、繰り返し使われる要素も含みます。プリミティブを使えるのは、Phase 2 で一致するものがないと確認された行のみです。そのようなプリミティブには、それぞれ DS Drift アノテーションが付いています。
- フレームの寸法が CSS で測定したビューポートと一致する
- ローカルアセットに新しいマスターコンポーネントが作成されていない
- DS 変数のバインディングがカラーの塗り、角丸、ボーダー幅に設定されている。テキストはライブラリのテキストスタイルにバインドされ、ページ/サーフェスの背景はサーフェス変数にバインドされている
- 正方形/円形のコンテナが正方形に表示される — 幅と高さが同じである(hug による縮小がない)
- インライン SVG が保持されている — アプリに
<svg>(ロゴ、アイコン、装飾用の図形など)がある場合、出力にそれらの VECTOR ノードが含まれている必要があります。フレームのベクター数が0の場合、インライン SVG がすべて欠落しています(ロゴが誤ったもの/プレースホルダーになっている、フッターが空になっている、カードの装飾が失われているなど)。createNodeFromSvgを使って SVG を追加してください。
提示する前に、不足しているものがあれば use_figma を呼び出して修正します。
6b. Code Connect (任意) — get_code_connect_suggestions → 内容を確認 → send_code_connect_mappings。
6c. ユーザーに提示する内容:
- Figma ファイルの URL(必須)と、キャンバスの原点以外にある場合はセクションノードへのディープリンク
- フロー数、フレーム数
- 使用した DS インスタンスとプリミティブ
- デザインチーム向けの DS の不足項目(プリミティブ)の全一覧
- CSS の測定値からの差異とその理由
- 機能上の制限により省略した手順
プロトタイプ仕様書 — 閲覧のみの出力
書き込みツールが利用できない場合は、figma-patterns.md のセクション 12 にあるテンプレートを使用して、構造化された Markdown ドキュメントを作成します。
重要な原則
まずインスタンス、プリミティブは最後です。 このスキルの価値は、手作業で作り直すことではありません。DS にコンポーネントがあるなら、完全に一致するバリアントがなくても、オーバーライドを適用して使用してください。タイポグラフィ、色、スペーシング、角丸、ボーダー幅は、DS のスタイルと変数に紐付けてください。実際のコンポーネントを模倣するプリミティブで作られた、ピクセル単位で正確なフレームであっても、実行としては失敗です。
レンダリングしてからシリアライズします — ヘッドレスで。 真の 1:1 は、LLM がソースからレイアウトを再導出する方法(実際のページでは情報が失われます)でも、画面に表示されるキャプチャ(デザイナーをターミナルから引き離します)でもなく、ヘッドレスブラウザーでコードをレンダリングし、その結果を Figma にシリアライズすることで実現します。ヘッドレスなら、同じ忠実度を保ちながら、画面には表示されず、ターミナルネイティブです。モデルの役割は、ピクセルを手作業で再現することではなく、その上に DS と注釈レイヤーを構築することです。
キャンバスではなく、ノードに注釈を付けます。 Dev Mode に表示されるのは node.annotations = [...] です。浮動テキストボックスや独立した注釈フレームはノイズであり、注釈ではありません。
すべてに名前を付けます。 「Frame 47」では役に立ちません。「2.3a — トーストによる保存成功」なら、レビュー担当者はどこを見ているか正確に把握できます。
タップ対象ではなく、フローに注釈を付けます。 目標は、レビュー担当者がフレーム上のすべての注釈を 30 秒以内に読み、フロー全体を理解できるようにすることです。仕組みではなく状態遷移に注釈を付けてください。金額ピッカーの行に 1 つ注釈を付けるほうが、その中の各チップに同じ注釈を 4 つ付けるより効果的です。
DS の不足を明示してください。 概要にはすべてのプリミティブを記載し、デザインチームが DS に不足しているコンポーネントを把握できるようにします。これにより、一致しない要素が見過ごされる失敗ではなく、対処可能なシグナルになります。
リファレンス:Figma Plugin API のパターン
Plugin API のパターン(フレームの作成、コンポーネントのインポート、プリミティブヘルパー、addNoDsMatchBadge、オートレイアウト、テキストノード、注釈の設定、Prototype Spec Document のテンプレート)については、figma-patterns.md を参照してください。最初の use_figma 呼び出しの前にお読みください。
(Write-tier クライアントのみ。)