TL;DR
- Spec KitをFSD対応にカスタマイズし、実装の土台作りを効率化
- Figma APIでデザイントークンを抽出、FSD層へ自動マッピング
はじめに
フロントエンド開発において、Feature-Sliced Design (FSD) による堅牢な設計と、デザインシステムと整合性の取れた実装を両立させることは、開発リソースの限られたチームにとって大きな負担です。
本記事では、仕様駆動開発ツール「Spec Kit」を拡張し、このプロセスを半自動化した事例を紹介します。
※ Figma APIと連携することで土台は素早く作れますが、デザインの細部調整は別途対応が必要です。
カスタマイズの概要
| 項目 | 標準版 | カスタマイズ後 |
|---|---|---|
| レイヤー配置 | 考慮なし | FSD階層順(shared→entities→features→widgets→pages) |
| 実装順序 | User Story順 | FSD依存関係を考慮したボトムアップ |
| デザイン連携 | 考慮なし | Figma API経由でデザイントークン自動抽出 |
ワークフロー
# 標準のワークフロー
/frontend:speckit.specify # 1. 仕様書作成
/frontend:speckit.plan # 2. 実装計画
/frontend:speckit.tasks # 3. タスク生成
/frontend:speckit.implement # 4. 実装実行
# カスタマイズ後のワークフロー
/frontend:speckit.specify
/frontend:speckit.design-import # Figmaインポートを追加
/frontend:speckit.plan
/frontend:speckit.tasks
/frontend:speckit.implement
プロンプトのカスタマイズ内容
| コマンド | カスタマイズ内容 |
|---|---|
| specify | ・UI機能検出時のFigmaインポート提案 |
| design-import | ・Figma REST APIを用いたデザイントークン抽出 ・FigmaコンポーネントのFSD層へのマッピング |
| plan | ・FSDアーキテクチャ情報の事前読み込み ・デザインシステムとの統合 ・下位レイヤーから実装するように明示 |
| tasks | ・下位レイヤーからのタスク化 ・design-importをもとにFigmaコンポーネントをFSD層に配置 |
| implement | ・FSD層ルール・コーディング規約の事前読み込み ・ESLint FSD lintルールへの準拠を保証 |
成果物の例
spec.md
Given-When-Then形式で、テスト可能な仕様を定義
### User Story 1 - カテゴリ階層選択
ユーザーは、大カテゴリ→中カテゴリ→小カテゴリの3段階でカテゴリを指定できる。
**受け入れシナリオ**:
1. **Given** フォームが表示されている
**When** 大カテゴリドロップダウンを開く
**Then** 全ての大カテゴリが選択肢として表示される
2. **Given** 大カテゴリ→中カテゴリを選択済み
**When** 大カテゴリを変更する
**Then** 中カテゴリ・小カテゴリの選択がクリアされる
design-mapping.md
FSDへのマッピングとデザイントークン
## 1. Figma Component → FSD Mapping
AIがコンポーネントの役割と依存関係を解析し、適切なレイヤー(Shared/Features)に自動で振り分けます。
| Figma Element | Component Type | FSD Layer | Path | AI判定理由 (Rationale) |
|---|---|---|---|---|
| **CategorySelect** | Select (Hierarchical) | `features/item-form` | `ui/CategorySelect` | **階層依存あり**: 親カテゴリ(大)の選択に応じて、子カテゴリ(中・小)の選択肢が動的に変動するロジックを含むため。 |
| **TagSelector** | Toggle Group | `features/item-form` | `ui/TagSelector` | **機能固有**: 複数選択かつ排他制御(タグ付け)というドメイン独自のUIロジックを含むため。 |
| **LocationSelect** | Select (Hierarchical) | `features/item-form` | `ui/LocationSelect` | **階層依存あり**: エリア→詳細地域の依存関係があるため。 |
| **PriceInput** | TextField (number) | `shared/ui` | `ui/TextField` | **再利用可能**: 汎用的な数値入力(金額、数量等)として、ドメインロジックを持たないMUIラッパーを利用。 |
| **PeriodPicker** | Date Picker | `shared/ui` | `ui/DatePicker` | **再利用可能**: 汎用的な日付選択コンポーネントとして利用。 |
---
## 2. Design Tokens (Theme Configuration)
FigmaのStylesからトークンを抽出し、MUIテーマ(`theme.ts`)生成用の定義として出力します。
### Colors
| Token Name | Hex | Usage |
|---|---|---|
| **Primary** | `#005ce5` | アクションボタン、リンク |
| **Error** | `#c75100` | バリデーションエラー、必須項目マーク |
| **Surface** | `#ffffff` | 入力フィールド背景、カード背景 |
| **Border** | `rgba(18, 23, 26, 0.20)` | Inputの境界線(Divider) |
### Typography
| Style | Size | Weight | Use Case |
|---|---|---|---|
| **Section Title** | 18px | Bold | セクション見出し |
| **Field Label** | 14px | Medium | 入力フォームのラベル |
### Spacing & Layout
FigmaのAuto Layout設定からグリッドシステムを特定。
- **Grid System**: `8px` Base
- **Horizontal Gap**: `8px` (`spacing(1)`)
- **Vertical Gap**: `16px` (`spacing(2)`)
- **Responsive**: PC (1024px+) 用レイアウトとして抽出
plan.md
デザインシステムとの統合
## Phase 0: Research & Logic Design
実装前に以下の技術的課題を解決します。
- **課題**: 4階層の依存関係(大→中→小→詳細)の状態管理
- **方針**: Zustandストアで各層のIDを管理し、親変更時に子をリセットするロジックを実装
## Phase 1: Design System Integration
Figmaから抽出したトークンとレイアウト情報をコードベースに適合させます。
### 1. Figma Design Tokens → MUI Theme
| Token Name | Value | MUI Path | Usage |
|---|---|---|---|
| **Primary** | `#005ce5` | `palette.primary.main` | Action Buttons |
| **Error** | `#c75100` | `palette.error.main` | Validation Errors |
| **Spacing** | `8px` | `theme.spacing(1)` | Grid System Base |
### 2. Component-to-FSD Mapping
| Figma Component | FSD Layer | Path | 備考 |
|---|---|---|---|
| **CategorySelect** | `features` | `ui/CategorySelect` | 4階層の依存関係を持つドメイン固有UI |
| **ItemFormSection** | `features` | `ui/ItemFormSection` | 全フィールドを統合するコンテナ |
| **TextField** | `shared/ui` | `ui/TextField` | 汎用数値入力(再利用可能) |
### 3. Design Fidelity Strategy (実装戦略)
AIが検出したレイアウト要件と解決策:
- **レイアウト再現**: FigmaのAuto Layout設定に基づき、`<Box sx={{ gap: 1 }}>` 等で横並び(2カラム/4カラム)を実装
- **プレースホルダー競合回避**: ラベルをフィールド外側に配置(`InputLabel`)し、内部プレースホルダーとの重複表示を解消
- **日付フォーマット**: デザイン指定の `YYYY/MM/DD` (スラッシュ区切り) を強制適用
tasks.md
FSD階層順にタスクを生成(shared→features の順で実装)
## Phase 2: Foundational(基盤)
**Select Component**:
- [ ] T004 `shared/ui/Select/types.ts` 型定義作成
- [ ] T005 `shared/ui/Select/Select.tsx` MUI Selectラッパー実装
- [ ] T006 `shared/ui/Select/index.ts` Public APIエクスポート
## Phase 3: User Story 1 - カテゴリ階層選択
- [ ] T020 `features/item-form/ui/CategorySelect` 実装
- **依存**: `shared/ui/Select` と `model/store.ts` を使用
- **内容**: 4つのセレクトボックスを縦並びに配置し、storeの状態と紐付け
まとめ
Spec KitをFSDとFigma APIに最適化することで、「設計ルールの強制」と「デザイン実装の高速化」の両立が可能となり、より本質的なロジックやUIの細部へのこだわりに時間を割けるようになりました。
Tips
- Figma APIで100%のデザインを反映しようとせず、土台作成として使う
- FSDは「下位レイヤーから」という制約を明示するだけで依存逆転を防げる
- 大規模な機能は仕様書が肥大化するので分割が必要
- 最初から完璧なプロンプトを目指すのではなく、制約→試行→修正のサイクルを回し最適化していく