ユースケース: Vite → Next.js 16 への並列マイグレーション
これは実際のユースケースで、Claude Code + Superpowers を使用して実行されました。以下の内容は、ブレインストームから完了まで、マイグレーション後の UI リデザインを含むプロセスを記述しています。
React アプリケーションを Vite から Next.js 16 に移行する作業は、1つのエージェントが順次実行するものではありません。Superpowers を使えば、戦略をブレインストームし、詳細なプランを作成し、複数のエージェントを並列にディスパッチできます -- 各エージェントが独自のファイルを所有し、コンフリクトなしで作業します。
背景
プロジェクトはログイン機能付きの Todo App で、React 19 + Vite 7 で作られています。現在のスタックは以下のとおりです:
| 項目 | 詳細 |
|---|---|
| フレームワーク | React 19 + Vite 7(SPA、ルーティングなし) |
| 言語 | TypeScript 5.9(strict モード) |
| UI | Tailwind CSS 4 + shadcn/ui |
| 状態管理 | Context API + useReducer |
| バックエンド | なし — 100% localStorage |
| 認証 | クライアントサイド SHA-256 ハッシュ、localStorage に保存 |
| 機能 | Todo CRUD、ドラッグ&ドロップ、フィルタ、ダークモード、認証 |
| テスト | Vitest + React Testing Library |
目標: すべてを Next.js 16 App Router に移行し、既存のロジック(localStorage、クライアントサイド認証、UI ライブラリ)を維持します。チームには並列で作業できる3-4のエージェントがあります。
重要な要件:
- フレームワークのみ変更、ロジックは変更しない
- 既存のテストはすべてマイグレーション後もパスすること
- 複数のエージェントが異なるファイルで同時に作業できること
学べること
このユースケースを読み終えると、実際のリファクタリング/マイグレーション状況に Superpowers のテクニックを適用する方法がわかります:
- ブレインストーミング マイグレーション戦略 — 適切な質問をし、アプローチを提案し、最適な方向を選択
- プランの作成 並列作業用 — 明確な依存関係を持つフェーズごとにタスクを分割
- 並列サブエージェント による同時実行 — 3つのエージェントが個別のファイルで同時に作業
- 2段階コードレビュー による品質保証 — 各フェーズ後の自動 spec レビュー
- 検証 による結果の確認 — 次に進む前にビルド + テストがパスすること
ステップバイステップ実践
ステップ 0: マイグレーション戦略のブレインストーム
プランを書く前に、戦略を決定するためのブレインストームが必要です。AI とのチャットを開き、以下のように伝えます:
「このプロジェクト全体を NextJS 16 にリファクタリングする必要があります。これはログイン機能付きの Web todo プロジェクトです。チームには並列で作業できる3-4のエージェントがあります。始める前にリファクタリング戦略をブレインストームしましょう。」
AI はブレインストームモード(superpowers:brainstorming スキルを使用)に入り、コードベースを調査してから、1つずつ質問を始めます:
AI: 「このリファクタリングのスコープはどこまでですか?」
- A) フルスタック — 実際のデータベース、API routes、サーバーサイド認証を追加
- B) ハイブリッド — レンダリングに Server Components + App Router、ただし localStorage は維持
- C) フレームワークマイグレーションのみ — Vite から Next.js 16 に移行、ロジックは維持
選択: C) フレームワークマイグレーションのみ — プロジェクト構造とルーティングに集中。
AI: 「ルーティングについて、URL 構造はどうしますか?」
- A) 最小限のルーティング — 2つのルートのみ:
/(todo app)と/login(auth ページ) - B) 構造化ルーティング — 複数のルート:
/login、/register、/todos、/todos/[id]
選択: A) 最小限のルーティング — シンプルで、現状に最も近い。
AI: 「現在の UI ライブラリはそのまま維持しますか、変更しますか?」
選択: すべて維持 — shadcn/ui、@dnd-kit、sonner、date-fns、lucide-react。
AI: 「テストにはどのフレームワークを使いますか?」
- A) Vitest を維持 — Next.js 16 がネイティブサポート
- B) Jest に移行
選択: A) Vitest を維持。
AI: 「デプロイメントについて、特定のターゲットはありますか?」
- A) Vercel — Next.js に最適、ゼロコンフィグ
- B) セルフホスト / Docker
- C) まだ考えていない — マイグレーションに集中
選択: C) まだ考えていない — まずマイグレーションに集中。
十分な情報を収集した後、AI は3つのアプローチを提示します:
## Approach A: 新規スキャフォールド + 段階的マイグレーション(推奨)
新しい Next.js 16 プロジェクトを作成し、各パーツをコピー/適応。
- Pros: クリーンな構造、エージェントの並列分担が容易、最初からプロジェクトが動作
- Cons: 設定のやり直しが必要(shadcn、tailwind)
## Approach B: インプレースマイグレーション
既存のプロジェクト上で直接変換 — Vite を Next.js に置換。
- Pros: git 履歴を維持
- Cons: コンフリクトしやすい、途中でプロジェクトが動作しない、並列タスク分割が困難
## Approach C: Codemods + 自動化
@next/codemod とスクリプトで自動変換。
- Pros: 基本的な部分は高速
- Cons: Vite → Next.js の codemod はない、小規模プロジェクトではオーバーキル
## 推奨
Approach A。プロジェクトは小規模(約15コンポーネント)、新規スキャフォールドの方がインプレースマイグレーションより速い。
3-4エージェントの並列分担が容易。
Approach A を選択。AI がさらに質問: 「ブラウザにダイアグラムとモックアップを表示しましょうか?」 → 同意。AI が ビジュアルコンパニオン(ローカルサーバー)を起動し、アーキテクチャダイアグラムをブラウザ上に直接レンダリングします。
AI は5つのセクションに分けた詳細設計を(ブラウザ上で)続けて説明します:
- Project Structure — App Router を使用した新しいディレクトリ構造(
app/、components/、hooks/、lib/、types/、contexts/) - Component Mapping — Server vs Client Components の分類。パターン: Thin Server Shell → Fat Client Tree
- Routing & Auth Flow —
/を AuthGuard でラップ、/loginはログイン済みならリダイレクト、next/navigationを使用 - Agent Parallelization — 3フェーズ: Foundation → Parallel Features → Integration
- Migration Details — 追加/削除するパッケージ、設定変更、import パス
AI はデザイン仕様を docs/superpowers/specs/ に保存し、自動 spec reviewer をディスパッチします。レビュアーが3件の問題を発見(todo-app.tsx オーケストレーターの欠如、テストディレクトリ構造、Toaster の配置)→ AI が修正 → レビュアーが2回目で承認。
Superpowers メモ: デザイン仕様は
docs/superpowers/specs/に保存され、プラン作成前にレビューされます。詳しくは ブレインストーミング をご覧ください。
ステップ 1: Superpowers がタスク分割プランを作成する
コードが1行も書かれる前に、AI が詳細なプランを作成します(superpowers:writing-plans スキルを使用)。これがコアの原則です: プランなくして実行なし。
AI がすべてのソースファイルを読み、3フェーズ10タスクのプランを作成します:
Phase 1: Foundation(1エージェント、順次 — 先に完了する必要あり)
- Task 1:
create-next-appで新しい Next.js 16 プロジェクトをスキャフォールド - Task 2: 依存関係と設定の追加(Tailwind、shadcn、Vitest、tsconfig)
- Task 3: 変更不要のファイルをコピー(lib/、types/、hooks/、contexts/、components/ui/)
- Task 4:
app/layout.tsxを作成 — AuthProvider と Toaster を含む Root layout - Task 5:
app/globals.cssを作成 —src/index.cssから CSS を移行
Phase 2: Features(3エージェント並列)
- Task 6 — Agent Auth: auth ページを作成(
auth-guard.tsx、auth-page.tsx、login-form.tsx、register-form.tsx、app/login/page.tsx) - Task 7 — Agent Todo: todo ページを作成(
todo-app.tsx、header.tsx、filter-bar.tsx、todo-list.tsx、todo-item.tsx、todo-input.tsx、edit-todo-dialog.tsx、app/page.tsx) - Task 8 — Agent Test: 8つのテストファイルを
__tests__/に移行、相対 import を@/エイリアスに更新
Phase 3: Integration(1エージェント、順次)
- Task 9:
npm run build+npx vitest runを実行、すべての問題を修正 - Task 10: クリーンアップと最終コミット
依存関係グラフ:
Phase 1 (Tasks 1-5) ─── sequential ───→ Phase 2 (Tasks 6-8) ─── parallel ───→ Phase 3 (Tasks 9-10)
├─ Agent Auth (Task 6)
├─ Agent Todo (Task 7)
└─ Agent Test (Task 8)
並列実行の前提条件: 各エージェントが独自のファイルを所有し、重複がないこと。Agent Auth は auth 関連ファイルのみ、Agent Todo は todo 関連ファイルのみ、Agent Test はテストファイルのみを修正します。
AI が自動 plan reviewer をディスパッチ → レビュアーが1件の問題を発見(テストファイルの相対 import が移動時に壊れる)→ AI が import マッピングテーブルで修正 → レビュアーが承認。
AI が実行方法を質問します:
「2つの実行方法: 1) Subagent-Driven(推奨)— エージェントをディスパッチし、タスク間でレビュー。2) Inline Execution — セッション内で直接実行。どちらを選びますか?」
選択: 1) Subagent-Driven — 3-4エージェントの並列要件に適合。
ステップ 2: Phase 1 — Foundation
AI は5つの foundation タスクを1つの大きなエージェントに統合します(順次依存するため)。エージェントは以下を実行します:
- スキャフォールド:
npx create-next-app@latest— TypeScript、Tailwind CSS、App Router - 設定: 依存関係の追加(
@dnd-kit/*、sonner、date-fns、shadcnなど)、vitest.config.ts、components.jsonのセットアップ - ファイルコピー:
lib/、types/、hooks/、contexts/、components/ui/— そのままコピー、ファイル先頭に"use client"を追加 - レイアウト: metadata、fonts、
<AuthProvider>、<Toaster />を含むapp/layout.tsxを作成 - CSS: Tailwind 4 構文で
globals.cssを移行
Phase 1 完了後(7コミット)、AI は Phase 2 の準備をしながら バックグラウンドで spec reviewer をディスパッチ してコンプライアンスをチェックします。
Phase 1: 完了 — 7コミット、ビルド成功、すべてのファイルが正しい位置に配置
ステップ 3: 3エージェントを並列ディスパッチ(Phase 2)
Phase 1 が完了すると、コントローラーが3つのエージェントを 同時に ディスパッチします:
| エージェント | タスク | 所有ファイル |
|---|---|---|
| Auth Agent | Auth ページ + ルート保護 | auth-guard、auth-page、login-form、register-form、app/login/page.tsx |
| Todo Agent | Todo ページ + 全コンポーネント | todo-app、header、filter-bar、todo-list、todo-item、todo-input、edit-todo-dialog、app/page.tsx |
| Test Agent | 8つのテストファイルを移行 | __tests__/components/、__tests__/contexts/、__tests__/hooks/、__tests__/lib/ |
各エージェントは以下を受け取ります:
- 明確なスコープ: プランからの具体的なファイルリスト
- Spec リファレンス: コンポーネントの適応方法を把握するためのデザイン仕様へのリンク
- 制約: スコープ外のファイルを修正しない、各インタラクティブコンポーネントの先頭に
"use client"を追加
実際の展開:
-
Auth Agent が最初に完了 — 5ファイル、TypeScript パス、コミット
740e5dd。IDE がtodo-list.tsxの./todo-itemimport でエラーを報告 — ただしこれは Todo Agent がファイルを作成中のためで、完了すれば自動解決します。 -
Todo Agent が次に完了 — 8ファイル、TypeScript パス、コミット
55a8988。新しいオーケストレーターとしてtodo-app.tsxを作成(App.tsxからロジックを抽出)、<AuthGuard>でラップ。 -
Test Agent が最後に完了 — 8つのテストファイルを作成完了、ただし権限の問題でテスト実行/コミットができず。コントローラーが
npx vitest runを実行しコミットを代行 — 39/39 テスト PASS。
Auth Agent: 完了 — 5ファイル、TypeScript パス
Todo Agent: 完了 — 8ファイル、TypeScript パス
Test Agent: 完了 — 8テストファイル移行済み、39/39 テストパス
ステップ 4: Phase 3 — インテグレーション検証
3つのエージェントすべてが完了後、コントローラーがインテグレーションを実行します:
npm run build
ビルド失敗! エラー: window is not defined — useTheme と useTodos が useState の初期化子で window/localStorage にアクセスしているために発生。これは Next.js 特有の SSR プリレンダリングの問題です(Vite にはありません)。
修正: フックに SSR ガードを追加:
// hooks/use-theme.ts
const [theme, setTheme] = useState<'light' | 'dark'>(() => {
if (typeof window === 'undefined') return 'light' // SSR ガード
const saved = loadTheme()
if (saved) return saved
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
})
// hooks/use-todos.ts
const [todos, dispatch] = useReducer(todoReducer, [], () => {
if (typeof window === 'undefined') return [] // SSR ガード
return loadTodos()
})
再実行: npm run build → ビルド成功! npx vitest run → 39/39 テスト PASS!
実践的な教訓: SPA(Vite)から SSR フレームワーク(Next.js)に移行する場合、初期状態でブラウザ専用 API(
window、localStorage、document)を常にガードしてください。これが最も一般的な問題です。
ステップ 5: Verification Gate
マイグレーション完了を宣言する前に:
1. 実行
npm run build && npx vitest run
2. 読解
✓ Compiled successfully
Routes:
○ / — Static
○ /login — Static
○ /_not-found — Static
Test Suites: 8 passed, 8 total
Tests: 39 passed, 39 total
3. 確認
| メトリクス | 結果 |
|---|---|
| ビルド | next build 成功 |
| テスト | 39/39 パス(8テストファイル) |
| ルート | /(todo app)、/login(auth) |
| コミット | 11のクリーンコミット |
4. GIT HISTORY
050db4f chore: add .superpowers/ to .gitignore
edfa697 fix: guard window/localStorage access for SSR prerendering
97542b0 test: migrate all test files to __tests__/ directory
55a8988 feat: add todo page with all components
740e5dd feat: add auth pages with client-side route protection
76abbff fix: add "use client" to sonner component, accept Next.js tsconfig updates
e78ce06 feat: add root layout with AuthProvider and Toaster
65ff090 chore: copy unchanged source files
451ad1d chore: configure TypeScript, Vitest, and shadcn
a50080f chore: add project dependencies
bb0f5c5 chore: scaffold Next.js 16 project
ボーナス: Neo Brutalism リデザイン(続きの並列作業)
マイグレーションが完了し検証された後、チームは新しい要件に進みます: UI 全体を Neo Brutalism スタイルにリデザインする。Superpowers のプロセスがまったく同じように繰り返されます:
Neo Brutalism のブレインストーム
AI が5つの質問をします:
- Brutal のレベル → 選択: Bold Neo Brutalism(黒3pxボーダー、ハードシャドウ、鮮やかな色)
- カラーパレット → 選択: Candy Crush(ピンク/パープル/ブルー —
#FF85A1、#A855F7、#38BDF8) - スコープ → 選択: 全体(login と todo ページ両方)
- ダークモード → 選択: 両方維持(ライト Neo Brutalism をメインに、ダークは適応版)
- フォント → 選択: Space Grotesk(Neo Brutalism で人気のジオメトリックサンセリフ)
AI が3つのアプローチを提案 → CSS-first を選択(CSS 変数 + Tailwind クラスによる変更、コンポーネント構造は維持、テストは引き続きパス)。
Neo Brutalism プラン: 6タスク、4フェーズ
| フェーズ | タスク | エージェント | 説明 |
|---|---|---|---|
| 1: Foundation | Task 1 | 1 | フォント変更、CSS 変数、ユーティリティクラス |
| 2: Base UI | Task 2 | 1 | button、input、dialog、select、dropdown、popover、sonner、calendar |
| 3: Components | Task 3-5 | 3 並列 | Auth (A)、Layout (B)、Items (C) |
| 4: Integration | Task 6 | 1 | ビルド、テスト、ビジュアルチェック |
並列実行
Phase 1+2(依存関係があるため1エージェントに統合):
- フォント Geist → Space Grotesk に変更
- すべての CSS 変数を置換(colors OKLch → Candy Crush パレット)
- ユーティリティクラスを追加:
.brutal-shadow、.brutal-border、hover/active transforms - shadcn/ui ベースコンポーネントを更新(button、input、dialog、select...)
Phase 3 — 3エージェント並列:
| エージェント | ファイル |
|---|---|
| Agent A: Auth | auth-page、login-form、register-form |
| Agent B: Layout | header、filter-bar、todo-list |
| Agent C: Items | todo-item、todo-input、edit-todo-dialog |
Phase 4: ビルド + テスト → 39/39 テストが引き続きパス(スタイリングのみの変更でロジックに触れていないため)。
Neo Brutalism の結果
- フォント: Geist → Space Grotesk Variable
- カラー: OKLch neutral → Candy Crush(pink/purple/blue)
- ボーダー: 1px transparent → 3px solid black
- シャドウ: ソフトブラー → ハード4pxオフセット(ブラーなし)
- ホバー/アクティブ: リフトアップ / プッシュダウン transforms
- ダークモード: ネイビー背景、カラーボーダー、ボールドカラーを維持
- リデザイン全体で 5コミット
総合結果
マイグレーションとリデザインの両方を完了した後:
| メトリクス | 変更前 | 変更後 |
|---|---|---|
| フレームワーク | React 19 + Vite 7(SPA) | Next.js 16 App Router |
| ルーティング | なし(toggle state) | / と /login(next/navigation) |
| コンポーネント | すべてクライアントサイド | Server shells + Client components |
| スタイル | デフォルト shadcn/ui | Bold Neo Brutalism(Candy Crush) |
| フォント | Geist | Space Grotesk |
| テスト | 39 パス | 39 パス(壊れなし) |
| コミット | — | 11(マイグレーション)+ 5(リデザイン)= 16コミット |
- 0テストが壊れた — ロジック100%維持
- 並列実行により時間が大幅に短縮(マイグレーション Phase 2 で3エージェント + リデザイン Phase 3 で3エージェント)
- 実際の問題をオンザフライで修正: SSR
windowガード、sonner の"use client"ディレクティブ、テストの import パス
重要なポイント
-
コードを書く前にブレインストームする。 適切な質問(スコープ、アプローチ、制約)をすることで、間違った方向のリファクタリングを避けられます。このケースでは、5つのブレインストーム質問で明確になりました: 「フレームワークマイグレーションのみ、新規スキャフォールド、ロジック維持」。
-
詳細なプランは並列実行の前提条件。 プランには以下を明確に示す必要があります: 誰が何をするか、どのファイルか、タスク間の依存関係。ファイル所有権を明確に分けないと、エージェントがコンフリクトします。
-
依存関係でフェーズを分け、各フェーズ内で並列化する。 Foundation を先に完了し(スキャフォールド、設定)、その後でフィーチャー用のエージェントを並列ディスパッチします。パターン: Sequential Phases → Parallel Tasks Within Phase。
-
Spec とプランは自動レビューされる。 AI は spec/plan 作成後にレビュアーエージェントをディスパッチします。レビュアーが実行開始前に問題を発見(オーケストレーターコンポーネントの欠如、テスト import パスの誤り)— コード後の修正よりはるかに安価です。
-
実際の問題は必ず発生する。 このケースでは、SSR
window is not definedが SPA → SSR フレームワーク移行特有の問題でした。Integration フェーズ(Phase 3)はこれらの問題をキャッチして修正するために存在します。 -
プロセスは再利用可能。 マイグレーション完了後、Neo Brutalism リデザインもまったく同じプロセスに従います: ブレインストーム → spec → プラン → 並列実行 → 検証。同じパターン、異なるコンテキスト。
まとめ: React/Vite アプリケーションを Next.js 16 に移行し、Neo Brutalism にリデザインする作業を1つのセッションで実行。Superpowers がすべてをオーケストレーション: ブレインストームで戦略を決定、プランでフェーズごとにタスクを分割、並列エージェントが同時に実行、spec レビューが品質を保証、verification gate が完了宣言前に問題をキャッチ。結果: 16コミット、39/39 テストパス、0リグレッション。