nextjs-shadcn-builder について
Next.jsアプリの新規作成や、既存フロントエンドのNext.jsとshadcn/uiへの移行を支援するスキルです。分析、コンポーネント対応付け、段階的な変換、検証を、デザイントークン、レスポンシブ設計、アクセシビリティを軸に進めます。
主な機能
- 01App Routerを使ったNext.jsの初期化
- 02フロントエンドコードとコンポーネントの分析
- 03コンポーネント移行の計画と分割
- 04UIをshadcn/uiコンポーネントに対応付け
- 05テスト、レスポンシブ設計、アクセシビリティの検証
活用シーン
- 01Next.jsアプリの新規構築
- 02Reactフロントエンドの移行
- 03VueやAngularのUI変換
- 04移行中のスタイル統一
MCP 対応
ワークフローではshadcn MCPサーバーを使い、コンポーネント、ドキュメント、ブロック、チャート、デザイントークンの情報を検索します。サーバーの利用可否を確認し、利用できない場合の初期化方法も示します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ovachiever/ droid-tings --skill nextjs-shadcn-builderインストール後、Claude Code で/nextjs-shadcn-builderを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.mdassets/theme-example-oklch.cssassets/component-templates/complex-form.tsxexample-feature-card.tsxexample-user-profile.tsxresponsive-dashboard.tsxresponsive-data-table.tsxresponsive-navigation.tsxreferences/accessibility-best-practices.mdadvanced-shadcn-components.mdreact-to-nextjs.mdresponsive-design-patterns.mdshadcn-component-mapping.mdstyling-migration.mdvue-to-nextjs.mdscripts/analyze-codebase.pydetect-hardcoded-values.shgenerate-migration-report.pyinit-nextjs-shadcn.sh詳細
Next.js + shadcn/ui ビルダー&移行ツール
厳格な設計原則とベストプラクティスに従って、本番環境に対応した Next.js アプリケーションを構築するか、既存のフロントエンドを体系的に Next.js + shadcn/ui に移行します。
概要
このスキルでは、次の 2 つの主要なワークフローを扱います。
- 新しい Next.js アプリケーションの作成 - Next.js 15+(App Router)、shadcn/ui、適切なデザインシステム設定でプロジェクトを初期化します
- 既存フロントエンドの移行 - あらゆるフロントエンドのコードベース(React、Vue、Angular、vanilla JS)を分析し、体系的に Next.js + shadcn/ui に変換します
基本方針:shadcn/ui の設計原則に 100%準拠します。
- すべてのテーマ設定に CSS 変数を使用します(色、間隔、タイポグラフィ)
- 標準の shadcn/ui コンポーネントのみを使用します(カスタム UI コンポーネントは使用しません)
- ハードコードされた値は使用しません(色、間隔、フォント)
- アプリケーション全体で一貫したデザイントークンを使用します
- すべてのデバイス(スマートフォン、タブレット、デスクトップ)に対応するモバイルファーストのレスポンシブデザイン
- WCAG 2.1 レベル AA のアクセシビリティ準拠
- https://ui.shadcn.com のベストプラクティス
ワークフロー決定ツリー
User Request
├─ Creating New Next.js App
│ └─ Follow "Creating New Application" workflow (Phase 3 onwards)
│
└─ Migrating Existing Codebase
├─ Phase 1: Codebase Analysis
├─ Phase 2: Migration Planning
├─ Phase 3: Next.js + shadcn Setup
├─ Phase 4: Systematic Conversion
└─ Phase 5: Verification & Cleanup
移行の大まかなワークフロー
フェーズ 1:コードベースの分析
既存のフロントエンドを自動分析し、範囲と複雑さを把握します。
手順:
- フレームワークとバージョンの検出
- コンポーネントの一覧作成と分類
- ハードコードされた値の検出(色、間隔、カスタムコンポーネント)
- スタイリング手法の分析(CSS、SCSS、CSS-in-JS、Tailwind など)
- 状態管理とルーティングのパターンの特定
- 詳細な分析レポートの生成
成果物:
- フレームワーク分析レポート
- コンポーネント一覧(JSON)
- ハードコードされた値のレポート
- 複雑さの評価
フェーズ 2:移行計画の作成
優先順位を付けたバッチで、体系的な変換計画を作成します。
手順:
- 既存のコンポーネントを shadcn/ui の同等コンポーネントに対応付ける
- カスタム開発が必要なコンポーネントを特定する
- 変換をバッチに分割する(1 バッチあたり 5~10 個のコンポーネント)
- バッチごとにリスクと複雑さを評価する
- 詳細な移行計画を作成する
成果物:
- コンポーネント対応表
- バッチ分割された変換計画
- リスク評価
- コンポーネントごとの複雑さの見積もり
フェーズ 3:Next.js + shadcn のセットアップ
既存のコードベースに併設するか置き換える形で、Next.js のインフラストラクチャを初期化します。
手順:
- ドキュメントにアクセスできるよう、shadcn MCP サーバーを確認/インストールする
- App Router と TypeScript を使用して Next.js 15+ を初期化する
- Tailwind CSS をインストールして設定する
- shadcn/ui の初期化を実行する
- CSS 変数とデザイントークンをセットアップする
- パスエイリアス(@/)を設定する
- 必須の shadcn コンポーネントをインストールする
- デザインシステムのドキュメントを作成する
成果物:
- 設定済みの Next.js プロジェクト
- デザイントークンシステム(CSS 変数)
- コンポーネントライブラリのセットアップ
- 設定済みのパスエイリアス
フェーズ 4:体系的な変換
バッチごとにコンポーネントを変換し、各バッチの後にテストします。
手順:
- バッチ 1:レイアウトと構造(ヘッダー、フッター、レイアウトラッパー)
- バッチ 2:シンプルな UI コンポーネント(ボタン、カード、バッジ、アラート)
- バッチ 3:フォームコンポーネント(入力、セレクト、チェックボックス、フォーム)
- バッチ 4:複雑なコンポーネント(テーブル、ダイアログ、コマンドメニュー、データの可視化)
- バッチ 5:スタイリングの標準化(ハードコードされた値を削除し、CSS 変数を適用)
- バッチ 6:ページとルート(ページを変換し、Next.js のルーティングをセットアップ)
バッチごとのワークフロー:
- 関連するコンポーネントを 5~10 個選択する
- MCP を使用して適切な shadcn コンポーネントを見つける
- shadcn のパターンに従ってコンポーネントを変換する
- ハードコードされた値を CSS 変数に置き換える
- 機能をテストする
- 視覚的な一貫性を確認する
- 次のバッチに進む
成果物:
- 移行済みコンポーネント(バッチごと)
- CSS 変数を使用したスタイルの更新
- Next.js App Router のページ
- バッチごとのテスト合格
フェーズ 5:検証とクリーンアップ
最終テスト、最適化、古いコードの削除を行います。
手順:
- テストスイート全体を実行します
- ビジュアルリグレッションテストを行います
- レスポンシブデザインをテストします(モバイル、タブレット、デスクトップ)
- パフォーマンス監査を行います
- アクセシビリティ監査を行います(WCAG 2.1 レベル AA 準拠)
- 古いフレームワークのコードを削除します
- ドキュメントを更新します
- 完了レポートを生成します
成果物:
- テスト結果
- レスポンシブデザインの検証レポート
- パフォーマンス指標
- アクセシビリティ監査レポート(WCAG 2.1 AA)
- クリーンなコードベース
- 移行の概要
フェーズ 1:コードベース分析(詳細な手順)
1.1 フレームワークの検出
自動分析スクリプトを実行します:
python ./scripts/analyze-codebase.py /path/to/existing/codebase
このスクリプトは以下を実行します:
- フレームワークを検出します(React、Vue、Angular、Svelte、vanilla JS など)
- フレームワークのバージョンを特定します
- ビルドツールを検出します(Vite、Webpack、Parcel など)
- package.json の依存関係を確認します
- ディレクトリ構成をマッピングします
出力: フレームワークのメタデータを含む codebase-analysis.json
1.2 コンポーネントの一覧作成
分析スクリプトは、以下を含むコンポーネントの一覧を自動生成します:
- コンポーネント名とファイルパス
- コンポーネントの種類(関数型、クラス型、Vue SFC など)
- Props/入力
- State の使用状況
- 子コンポーネント
- 外部依存関係
出力: component-inventory.json
構造の例:
{
"components": [
{
"name": "UserCard",
"path": "src/components/UserCard.tsx",
"type": "functional",
"complexity": "simple",
"shadcn_equivalent": "Card",
"hardcoded_values": ["#3b82f6", "16px padding"],
"dependencies": ["react", "styled-components"]
}
]
}
1.3 ハードコードされた値の検出
検出スクリプトを実行します:
bash ./scripts/detect-hardcoded-values.sh /path/to/existing/codebase
このスクリプトは以下を検出します:
- ハードコードされた色:
#hex、rgb()、rgba()、hsl()、色名 - インラインのスペーシング:
margin: 20px、padding: 1rem - カスタムフォントの宣言: 標準以外のフォント
- マジックナンバー: コンポーネント内の任意の値
- インラインスタイル:
style={{...}} - 標準外のパターン: Tailwind を使用すべき CSS-in-JS、styled-components
出力: 違反項目をカテゴリ別にまとめた hardcoded-values-report.md
1.4 分析レポートの生成
レポート生成ツールを実行します:
python ./scripts/generate-migration-report.py
これにより、すべての分析データを包括的な Markdown レポートにまとめます:
出力: migration-analysis-report.md
# Frontend Migration Analysis Report
## Executive Summary
[One-paragraph overview: framework, size, complexity]
## Current State Analysis
- **Framework**: React 18.2.0
- **Build Tool**: Vite 4.3.0
- **Component Count**: 47 components
- **Styling**: styled-components + custom CSS
- **State Management**: Redux Toolkit
- **Routing**: React Router v6
## Hardcoded Values Detected
- Colors: 142 instances across 34 files
- Spacing: 89 instances across 28 files
- Custom fonts: 3 non-standard fonts
- Inline styles: 67 instances
## Component Categorization
- **Simple (shadcn mapping exists)**: 28 components
- **Moderate (requires adaptation)**: 13 components
- **Complex (custom development needed)**: 6 components
## Recommended Migration Plan
1. Phase 3: Setup Next.js + shadcn infrastructure
2. Phase 4.1: Convert layout components (Header, Footer, Layout)
3. Phase 4.2: Convert simple UI (Button, Card, Badge → shadcn equivalents)
4. Phase 4.3: Convert forms (Input, Select → shadcn/ui Form components)
5. Phase 4.4: Convert complex components (DataTable, Charts)
6. Phase 4.5: Styling standardization (CSS variables)
7. Phase 4.6: Pages and routing
8. Phase 5: Verification and cleanup
## Estimated Effort
- **Total Components**: 47
- **Batches**: 9-10 batches
- **Complexity**: Moderate
フェーズ 2:移行計画(詳細な手順)
2.1 コンポーネントのマッピング戦略
component-inventory.json を確認し、shadcn コンポーネントのリファレンスを使用してマッピング表を作成します。
非常に重要:MCP を使用して shadcn コンポーネントを確認してください
マッピングの前に、shadcn MCP サーバーが利用可能か確認します:
# Check if MCP server is available
# Try accessing https://ui.shadcn.com/docs/mcp
MCP が利用できない場合は、インストールします:
npx shadcn@latest mcp init --client claude
MCP を使用して利用可能なコンポーネントを検索します:
- 「ボタンにはどの shadcn コンポーネントがありますか?」
- 「shadcn のフォームコンポーネントを表示してください」
- 「モーダル/ダイアログに相当する shadcn コンポーネントは何ですか?」
- 「shadcn で利用できるデータ表示コンポーネント」
コンポーネントマッピング表のテンプレート:
| 既存のコンポーネント | shadcn の相当コンポーネント | 複雑さ | 優先度 | 備考 |
|---|---|---|---|---|
| CustomButton | Button | 低 | 1 | Props はほぼ互換性があります |
| Modal | Dialog | 中 | 2 | API が異なり、Radix を使用します |
| DataTable | Table + DataTable | 高 | 3 | カスタムフックが必要です |
| Dropdown | DropdownMenu | 低 | 1 | 直接マッピングできます |
| DatePicker | Calendar + Popover | 中 | 2 | コンポジションパターン |
フレームワーク固有の移行ガイドを読み込みます:
- React の場合:
./references/react-to-nextjs.mdを読みます - Vue の場合:
./references/vue-to-nextjs.mdを読みます - Angular の場合:
./references/angular-to-nextjs.mdを読みます - スタイリングの場合:
./references/styling-migration.mdを読みます
2.2 バッチの編成
以下の原則に従って、コンポーネントをバッチに編成します。
バッチ戦略:
- 種類ごとにグループ化(レイアウト、フォーム、データ表示、ナビゲーション)
- シンプルなものから複雑なものへ(簡単に対応できるものから始めます)
- 依存関係の順序(依存先を先に変換します)
- バッチのサイズ:バッチあたり5~10個のコンポーネント
バッチ計画の例:
バッチ1:レイアウトと構造(優先度:重大)
- ヘッダー
- フッター
- MainLayout
- Container
- Sidebar
バッチ2:シンプルなUIコンポーネント(優先度:高)
- Button → shadcn Button
- Card → shadcn Card
- Badge → shadcn Badge
- Alert → shadcn Alert
- Avatar → shadcn Avatar
バッチ3:フォームコンポーネント(優先度:高)
- Input → shadcn Input
- Select → shadcn Select
- Checkbox → shadcn Checkbox
- RadioGroup → shadcn RadioGroup
- フォームのバリデーション → shadcn Form + react-hook-form
バッチ4:ナビゲーション(優先度:中)
- NavBar → shadcn NavigationMenu
- パンくずリスト → shadcn Breadcrumb
- Tabs → shadcn Tabs
- ページネーション → shadcn Pagination
バッチ5:データ表示(優先度:中)
- Table → shadcn Table
- DataGrid → shadcn DataTable(並べ替え、フィルタリング機能付き)
- List → shadcn のカスタム合成
- Accordion → shadcn Accordion
バッチ6:オーバーレイとモーダル(優先度:中)
- Modal → shadcn Dialog
- Tooltip → shadcn Tooltip
- Popover → shadcn Popover
- DropdownMenu → shadcn DropdownMenu
バッチ7:複雑なコンポーネント(優先度:低)
- グラフ → shadcn Charts(Recharts との統合)
- カレンダー/DatePicker → shadcn Calendar
- CommandPalette → shadcn Command
- DataVisualization → shadcn プリミティブを使ったカスタム実装
バッチ8:スタイルの標準化(優先度:重大)
- ハードコードされたすべての色を抽出 → CSS 変数
- 余白を Tailwind クラスに変換
- タイポグラフィを標準化
- テーマシステムを一貫して適用
バッチ9:ページとルーティング(優先度:重大)
- ページを Next.js App Router に変換
- Next.js の layout.tsx でレイアウトを設定
- ルーティングパターンを実装
- ローディング状態とエラー状態を追加
2.3 リスク評価
各バッチについて、リスクを特定します。
- API の違い:API が大きく異なるコンポーネント
- 機能の不足:旧コンポーネントにあり、shadcn にはない機能
- 状態管理:リファクタリングが必要な複雑な状態
- 依存関係:置き換えが必要な外部ライブラリ
- カスタムロジック:UI と密接に結び付いているビジネスロジック
リスクの軽減策:
- 変換前に API の違いを文書化します
- 必要に応じてアダプター/ラッパーコンポーネントを作成します
- 移行前にテストを作成します
- 移行中は古いコンポーネントを一時的に残します
2.4 詳細な移行計画の作成
詳細な計画書 migration-plan.md を生成します。
# Next.js + shadcn Migration Plan
## Project: [Project Name]
## Date: [Current Date]
## Estimated Timeline: [X batches]
## Migration Strategy
### Approach
- Incremental migration with parallel running old and new code
- Batch-based conversion (5-10 components per batch)
- Test after each batch before proceeding
- Feature flag new components during transition
### Success Criteria
- All components use shadcn/ui or shadcn patterns
- Zero hardcoded colors/spacing (CSS variables only)
- 100% TypeScript coverage
- Passing test suite
- Lighthouse score >= 90
- No accessibility violations
## Detailed Batch Plan
[Include all batches from 2.2 with specific components listed]
## Timeline
Batch 1: Layout & Structure (Days 1-2)
Batch 2: Simple UI (Days 3-4)
[etc.]
## Notes and Considerations
[Any special requirements, blockers, or dependencies]
フェーズ3:Next.js + shadcn のセットアップ(詳細手順)
3.1 shadcn MCP サーバーの確認/インストール
重大:shadcn コンポーネントの検索には常に MCP を使用してください
-
MCP サーバーにアクセスできるか確認します。
https://ui.shadcn.com/docs/mcpのドキュメントにアクセスしてみます- MCP 経由で shadcn コンポーネントを照会できるか確認します
-
利用できない場合は、MCP サーバーをインストールします。
npx shadcn@latest mcp init --client claude
これにより、以下が可能になります。
- shadcn のドキュメントにリアルタイムでアクセス
- コンポーネントの検索と探索
- ブロックとグラフのテンプレートの探索
- テーマとデザイントークンの参照
開発中の MCP の使用方法:
- 「[ユースケース]で利用できるコンポーネントは何ですか?」
- 「shadcn Button の props を見せてください」
- 「shadcn で利用できるグラフの種類は何ですか?」
- 「バリデーション付きで shadcn Form を使用する方法を教えてください」
3.2 Next.js プロジェクトの初期化
初期化スクリプトを実行します。
bash ./scripts/init-nextjs-shadcn.sh [project-name]
または、手動で初期化します。
# Check Node.js version (18+ required)
node -v
# Create Next.js project with App Router
npx create-next-app@latest [project-name] \
--typescript \
--tailwind \
--app \
--src-dir \
--import-alias "@/*" \
--no-turbopack
cd [project-name]
3.3 shadcn/ui のインストールと設定
# Initialize shadcn/ui
npx shadcn@latest init
# Configuration prompts:
# - TypeScript: Yes
# - Style: Default
# - Base color: Choose from slate/gray/zinc/neutral/stone
# - CSS variables: Yes (CRITICAL - required for theming)
# - Import alias: @/components
これにより、以下が作成されます。
components.json設定ファイル- cn() ヘルパーを含む
lib/utils.ts - shadcn テーマで更新された
tailwind.config.ts app/globals.css内の CSS 変数
3.4 デザイントークン(CSS 変数)の設定
非常に重要:テーマ設定には必ず CSS 変数を使用してください
カラー形式:OKLCH(推奨)
このスキルでは、知覚上の均一性と色の正確性を高めるため、HSL ではなく OKLCH(OKLab 明度・彩度・色相)色空間を使用します。
OKLCH のメリット:
- 知覚上均一です(同じ変化量が同じ知覚差になります)
- グラデーションの補間に優れています
- 明度をより予測しやすくなります
- アクセシビリティに適しています(コントラスト比をより正確に把握できます)
app/globals.css を編集して、デザインシステムを定義します。
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--radius: 0.65rem;
/* Background - Pure white */
--background: 1 0 0;
--foreground: 0.141 0.005 285.823;
/* Card */
--card: 1 0 0;
--card-foreground: 0.141 0.005 285.823;
/* Popover */
--popover: 1 0 0;
--popover-foreground: 0.141 0.005 285.823;
/* Primary - Warm orange */
--primary: 0.646 0.222 41.116;
--primary-foreground: 0.98 0.016 73.684;
/* Secondary - Light purple-gray */
--secondary: 0.967 0.001 286.375;
--secondary-foreground: 0.21 0.006 285.885;
/* Muted - Subtle elements */
--muted: 0.967 0.001 286.375;
--muted-foreground: 0.552 0.016 285.938;
/* Accent */
--accent: 0.967 0.001 286.375;
--accent-foreground: 0.21 0.006 285.885;
/* Destructive - Red */
--destructive: 0.577 0.245 27.325;
/* Border and Input */
--border: 0.92 0.004 286.32;
--input: 0.92 0.004 286.32;
/* Focus ring */
--ring: 0.75 0.183 55.934;
/* Chart colors */
--chart-1: 0.837 0.128 66.29;
--chart-2: 0.705 0.213 47.604;
--chart-3: 0.646 0.222 41.116;
--chart-4: 0.553 0.195 38.402;
--chart-5: 0.47 0.157 37.304;
}
.dark {
/* Dark mode backgrounds */
--background: 0.141 0.005 285.823;
--foreground: 0.985 0 0;
/* Dark mode card */
--card: 0.21 0.006 285.885;
--card-foreground: 0.985 0 0;
/* Dark mode popover */
--popover: 0.21 0.006 285.885;
--popover-foreground: 0.985 0 0;
/* Dark mode primary - Brighter for contrast */
--primary: 0.705 0.213 47.604;
--primary-foreground: 0.98 0.016 73.684;
/* Dark mode secondary */
--secondary: 0.274 0.006 286.033;
--secondary-foreground: 0.985 0 0;
/* Dark mode muted */
--muted: 0.274 0.006 286.033;
--muted-foreground: 0.705 0.015 286.067;
/* Dark mode accent */
--accent: 0.274 0.006 286.033;
--accent-foreground: 0.985 0 0;
/* Dark mode destructive */
--destructive: 0.704 0.191 22.216;
/* Dark mode borders (with alpha) */
--border: 1 0 0 / 10%;
--input: 1 0 0 / 15%;
/* Dark mode focus ring */
--ring: 0.408 0.123 38.172;
/* Chart colors (consistent) */
--chart-1: 0.837 0.128 66.29;
--chart-2: 0.705 0.213 47.604;
--chart-3: 0.646 0.222 41.116;
--chart-4: 0.553 0.195 38.402;
--chart-5: 0.47 0.157 37.304;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
移行するプロジェクト向けのカスタマイズ:
デザインシステムを備えた既存アプリを移行する場合は、既存のカラーを抽出し、CSS 変数に割り当てます。
# Use the detection script to find existing colors
bash ./scripts/detect-hardcoded-values.sh /path/to/old/codebase
# Map old colors to new CSS variables (OKLCH format)
# Use https://oklch.com or https://colorjs.io to convert
# Example:
# Old: #FF6B35 (brand orange) → --primary: 0.646 0.222 41.116
# Old: #3B82F6 (blue) → --primary: 0.630 0.213 255.5
# Old: #10B981 (green) → --success: 0.710 0.180 165.4
3.5 必須の shadcn コンポーネントをインストールする
MCP を使って、必要なコンポーネントを確認しましょう!
コアコンポーネントをインストールします。
# Layout & Structure
npx shadcn@latest add card
npx shadcn@latest add separator
# Forms
npx shadcn@latest add button
npx shadcn@latest add input
npx shadcn@latest add label
npx shadcn@latest add select
npx shadcn@latest add checkbox
npx shadcn@latest add radio-group
npx shadcn@latest add form
# Navigation
npx shadcn@latest add navigation-menu
npx shadcn@latest add tabs
npx shadcn@latest add breadcrumb
# Feedback
npx shadcn@latest add alert
npx shadcn@latest add toast
npx shadcn@latest add dialog
npx shadcn@latest add tooltip
# Data Display
npx shadcn@latest add table
npx shadcn@latest add badge
npx shadcn@latest add avatar
# Overlays
npx shadcn@latest add popover
npx shadcn@latest add dropdown-menu
npx shadcn@latest add sheet
開発中に必要に応じて、MCP に問い合わせて追加のコンポーネントを確認してください。
3.6 テーマプロバイダーを設定する(ダークモード対応)
next-themes をインストールします。
npm install next-themes
components/theme-provider.tsx を作成します。
"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types"
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}
app/layout.tsx を更新します。
import { ThemeProvider } from "@/components/theme-provider"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</ThemeProvider>
</body>
</html>
)
}
3.7 サンプルコンポーネントを作成する
ベストプラクティスを示す components/example-card.tsx を作成します。
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
export function ExampleCard() {
return (
<Card className="w-full max-w-md">
<CardHeader>
<CardTitle>shadcn/ui Best Practices</CardTitle>
<CardDescription>
This card demonstrates proper shadcn patterns
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">
Notice: No hardcoded colors, using CSS variables via Tailwind classes,
standard shadcn components, and proper typography scale.
</p>
</CardContent>
<CardFooter className="flex justify-between">
<Button variant="outline">Cancel</Button>
<Button>Continue</Button>
</CardFooter>
</Card>
)
}
示されている主なパターン:
- 標準の shadcn コンポーネント(Card、Button)を使用しています
- ハードコードされたカラーを使用しません(
text-muted-foregroundを使用) - CSS 変数は Tailwind を通じて自動的に適用されます
- セマンティックなバリアント(
outline、default)を使用しています - 適切にコンポーネントを構成しています
フェーズ 4:体系的な変換(詳細な手順)
4.1 コンポーネント変換のワークフロー
コンポーネントを 5~10 個ずつ変換します。
ステップ 1:バッチ内のコンポーネントを確認する
コンポーネントファイルを読み込み、以下を把握します。
- 現在の機能
- Props/API
- スタイル設定の方法
- 状態管理
- イベントハンドラー
ステップ 2:MCP に shadcn の対応コンポーネントを問い合わせる
変換前に、MCP を使って以下を確認します。
- 「[component type] に対応する shadcn コンポーネントは何ですか?」
- 「shadcn の [component] の Props と使用例を見せてください」
- 「[feature] で shadcn の [component] を使う方法を教えてください」
ステップ 3:コンポーネントを変換する
次のパターンに従います。
// OLD: Custom button with hardcoded styles
const CustomButton = ({ children, onClick, variant = 'primary' }) => {
const styles = {
primary: {
backgroundColor: '#3b82f6', // HARDCODED!
color: '#ffffff',
padding: '8px 16px', // HARDCODED!
borderRadius: '6px'
},
secondary: {
backgroundColor: '#6b7280',
color: '#ffffff',
padding: '8px 16px',
borderRadius: '6px'
}
}
return (
<button style={styles[variant]} onClick={onClick}>
{children}
</button>
)
}
// NEW: shadcn Button with CSS variables
import { Button } from "@/components/ui/button"
const CustomButton = ({ children, onClick, variant = 'default' }) => {
return (
<Button variant={variant} onClick={onClick}>
{children}
</Button>
)
}
変換チェックリスト:
- ✅ shadcn コンポーネントに置き換える
- ✅ ハードコードされたカラーをすべて削除する
- ✅ インラインスタイルを削除する
- ✅ Tailwind クラスのみを使用する
- ✅ セマンティックなバリアント(default、outline、destructive など)を使用する
- ✅ すべての機能を維持する
- ✅ TypeScript の型を適切に定義する
ステップ 4:ハードコードされた値を CSS 変数に置き換える
// OLD: Hardcoded spacing and colors
<div style={{
backgroundColor: '#f3f4f6', // WRONG
padding: '20px', // WRONG
margin: '10px 0' // WRONG
}}>
// NEW: Tailwind classes using CSS variables
<div className="bg-secondary p-5 my-2.5">
// Or for custom spacing:
<div className="bg-secondary" style={{ padding: 'var(--spacing-5)' }}>
ステップ 5:機能をテストする
各コンポーネントの変換後に、以下を行います。
# Run tests
npm test
# Visual testing
npm run dev
# Manually verify component renders correctly
ステップ 6:違反がないことを確認する
新しいコンポーネントに対して検出スクリプトを実行します。
bash ./scripts/detect-hardcoded-values.sh src/components/[batch-name]
違反数が 0 件になるはずです。
ステップ 7:バッチを完了としてマークし、次に進む
todo リストと migration-plan.md の進捗を更新します。
4.2 よくあるコンポーネントの移行
詳細な対応表については、./references/shadcn-component-mapping.md を参照してください。
クイックリファレンス:
| パターン | 従来の方法 | shadcn の方法 |
|---|---|---|
| Button | カスタムスタイルのボタン | <Button variant="..."> |
| Modal/Dialog | カスタムオーバーレイ | <Dialog> と <DialogTrigger>、<DialogContent> |
| Form Input | バリデーション付きカスタム入力 | <Form> + <FormField> + react-hook-form |
| Dropdown | カスタムセレクト | <Select> または <DropdownMenu> |
| Table | カスタムテーブル | <Table> または DataTable パターン |
| Tooltip | カスタムホバーコンポーネント | <Tooltip> |
| Toast/Notification | カスタム通知 | useToast() フック + <Toaster> |
| Tabs | カスタムタブコンポーネント | <Tabs> と <TabsList>、<TabsContent> |
| Card | カスタムカード | サブコンポーネントを含む <Card> |
| Badge | カスタムバッジ/ピル | <Badge variant="..."> |
4.3 複雑なコンポーネントの処理
shadcn に直接対応するものがないコンポーネントの場合:
オプション 1:コンポジション
shadcn のプリミティブを使って構築します:
// Complex dashboard widget using shadcn primitives
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
export function DashboardWidget({ title, data, onRefresh }) {
return (
<Card>
<CardHeader className="flex flex-row items-center justify-between">
<CardTitle>{title}</CardTitle>
<Button variant="outline" size="sm" onClick={onRefresh}>
Refresh
</Button>
</CardHeader>
<CardContent>
{data.map(item => (
<div key={item.id} className="flex items-center justify-between py-2">
<span className="text-sm">{item.label}</span>
<Badge variant={item.status === 'success' ? 'default' : 'destructive'}>
{item.value}
</Badge>
</div>
))}
</CardContent>
</Card>
)
}
オプション 2:shadcn コンポーネントの拡張
shadcn を拡張するカスタムコンポーネントを作成します:
// Custom component extending shadcn Button
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"
interface IconButtonProps extends React.ComponentProps<typeof Button> {
icon: React.ReactNode
}
export function IconButton({ icon, children, className, ...props }: IconButtonProps) {
return (
<Button className={cn("flex items-center gap-2", className)} {...props}>
{icon}
{children}
</Button>
)
}
オプション 3:shadcn ブロックを使用
MCP を使って shadcn ブロック(あらかじめ構築された複雑なコンポーネント)を検索します:
「shadcn には [ユースケース] 向けにどのようなブロックがありますか?」
ブロックをインストールします:
npx shadcn@latest add [block-name]
4.4 ページとルートの変換
ページを Next.js App Router の構造に変換します:
旧構造(React Router):
src/
pages/
Home.tsx
About.tsx
Dashboard.tsx
users/
UserList.tsx
UserDetail.tsx
新構造(Next.js App Router):
app/
page.tsx # Home
about/
page.tsx # About
dashboard/
page.tsx # Dashboard
layout.tsx # Dashboard layout
users/
page.tsx # UserList
[id]/
page.tsx # UserDetail
layout.tsx # Root layout
loading.tsx # Loading state
error.tsx # Error boundary
変換例:
// OLD: React Router page
// src/pages/Dashboard.tsx
import { useNavigate } from 'react-router-dom'
export function Dashboard() {
const navigate = useNavigate()
return (
<div style={{ padding: '20px' }}>
<h1>Dashboard</h1>
<button onClick={() => navigate('/users')}>
View Users
</button>
</div>
)
}
// NEW: Next.js App Router page
// app/dashboard/page.tsx
import Link from 'next/link'
import { Button } from '@/components/ui/button'
export default function DashboardPage() {
return (
<div className="container py-6">
<h1 className="text-3xl font-bold mb-6">Dashboard</h1>
<Link href="/users">
<Button>View Users</Button>
</Link>
</div>
)
}
主な変更点:
- ページにはデフォルトエクスポートを使用します
- ルーターによるナビゲーションの代わりに Next.js の
<Link>を使用します - ハードコードされたパディングを削除し、Tailwind クラスを使用します
- shadcn の Button を使用します
4.5 状態管理の移行
参照資料を読み込みます: 状態管理のパターンについては ./references/react-to-nextjs.md を参照してください
一般的なパターン:
ローカル状態(useState):
- Next.js App Router でも変更ありません
- クライアントコンポーネントに
"use client"を指定します
グローバル状態:
- Redux → Zustand または React Context
- MobX → Zustand
- Recoil → Zustand または Jotai
サーバー状態:
- React Query → TanStack Query(Next.js でも引き続き動作します)
- SWR → SWR(Next.js 互換)
- または、サーバーのデータには Next.js Server Components を使用します
フェーズ 5:検証とクリーンアップ(詳細手順)
5.1 テストスイートを実行
# Run all tests
npm test
# Run with coverage
npm test -- --coverage
# Ensure 100% of migrated components have passing tests
5.2 ビジュアルリグレッションテスト
手動での確認チェックリスト:
- すべてのページが正しく表示される
- すべてのコンポーネントがデザインシステムに準拠している
- ダークモードが正しく動作する
- レスポンシブデザインが維持されている
- ハードコードされた色が表示されない
- 全体を通して間隔が統一されている
- タイポグラフィがデザインシステムに準拠している
任意:Percy、Chromatic、または Playwright を使って、自動ビジュアルリグレッションテストを設定します。
5.3 レスポンシブデザインのテスト
重要:ブラウザーの DevTools だけでなく、実機でテストしてください
参照先: 包括的なレスポンシブテストのガイドラインについては ./references/responsive-design-patterns.md を参照してください。
デバイステストのチェックリスト:
- iPhone SE(320px - 現行機種で最小のビューポート)
- iPhone 14 Pro(390px)
- iPad(768px)
- iPad Pro(1024px)
- デスクトップ(1280px - 1920px)
- ウルトラワイド(2560px 以上)
向きのテスト:
- モバイル/タブレットの縦向き
- モバイル/タブレットの横向き
- デバイスを回転させたときのレスポンシブな動作
レスポンシブパターンの確認:
- ナビゲーション:モバイルのハンバーガーメニュー → タブレットのサイドバー → デスクトップのナビゲーションバー
- データテーブル:モバイルのカード → タブレットのスクロール可能なテーブル → デスクトップの全幅テーブル
- グリッド:モバイルは 1 列 → タブレットは 2 列 → デスクトップは 3~4 列
- フォーム:モバイルは 1 列 → デスクトップは複数列
- タッチターゲット:モバイルでは最小 44x44px
- タイポグラフィ:すべての画面サイズで読みやすい(本文は最小 16px)
- 画像:適切なアスペクト比でレスポンシブにサイズ調整される
ブレークポイントの確認:
# Test all Tailwind breakpoints
# sm: 640px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px
# Verify components respond correctly at each breakpoint
コンポーネントの例:
レスポンシブデザインの例については ./assets/component-templates/ を確認してください:
responsive-navigation.tsx- モバイル/タブレット/デスクトップのナビゲーションパターンresponsive-data-table.tsx- モバイルではカード表示になるレスポンシブテーブルresponsive-dashboard.tsx- レスポンシブなグリッドレイアウトcomplex-form.tsx- 複数ステップのレスポンシブフォーム
5.4 ハードコードされた値の最終チェックを実行
bash ./scripts/detect-hardcoded-values.sh src/
期待される結果: 違反 0 件
違反が見つかった場合は、フェーズ 4 に戻って修正してください。
5.5 アクセシビリティ監査(WCAG 2.1 レベル AA)
重要:WCAG 2.1 レベル AA への準拠を達成してください
参照先: アクセシビリティテストの包括的なガイドラインについては、./references/accessibility-best-practices.md を参照してください。
# Install axe DevTools or use Lighthouse
npm install -D @axe-core/playwright
# Run accessibility tests
npm run test:a11y
shadcn/ui のコンポーネントは、アクセシビリティを考慮して構築されています(Radix UI のプリミティブを使用)が、次の項目を確認してください。
自動テスト:
- axe DevTools のブラウザー拡張機能をすべてのページで実行する
- Lighthouse のアクセシビリティスコアが 90 以上
- 自動ツールによる WCAG 違反の報告がない
- eslint-plugin-jsx-a11y が合格している(設定されている場合)
キーボード操作(WCAG 2.1.1、2.1.2):
- すべてのインタラクティブ要素に Tab キーでアクセスできる
- 論理的なタブ順序になっている(視覚的なレイアウトに沿っている)
- キーボードトラップがない(すべてのコンポーネントから Tab キーで移動できる)
- Enter/Space キーでボタンやリンクを操作できる
- Escape キーでモーダルやダイアログを閉じられる
- 矢印キーでコンポーネント内を移動できる(タブ、メニュー、ラジオグループ)
- すべてのインタラクティブ要素でフォーカスインジケーターが見える
スクリーンリーダーのテスト: 実際のスクリーンリーダーでテストします。
- macOS:VoiceOver(Cmd + F5)
- Windows:NVDA(無料)または JAWS
- モバイル:VoiceOver(iOS)または TalkBack(Android)
スクリーンリーダーのチェックリスト(WCAG 1.3.1、4.1.2):
- すべての画像に alt テキストがある
- フォーム入力に対応するラベルがある
- ボタンに説明的なテキストまたは aria-label がある
- 見出しが論理的な階層に沿っている(h1 → h2 → h3)
- ランドマークがある(header、nav、main、aside、footer)
- 動的コンテンツが aria-live 領域を介して通知される
- エラーメッセージがスクリーンリーダーに通知される
色のコントラスト(WCAG 1.4.3):
- 本文テキスト:コントラスト比が 4.5:1 以上
- 大きなテキスト(18pt 以上):コントラスト比が 3:1 以上
- UI コンポーネント:コントラスト比が 3:1 以上
- フォーカスインジケーター:コントラスト比が 3:1 以上
- ライトモードとダークモードの両方でテストする
フォームのアクセシビリティ(WCAG 3.3.1、3.3.2):
- すべての入力に視認できるラベルがある
- 必須フィールドが明確に示されている
- エラーメッセージが具体的で役に立つ
- エラーメッセージが入力に関連付けられている(aria-describedby)
- フォームの検証が色だけに依存していない
タッチターゲット(WCAG 2.5.5):
- モバイル上のすべてのタッチターゲットが CSS ピクセルで 44x44 以上
- タッチターゲット間に十分な間隔がある(最低 8px)
ARIA の使用(WCAG 4.1.2):
- アイコンのみのボタンに ARIA ラベルがある
- 折りたたみ可能なセクションに aria-expanded がある
- タブに aria-selected がある
- 装飾要素に aria-hidden がある
- エラーメッセージに role="alert" がある
- 重要度の低い更新に role="status" がある
WCAG 2.1 AA 完全チェックリスト:
WCAG 2.1 レベル AA の完全なチェックリストについては、./references/accessibility-best-practices.md を参照してください。
5.6 パフォーマンス監査
# Build for production
npm run build
# Analyze bundle
npm run analyze # If you have bundle analyzer configured
Lighthouse 監査を実行します。
- パフォーマンスが 90 以上
- アクセシビリティが 90 以上
- ベストプラクティスが 90 以上
- SEO が 90 以上
パフォーマンスのチェックリスト:
- Core Web Vitals が「良好」の基準を満たしている
- LCP(最大視覚コンテンツの表示時間)< 2.5s
- FID(初回入力遅延)< 100ms
- CLS(累積レイアウトシフト)< 0.1
- 画像が最適化されている(Next.js Image コンポーネントを使用)
- 大きなコンポーネントにコード分割が実装されている
- ファーストビューより下のコンテンツが遅延読み込みされる
- バンドルサイズが妥当である(バンドルアナライザーで確認)
5.7 古いコードを削除する
移行の検証が完了したら:
# Remove old framework code
rm -rf src/old-components/ # or whatever old structure was
# Remove old dependencies
npm uninstall [old-framework] [old-ui-library] styled-components emotion ...
# Clean up old config files
rm -f .babelrc webpack.config.js # etc.
5.8 完了レポートを生成する
migration-complete-report.md を作成します。
# Migration Completion Report
## Summary
Successfully migrated [Project Name] from [Old Framework] to Next.js + shadcn/ui.
## Statistics
- **Components Migrated**: 47
- **Lines of Code Changed**: ~5,200
- **Hardcoded Values Removed**: 231
- **CSS Variables Added**: 48
- **shadcn Components Used**: 18
## Test Results
- **Unit Tests**: 142/142 passing
- **Integration Tests**: 23/23 passing
- **Accessibility Score**: 98/100
- **Lighthouse Performance**: 94/100
## Before/After Comparison
### Before
- Framework: React 18 + Vite
- Styling: styled-components + custom CSS
- Hardcoded values: 231 violations
- Bundle size: 523 KB
- Lighthouse: 76
### After
- Framework: Next.js 15 + App Router
- Styling: Tailwind CSS + shadcn/ui
- Hardcoded values: 0 violations
- Bundle size: 398 KB (24% reduction)
- Lighthouse: 94 (23% improvement)
## Design System
All components now use CSS variables defined in globals.css:
- 24 color tokens
- 12 spacing tokens
- 8 typography tokens
- Full dark mode support
## Next Steps
- Deploy to production
- Monitor performance metrics
- Gather user feedback
- Optional: Implement additional shadcn blocks
shadcn のデザイン原則(重要)
基本原則
1. すべてのテーマ設定に CSS 変数を使用する
- 色、余白、タイポグラフィをハードコードしてはいけません
- すべてのデザイントークンを
globals.cssの CSS 変数として定義します - これらの変数を参照する Tailwind クラスを使用します
2. 標準コンポーネントのみを使用する
- shadcn/ui コンポーネントをそのまま使用します
- 変更ではなく、組み合わせによって拡張します
- shadcn にない場合は、shadcn のプリミティブを使って構築します
3. 一貫したデザイン言語
- shadcn のデザインパターンに従います
- 意味的なバリアント(default、outline、destructive、ghost、link、secondary)を使用します
- 一貫した余白のスケールを維持します
- タイポグラフィの階層は shadcn に従います
4. カスタム UI コンポーネントを作成しない
- カスタムのボタン、入力欄、カードなどを作成しないでください
- shadcn コンポーネントを使用するか、shadcn のプリミティブを使って構築します
- 例外:ビジネスロジックコンポーネント(UI プリミティブではないもの)
5. アクセシビリティを最優先する
- shadcn は Radix UI を使用しているため、デフォルトでアクセシブルです
- アクセシビリティ機能を上書きしないでください
- キーボード操作とスクリーンリーダーでテストします
避けるべきアンチパターン
以下は絶対に行わないでください:
❌ 色のハードコード
// WRONG
<div style={{ backgroundColor: '#3b82f6' }}>
// RIGHT
<div className="bg-primary">
❌ 余白のハードコード
// WRONG
<div style={{ padding: '20px', margin: '10px' }}>
// RIGHT
<div className="p-5 m-2.5">
❌ UI プリミティブ用のカスタムスタイル付きコンポーネント
// WRONG
const CustomButton = styled.button`
background: #3b82f6;
padding: 8px 16px;
border-radius: 6px;
`
// RIGHT
import { Button } from '@/components/ui/button'
❌ インラインスタイル
// WRONG
<div style={{ color: 'red', fontSize: '14px' }}>
// RIGHT
<div className="text-destructive text-sm">
❌ フォントのハードコード
// WRONG
<h1 style={{ fontFamily: 'Montserrat' }}>
// RIGHT
<h1 className="font-sans text-4xl font-bold">
❌ 絵文字アイコン(代わりに Lucide React アイコンを使用してください)
// WRONG
<span>❌ Delete</span>
// RIGHT
import { X } from 'lucide-react'
<Button variant="destructive">
<X className="mr-2 h-4 w-4" />
Delete
</Button>
❌ 任意の CSS 値
// WRONG
<div className="text-[#ff0000]">
// RIGHT
<div className="text-destructive">
ベストプラクティス
✅ 意味的な色名を使用する
// Use semantic CSS variable names
bg-background
text-foreground
bg-primary
text-primary-foreground
bg-secondary
text-muted-foreground
border-border
✅ Tailwind の余白スケールを使用する
// Consistent spacing using Tailwind
p-2, p-4, p-6, p-8 // padding
m-2, m-4, m-6, m-8 // margin
gap-2, gap-4 // flex/grid gap
✅ コンポーネントを組み合わせる
// Build complex UIs by composing shadcn components
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
✅ MCP を使って探す
// Before building, ask MCP:
// "What shadcn component should I use for [use case]?"
// "Show me examples of shadcn [component]"
✅ 組み合わせによって拡張する
// Create higher-level components that compose shadcn
export function FeatureCard({ feature }: { feature: Feature }) {
return (
<Card>
<CardHeader>
<CardTitle>{feature.title}</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground">{feature.description}</p>
<Button className="mt-4">Learn More</Button>
</CardContent>
</Card>
)
}
参考ファイル
フレームワーク固有の移行:
コンポーネントとスタイリング:
レスポンシブデザインとアクセシビリティ:
- レスポンシブデザインパターンガイド ⭐ NEW
- アクセシビリティのベストプラクティス(WCAG 2.1) ⭐ NEW
コンポーネントテンプレートの例:
- レスポンシブナビゲーション - モバイル/タブレット/デスクトップ向けのナビゲーションパターン ⭐ NEW
- レスポンシブデータテーブル - モバイルではカード表示、デスクトップではテーブル表示 ⭐ NEW
- レスポンシブダッシュボード - 統計情報とチャートを含むレスポンシブなグリッドレイアウト ⭐ NEW
- 複雑なマルチステップフォーム - フォーム検証、ファイルアップロード、条件付きフィールド ⭐ NEW
- 機能カードの例 - shadcn コンポーネントを組み合わせる基本例
- ユーザープロフィールの例 - アバター、バッジ、レイアウトのパターン
スクリプト:
./scripts/analyze-codebase.py- コードベースの自動分析./scripts/detect-hardcoded-values.sh- アンチパターンの検出./scripts/init-nextjs-shadcn.sh- プロジェクトの初期化./scripts/generate-migration-report.py- 移行レポートの作成
公式ドキュメント:
- shadcn/ui:https://ui.shadcn.com
- Next.js:https://nextjs.org/docs
- Tailwind CSS:https://tailwindcss.com/docs
- Radix UI:https://www.radix-ui.com
- WCAG 2.1 ガイドライン:https://www.w3.org/WAI/WCAG21/quickref/
新規プロジェクトのクイックスタート
新しい Next.js アプリを作成する場合(移行ではない場合):
-
初期化
bash ./scripts/init-nextjs-shadcn.sh my-app -
MCP へのアクセスを確認
npx shadcn@latest mcp init --client claude -
コンポーネントをインストール
- MCP を使って必要なコンポーネントを探します
npx shadcn@latest add [component]でインストールします
-
ベストプラクティスに従って構築
- CSS 変数のみを使用します
- shadcn コンポーネントを組み合わせます
- 上記のデザイン原則に従います
概要
このスキルを使うと、設計原則を厳格に遵守しながら、フロントエンドを Next.js + shadcn/ui に体系的に移行できます。
- 既存のコードベースを自動分析
- 体系的な一括変換(一度に 5~10 個のコンポーネント)
- ハードコードされた値を一切許容しない(CSS 変数のみ)
- shadcn コンポーネントの検索に対応するMCP 統合
- 複数のフレームワークに対応(React、Vue、Angular、vanilla JS)
- 包括的な検証(テスト、アクセシビリティ、パフォーマンス)
結果: shadcn/ui のベストプラクティスに従い、一貫性のあるデザインシステム、完全なダークモード対応、アンチパターンのない、本番環境向けの品質を備えた Next.js アプリケーション。