🐡

FigmaのデザインをClaude Codeで自動実装してみた

に公開

今回は、Figma のデザインを Claude Code で自動実装してみた内容をまとめていきます。

Webページ実装をする際の、カラー定義やコンポーネント実装、その後のページ実装を自動で実装できれば、自分も周りの人の工数も減りそう…!と思ったのがきっかけで色々と試してみました。

実際に試してみると、ガイド用のマークダウンファイルとプロンプトを上手く工夫すれば、どんなデザインでも汎用的に使えそうでした。

手順や精度の上げ方、実案件への導入イメージなど、整理したので、よかったご参考にください!

試したこと

試験用に、Figmaで上記みたいなコンポーネントとページのデザインを用意して、これらのデザインをClaudeで下記3フェーズに分けて自動実装してみました。

  1. Figmaライブラリカラーを取得 & プロジェクト内で汎用的に使えるようにソースファイル化
  2. FigmaのコンポーネントをReactコンポーネントに自動変換
  3. 実装したReactコンポーネントを使いつつページ自動実装

例えばコンポーネント実装であれば、下記のプロンプトを出せば自動実装できるようになっています。

Figmaで選択中のコンポーネント一覧を実装してください。

## 手順

1. `/CLAUDE.md` を読んでプロジェクトの基本情報を把握
2. `/docs/guide/figma-common-guide.md` を読んで共通要件を把握
3. `/docs/guide/figma-component-guide.md` を読んでコンポーネント固有要件を把握
4. `/docs/responsive-style-guide.md` を読んでレスポンシブの書き方を把握

上記のガイド系のファイル( *-guide.md )が重要で、ここにどんなルールで実装させるかを整理しています。これは後ほど解説。

自動実装したコンポーネント一覧化させたページ

実際に出力してもらったReactコンポーネントソース

初回のプロンプト一発で、完璧に実装...っていう訳じゃないですが、僕が試している中では1,2回調整願い出すくらいでほぼ仕上げられる温度感で実装できました。

デザインデータをもらって、さて実装しようかという場面で、カラー情報やコンポーネントが自動で実装できてしまえば、なかなか工数削減できるので便利!

その後のページ実装については、自動実装後にプロンプトで微調整したり、デザインと合致しているか目でチェックするのはもちろん必要ですが、序盤の骨組み作るくらいは任せてしまえます。

実装手順

前提として、Claude CodeからFigmaデザインファイルを読ませるためには、FigmaでMCPサーバーを立ち上げて、Claude Code側でサーバーと繋がせる必要があります。

この辺りの前提知識や公式の手順は、下記をご参考にください。

この記事では、MCPサーバーを起動して、FigmaのコンポーネントをReactコンポーネント化するところまで試していきます。

1. デスクトップアプリのFigmaでページを開く

2. Figma MCPサーバーを有効化

こちらを参考にMCPサーバーを有効にする
デスクトップアプリで操作: **[基本設定]**で、**[Dev Mode MCPサーバーを有効にする]**を選択

3. MCPクライアントセットアップ

```bash
claude mcp add --transport sse figma-dev-mode-mcp-server http://127.0.0.1:3845/sse
```

4. ガイド用のファイルを準備

下記は「Vite x React x Vanilla Extract(CSS in JS)」の環境で用意した、共通ガイドとコンポーネント実装ガイドになります。

共通ガイドの方は、下記のようなどんな実装フェーズでも共通のガイドを整理。

  • どんな手順でMCPサーバーから情報取得するか
  • HTML、TypeScript実装、CSS書き方、とうの実装要件
  • SVGや画像の実装方法

コンポーネントガイドの方は、FigmaのコンポーネントをReactコンポーネントに変換する際に、参照してもらう用のガイド。

  • どんな命名規則でコンポーネントファイルを生成するか
  • 既にコンポーネントが実装されているかどうかのチェック
  • 実際のコンポーネント例

このような内容をまとめています。

実案件に導入際のイメージとしては、こういったプロジェクトを跨いでも汎用的に使えるようなガイドを事前に準備しておいて使い回す形。

もし、別の環境(Next.js、Sass、他のCSS in JS)であれば、それに対応するようガイドを微調整するイメージでいます。

Figma自動実装|共通ガイド
```markdown
# Figma MCP 共通実装ガイド

コンポーネント実装・ページ実装に共通で参照すべきガイドです。

## 事前確認

### 既存デザインデータ確認
```bash
cat src/lib/figma-library/design-data.json
cat src/lib/figma-library/components.json
cat src/lib/figma-library/metadata.json
```

## Figmaデザイン取得・分析

### スクリーンショットで全体把握
```bash
mcp__figma-dev-mode-mcp-server__get_screenshot
```

### メタデータでノード構造確認
```bash
mcp__figma-dev-mode-mcp-server__get_metadata
```

### Code Connect情報確認(失敗しても続行)
```bash
mcp__figma-dev-mode-mcp-server__get_code_connect_map
```

### Figmaからコード生成
```bash
# 実装コードを取得(既存コンポーネント確認後)
mcp__figma-dev-mode-mcp-server__get_code
```

## 実装要件

### HTML構造
- セマンティックHTML構造で記述
- FigmaデザインデータとMCPのXMLデータから適切なHTML要素を選択
- ノード名から要素を推測:
  - `head` `heading` `見出し` → `<h1>` `<h2>` など
  - `button` `btn` `ボタン` → `<button>`
  - `nav` `navigation` → `<nav>`
  - `list` `ul` `ol` → `<ul>` `<ol>`

### React/TypeScript
- すべてのコンポーネントで `interface Props` による型定義
- HTMLに `data-name="[Figmaノード名]"` `data-node-id="[FigmaノードID]"` を付与
- 画像は `/src/components/utils/ImgOpt/ImgOpt.tsx` を使用

```typescript
interface ComponentProps {
  title: string;
  description?: string;
}

export default function Component({ title, description }: ComponentProps) {
  return (
    <div data-name="component" data-node-id="123:456">
      <h2>{title}</h2>
      <ImgOpt src="/path/to/image.png" alt={title} />
    </div>
  )
}
```

### スタイリング
- Vanilla Extract (.css.ts) でスタイル実装
- `/src/styles/colors.ts` のデザイントークン優先使用
- `/src/styles/responsive.config.ts` のブレークポイント使用
- 既存コンポーネントのスタイルパターンに準拠

#### 数値のレスポンシブ化

- 基本的に `px` の固定値ではなく `rvw()` を使用
- 詳細なガイドは @docs/responsive-style-guide.md を参照
```typescript
import { style } from '@vanilla-extract/css'
import { rvw } from '@/styles/responsive.css'

export const paragraph = style([
  {
    fontWeight: 'bold',
  },
  rvw.fontSize(16, 14),
  rvw.width(320, 240),
  rvw.padding([9, 24, 10], [6, 16, 7]),
])
```

#### 禁止パターン
```typescript
// HTMLタグセレクターは使用禁止
export const container = style([
  {
    selectors: {
      '& p': { color: 'red' } // NG
    },
  },
])
```

#### 推奨パターン
```typescript
// 個別クラスで管理
export const container = style([
  {
    display: 'flex',
    flexDirection: 'column'
  },
])

export const text = style([
  {
    color: 'red',
  },
])
```

### SVGアイコン・画像実装ルール

**重要**: SVGコードも `.svg画像` としてダウンロードし、以下の手順で実装すること:

1. **MCPで取得したSVGファイルを使用**
   - `mcp__figma-dev-mode-mcp-server__get_code`で取得されたSVGファイルパスを確認
   - 例: `const iconSvg = "/path/to/icon.svg"`

2. **ImgOptコンポーネントで表示**
   ```typescript
   <ImgOpt
     src={iconSvg}
     alt="アイコン"
     className={styles.icon}
   />
   ```

3. **手動SVGコード禁止**
   - `<svg>`タグを直接記述しない
   - Figmaデザインとの完全一致を最優先とする

4. **スタイリング調整**
   - `ImgOpt`でサイズ・色調整が困難な場合のみ、CSSフィルターを使用
   - それでも困難な場合は実装方針を再検討

### Figmaライブラリデータ活用

#### デザイントークン参照パターン
```typescript
import { colors } from '@/styles/colors'

// カラー参照
backgroundColor: colors.basic.white
border: `1px solid ${colors.basic.medium}`
color: colors.green.medium
```

#### データ不足時の対処
- `colors.ts` にカラー情報がない場合:
  1. Figmaでライブラリカラー一覧セクションを選択
  2. `mcp__figma-dev-mode-mcp-server__get_variable_defs` 実行
  3. 取得データを `'@/lib/figma-library/design-data.json'` の `design_tokens.colors` に追加
  4. さらに適切な命名規則で `colors.ts` に追加

## 画像アセットの最適化
- 生成された画像パスを ImgOpt コンポーネントに置き換え
- 適切なalt属性の設定

## エラーハンドリング

### `get_variable_defs` エラー対処
- 「使用されている変数がない」→ ライブラリ変数を使用しているコンポーネントを選択

### `get_code` エラー対処
- 生成失敗 → ノードを小さな単位に分けて再実行
- ノードID無効 → `get_metadata` で有効ID確認

### `get_screenshot` エラー対処
- 画像取得失敗 → ノードの表示状態・サイズを確認

```
コンポーネント実装用ガイド
```markdown
# Figma MCP コンポーネント実装ガイド

コンポーネント実装時に特化したガイドです。
必ず `./figma-common-guide.md` を先に参照してください。

**変数定義** : 下記の変数は置き換えて書類を読んでください。

<!--
変数定義:
- DIR_COMMON_COMPONENTS: /src/components/
- DIR_PAGE_COMPONENTS: /src/pages/**/components/
-->

## 事前確認

### 既存UIコンポーネント確認
```bash
ls -la DIR_COMMON_COMPONENTS
```

**目的**: 重複実装の防止、既存パターンの把握

## 実装方針決定

### Figmaノード名と既存コンポーネント名の対応確認
```bash
# 例: img_caption ノードがある → ImgCaption コンポーネントを探す
find DIR_COMMON_COMPONENTS -name "*[ノード名に対応する名前]*" -type f
```

**重要なポイント:**
- Figmaのノード名(snake_case)と既存コンポーネント名(PascalCase)の対応関係を確認
- 既存コンポーネントがある場合は必ず再利用
- 類似機能コンポーネントの拡張可能性を検討

### 新規コンポーネント作成の必要性判断
以下を検討:
- 既存コンポーネントで対応可能か
- 新規作成が必要なコンポーネントは何か
- どこに配置するか
  - プロジェクト共通コンポーネント DIR_COMMON_COMPONENTS
  - ページ内 DIR_PAGE_COMPONENTS

## コンポーネント実装

### 既存コンポーネントとの整合性確認
- 生成されたコンポーネント(Button, Input, Card等)が既存コンポーネントにないか確認
- 既存コンポーネントがある場合は、生成コードから削除し、importで使用

### 新規コンポーネントの分離・配置
- 再利用性の高いコンポーネントは DIR_COMMON_COMPONENTS に別ファイルとして作成
- 各コンポーネントに適切な Props インターフェースを定義

### コンポーネント配置の判断基準

#### DIR_COMMON_COMPONENTS に配置する場合
- 複数ページで再利用される可能性が高い
- 独立した機能を持つUI要素(Button、Input、Card、Modal等)
- デザインシステムの一部として管理すべき要素

#### DIR_PAGE_COMPONENTS に配置する場合
- そのページでのみ使用される固有のコンポーネント
- ページの構造に強く依存する要素

## コンポーネント設計ベストプラクティス

### 1. Props インターフェース設計
```typescript
interface ButtonProps {
  children: React.ReactNode;
  variant?: 'primary' | 'secondary' | 'outline';
  size?: 'small' | 'medium' | 'large';
  disabled?: boolean;
  onClick?: () => void;
  className?: string;
}

export default function Button({
  children,
  variant = 'primary',
  size = 'medium',
  disabled = false,
  onClick,
  className
}: ButtonProps) {
  // 実装
}
```

### 2. 再利用性の考慮
- バリエーション(variant)の定義
- サイズ(size)の選択肢
- カスタムスタイル(className)の受け取り
- 必要な機能のプロパティ化

### 3. スタイルの分離
```typescript
// Button.css.ts
export const buttonBase = style([
  {
    border: 'none',
    cursor: 'pointer',
    transition: 'all 0.2s ease',
  },
]);

export const variants = styleVariants({
  primary: {
    backgroundColor: colors.primary.main,
    color: colors.basic.white,
  },
  secondary: {
    backgroundColor: colors.gray.light,
    color: colors.basic.dark,
  },
});

export const sizes = styleVariants({
  small: { padding: '8px 16px', fontSize: '14px' },
  medium: { padding: '12px 24px', fontSize: '16px' },
  large: { padding: '16px 32px', fontSize: '18px' },
});
```

## コンポーネントドキュメント

### 1. 使用例の記載
```typescript
/**
 * 基本的なボタンコンポーネント
 *
 * @example
 * <Button variant="primary" size="medium" onClick={handleClick}>
 *   クリック
 * </Button>
 */
export default function Button({ ... }: ButtonProps) {
  // 実装
}
```

### 2. エクスポート
```typescript
// index.ts でのre-export
export { default as Button } from './Button/Button';
export { default as Input } from './Input/Input';
export { default as Card } from './Card/Card';
```

## テスト・検証

### 1. 単体テストの考慮
- コンポーネントが独立して動作するか
- プロパティの変更が正しく反映されるか
- エラー状態の処理が適切か

### 2. デザインシステムとの一貫性
- 既存コンポーネントとの見た目の統一性
- デザイントークンの正しい使用
- レスポンシブ対応の確認

```

精度を上げるポイント

自動実装する際は、Figmaデータの精度やプロンプトの書き方で、精度が変わってきます。何も考えず「実装してくれ」だけじゃ精度が落ちてしまうので、下記みたいな意識は大切...!

1. Figmaデザインデータの精度を上げる

  • バリアントで状態を整理する
    • 実装時に自動でパターン分けをしてくれる
  • プロパティで組む
    • テキスト情報等もプロパティ化することで、TypeScript型定義も一発
  • できるだけ「オートレイアウト(垂直・水平)」を適用
    • 自由形式のままにすると、不要な position: absolute が入ったり調整が必要になる
  • ノード名はシンプルな英名
    • Claude Code が認識しやすい英名にしておく方が、CSS の class 名や、コンポーネントファイル生成時の精度が上がる

2. 1フェーズ1プロンプト

  • 全ての工程を一気にお願いするよりも、実装フェーズ毎にプロンプトを分割した方が精度が上がる
  • 例えば、「ライブラリカラー実装」「コンポーネント実装」「ページ実装」など
  • 指示のボリュームが広がると精度がブレる & フィードバックがしづらくなる

Discussion