本文へスキップ

ユースケース: 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 モード)
UITailwind 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 のテクニックを適用する方法がわかります:

  1. ブレインストーミング マイグレーション戦略 — 適切な質問をし、アプローチを提案し、最適な方向を選択
  2. プランの作成 並列作業用 — 明確な依存関係を持つフェーズごとにタスクを分割
  3. 並列サブエージェント による同時実行 — 3つのエージェントが個別のファイルで同時に作業
  4. 2段階コードレビュー による品質保証 — 各フェーズ後の自動 spec レビュー
  5. 検証 による結果の確認 — 次に進む前にビルド + テストがパスすること

ステップバイステップ実践

ステップ 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つのセクションに分けた詳細設計を(ブラウザ上で)続けて説明します:

  1. Project Structure — App Router を使用した新しいディレクトリ構造(app/components/hooks/lib/types/contexts/
  2. Component Mapping — Server vs Client Components の分類。パターン: Thin Server Shell → Fat Client Tree
  3. Routing & Auth Flow/ を AuthGuard でラップ、/login はログイン済みならリダイレクト、next/navigation を使用
  4. Agent Parallelization — 3フェーズ: Foundation → Parallel Features → Integration
  5. 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エージェント、順次 — 先に完了する必要あり)

  1. Task 1: create-next-app で新しい Next.js 16 プロジェクトをスキャフォールド
  2. Task 2: 依存関係と設定の追加(Tailwind、shadcn、Vitest、tsconfig)
  3. Task 3: 変更不要のファイルをコピー(lib/、types/、hooks/、contexts/、components/ui/)
  4. Task 4: app/layout.tsx を作成 — AuthProvider と Toaster を含む Root layout
  5. Task 5: app/globals.css を作成 — src/index.css から CSS を移行

Phase 2: Features(3エージェント並列)

  1. Task 6 — Agent Auth: auth ページを作成(auth-guard.tsxauth-page.tsxlogin-form.tsxregister-form.tsxapp/login/page.tsx
  2. Task 7 — Agent Todo: todo ページを作成(todo-app.tsxheader.tsxfilter-bar.tsxtodo-list.tsxtodo-item.tsxtodo-input.tsxedit-todo-dialog.tsxapp/page.tsx
  3. Task 8 — Agent Test: 8つのテストファイルを __tests__/ に移行、相対 import を @/ エイリアスに更新

Phase 3: Integration(1エージェント、順次)

  1. Task 9: npm run build + npx vitest run を実行、すべての問題を修正
  2. 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つの大きなエージェントに統合します(順次依存するため)。エージェントは以下を実行します:

  1. スキャフォールド: npx create-next-app@latest — TypeScript、Tailwind CSS、App Router
  2. 設定: 依存関係の追加(@dnd-kit/*sonnerdate-fnsshadcn など)、vitest.config.tscomponents.json のセットアップ
  3. ファイルコピー: lib/types/hooks/contexts/components/ui/ — そのままコピー、ファイル先頭に "use client" を追加
  4. レイアウト: metadata、fonts、<AuthProvider><Toaster /> を含む app/layout.tsx を作成
  5. CSS: Tailwind 4 構文で globals.css を移行

Phase 1 完了後(7コミット)、AI は Phase 2 の準備をしながら バックグラウンドで spec reviewer をディスパッチ してコンプライアンスをチェックします。

Phase 1: 完了 — 7コミット、ビルド成功、すべてのファイルが正しい位置に配置

ステップ 3: 3エージェントを並列ディスパッチ(Phase 2)

Phase 1 が完了すると、コントローラーが3つのエージェントを 同時に ディスパッチします:

エージェントタスク所有ファイル
Auth AgentAuth ページ + ルート保護auth-guard、auth-page、login-form、register-form、app/login/page.tsx
Todo AgentTodo ページ + 全コンポーネントtodo-app、header、filter-bar、todo-list、todo-item、todo-input、edit-todo-dialog、app/page.tsx
Test Agent8つのテストファイルを移行__tests__/components/__tests__/contexts/__tests__/hooks/__tests__/lib/

各エージェントは以下を受け取ります:

  • 明確なスコープ: プランからの具体的なファイルリスト
  • Spec リファレンス: コンポーネントの適応方法を把握するためのデザイン仕様へのリンク
  • 制約: スコープ外のファイルを修正しない、各インタラクティブコンポーネントの先頭に "use client" を追加

実際の展開:

  • Auth Agent が最初に完了 — 5ファイル、TypeScript パス、コミット 740e5dd。IDE が todo-list.tsx./todo-item import でエラーを報告 — ただしこれは 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 defineduseThemeuseTodosuseState の初期化子で 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 run39/39 テスト PASS!

実践的な教訓: SPA(Vite)から SSR フレームワーク(Next.js)に移行する場合、初期状態でブラウザ専用 API(windowlocalStoragedocument)を常にガードしてください。これが最も一般的な問題です。

ステップ 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つの質問をします:

  1. Brutal のレベル → 選択: Bold Neo Brutalism(黒3pxボーダー、ハードシャドウ、鮮やかな色)
  2. カラーパレット → 選択: Candy Crush(ピンク/パープル/ブルー — #FF85A1#A855F7#38BDF8
  3. スコープ → 選択: 全体(login と todo ページ両方)
  4. ダークモード → 選択: 両方維持(ライト Neo Brutalism をメインに、ダークは適応版)
  5. フォント → 選択: Space Grotesk(Neo Brutalism で人気のジオメトリックサンセリフ)

AI が3つのアプローチを提案 → CSS-first を選択(CSS 変数 + Tailwind クラスによる変更、コンポーネント構造は維持、テストは引き続きパス)。

Neo Brutalism プラン: 6タスク、4フェーズ

フェーズタスクエージェント説明
1: FoundationTask 11フォント変更、CSS 変数、ユーティリティクラス
2: Base UITask 21button、input、dialog、select、dropdown、popover、sonner、calendar
3: ComponentsTask 3-53 並列Auth (A)、Layout (B)、Items (C)
4: IntegrationTask 61ビルド、テスト、ビジュアルチェック

並列実行

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: Authauth-page、login-form、register-form
Agent B: Layoutheader、filter-bar、todo-list
Agent C: Itemstodo-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/uiBold Neo Brutalism(Candy Crush)
フォントGeistSpace Grotesk
テスト39 パス39 パス(壊れなし)
コミット11(マイグレーション)+ 5(リデザイン)= 16コミット
  • 0テストが壊れた — ロジック100%維持
  • 並列実行により時間が大幅に短縮(マイグレーション Phase 2 で3エージェント + リデザイン Phase 3 で3エージェント)
  • 実際の問題をオンザフライで修正: SSR window ガード、sonner の "use client" ディレクティブ、テストの import パス

重要なポイント

  1. コードを書く前にブレインストームする。 適切な質問(スコープ、アプローチ、制約)をすることで、間違った方向のリファクタリングを避けられます。このケースでは、5つのブレインストーム質問で明確になりました: 「フレームワークマイグレーションのみ、新規スキャフォールド、ロジック維持」。

  2. 詳細なプランは並列実行の前提条件。 プランには以下を明確に示す必要があります: 誰が何をするか、どのファイルか、タスク間の依存関係。ファイル所有権を明確に分けないと、エージェントがコンフリクトします。

  3. 依存関係でフェーズを分け、各フェーズ内で並列化する。 Foundation を先に完了し(スキャフォールド、設定)、その後でフィーチャー用のエージェントを並列ディスパッチします。パターン: Sequential Phases → Parallel Tasks Within Phase。

  4. Spec とプランは自動レビューされる。 AI は spec/plan 作成後にレビュアーエージェントをディスパッチします。レビュアーが実行開始前に問題を発見(オーケストレーターコンポーネントの欠如、テスト import パスの誤り)— コード後の修正よりはるかに安価です。

  5. 実際の問題は必ず発生する。 このケースでは、SSR window is not defined が SPA → SSR フレームワーク移行特有の問題でした。Integration フェーズ(Phase 3)はこれらの問題をキャッチして修正するために存在します。

  6. プロセスは再利用可能。 マイグレーション完了後、Neo Brutalism リデザインもまったく同じプロセスに従います: ブレインストーム → spec → プラン → 並列実行 → 検証。同じパターン、異なるコンテキスト。


まとめ: React/Vite アプリケーションを Next.js 16 に移行し、Neo Brutalism にリデザインする作業を1つのセッションで実行。Superpowers がすべてをオーケストレーション: ブレインストームで戦略を決定、プランでフェーズごとにタスクを分割、並列エージェントが同時に実行、spec レビューが品質を保証、verification gate が完了宣言前に問題をキャッチ。結果: 16コミット、39/39 テストパス、0リグレッション。