本文へスキップ

ユースケース: ソロ開発者が Authentication 機能を構築する

一人で作業する開発者でも、Superpowers のプロセスに従うだけで、完全で安全な、十分なテストカバレッジを持つ authentication 機能を構築できます。


背景

あなたはソロ開発者として Todo App プロジェクトに取り組んでいます。プロジェクトには Todo の CRUD、フィルタ、ドラッグ&ドロップ、ダーク/ライトテーマなどの機能が揃っていますが、authentication システムがまだありません。アプリを開けば誰でもすべての Todo が見えてしまいます。新しい要件は以下のとおりです:

  • ユーザー登録(register)の追加
  • メール + パスワードによるログイン(login)の追加
  • アプリへのアクセス保護(login gate)-- ログインしないとアクセスできない
  • 機能全体のテストを記述

プロジェクトには auth システムがありません。コードをレビューしてくれる人もいません。最初から最後まで一人で作業します。

技術スタック:

  • React 19 + TypeScript + Vite
  • Tailwind CSS + shadcn/ui
  • localStorage(バックエンドなし)
  • Vitest + Testing Library(テスト)
  • Web Crypto API(SHA-256 パスワードハッシュ)

学べること

このチュートリアルでは、Superpowers の5つのコアスキルを実践します:

  1. Brainstorming & Design -- コードを書く前に設計する
  2. Writing Plans -- 作業を明確なタスクに分割する
  3. TDD -- テストを先に書き、実装は後から
  4. 実行 & サブエージェント -- 並列ディスパッチで速度を向上
  5. Debugging & Verification -- 実際の証拠で結果を検証する

最終目標: 39のテストケースがすべてパスし、完全に規律あるプロセスで構築された authentication システムを完成させます。


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

ステップ 1: Auth の設計をブレインストームする

コードを1行も書く前に、ブレインストームから始めます。brainstorming スキルを呼び出します:

/superpowers:brainstorming「Todo プロジェクトに authentication を追加する必要があります。コードを書く前にブレインストームしましょう。」

AI はまずコードベースを調査し、現在の技術スタック(React 19、TypeScript、Vite、Tailwind、shadcn/ui、localStorage)を把握してから、1つずつ質問を始めます:

質問 1: 「authentication は何のために必要ですか?」

  • A) アプリへのアクセス保護のみ(login gate)-- データは localStorage に保持、同じブラウザの各ユーザーが同じデータを参照
  • B) ユーザーごとに個別のデータ -- Todo をユーザーごとに保存するバックエンド/データベースが必要
  • C) 学習目的でログイン/登録フローをデモするだけ

選択: A) Login gate -- アクセス保護のみ、データは localStorage のまま。

質問 2: 「どのログイン方法を使いたいですか?」

  • A) メール + パスワード(ログイン/登録フォームを自作)
  • B) ソーシャルログイン(Google, GitHub...)-- Firebase Auth、Supabase Auth、Auth0 を使用
  • C) 両方

選択: A) メール + パスワード -- 自作、外部依存関係なし。

質問 3: 「Register(新規アカウント登録)は必要ですか?」

  • A) Register + Login 両方必要 -- ユーザーが新規アカウントを作成し、localStorage に保存
  • B) Login のみ -- モック/ハードコードされたアカウントを使用

選択: A) Register + Login 両方必要。

質問 4: 「パスワードを忘れた場合の機能は必要ですか?」

  • A) はい -- パスワードリセットフォームを表示(モック)
  • B) 不要 -- シンプルに保つ

選択: B) 不要 -- Login + Register のみでシンプルに。

質問 5: 「UI について、Login/Register ページはどのようなデザインにしますか?」

  • A) 別ページ(フルページ)-- 未ログイン時はログインページにリダイレクト
  • B) モーダル/ダイアログ -- 現在のアプリの上にオーバーレイ表示
  • C) 提案をお任せ

選択: A) 別ページ。

十分な情報を収集した後、AI は3つのアプローチを提示します:

## Approach A: React Context + localStorage(推奨)
- AuthContext でログイン状態を管理
- ユーザーを localStorage に保存(メール + Web Crypto API によるハッシュ化パスワード)
- シンプルなラッパーコンポーネントによる Protected route
- Login/Register はフルページ、認証済みの場合のみ App をレンダリング
- Pros: シンプル、依存関係を追加しない、現在のアーキテクチャに適合
- Cons: 本格的なルーティングなし(条件付きレンダリングのみ)

## Approach B: React Router + Context
- react-router-dom を追加して本格的なルーティング(/login, /register, /)
- Pros: URL ベースのナビゲーション、後でページを追加しやすい
- Cons: 新しい依存関係が増え、シンプルなアプリには複雑

## Approach C: TanStack Router + Context
- React 向けの型安全なルーティング
- Pros: 型安全、モダン
- Cons: 現在のスコープにはオーバーキル

## 推奨
Approach A。現在のプロジェクトはシングルページアプリで、ルーティングがありません。
2ページ(login + app)のためだけにルーターを追加するのは過剰です。
AuthContext による条件付きレンダリングで十分で、プロジェクトをシンプルに保てます。

Approach A に同意します。AI は各パートの詳細設計を続けて説明します:

パート 1 -- Architecture & Data Model:

User type:
  - id: string (crypto.randomUUID)
  - email: string
  - passwordHash: string (SHA-256 via Web Crypto API)
  - createdAt: string

AuthContext provides:
  - user: User | null
  - isAuthenticated: boolean
  - isLoading: boolean
  - login(email, password) → success/error
  - register(email, password) → success/error
  - logout()

localStorage keys:
  - todo-app-users — 登録済みユーザーの配列
  - todo-app-session — 現在のセッションのユーザー ID
  - todo-app-todos — そのまま維持(すべてのユーザー間で共有)

パート 2 -- Component Structure:

<StrictMode>
  <AuthProvider>
    <App>
      ├── isLoading = true → Loading indicator
      │
      ├── isAuthenticated = false → <AuthPage>
      │     ├── <LoginForm />
      │     └── <RegisterForm />
      │
      └── isAuthenticated = true → <TodoApp>
            ├── <Header> (+ logout ボタン、ユーザーメール)
            ├── <FilterBar>
            ├── <TodoInput>
            ├── <TodoList>
            └── <EditTodoDialog>
    </App>
  </AuthProvider>
</StrictMode>

パート 3 -- UI Design: AI はビジュアルコンパニオンを通じてブラウザ上に直接2つのモックアップを表示します: Centered Card と Split Layout。Split Layout を選択 -- 画面を二分割し、左側にブランディング、右側にフォーム。

パート 4 -- Validation & Error Handling:

  • Register: メール形式、メール重複、パスワード6-128文字、確認パスワードの一致
  • Login: メール/パスワードが空でないこと、間違いの場合はトーストエラーを表示(既存の Sonner を使用)
  • Session: アプリマウント時にチェック、ユーザー ID が無効な場合は自動ログアウト

パート 5 -- Testing Strategy: Vitest + Testing Library、ストレージテスト用に localStorage をモック。

AI はデザイン仕様を docs/superpowers/specs/2026-03-18-authentication-design.md に書き出し、自動 spec レビューを3ラウンド 実行 -- 7件の問題を発見し(ローディング状態の欠如、パスワード最大長の欠如、古いセッションの処理の欠如など)、プラン作成に進む前にすべて修正しました。

Superpowers メモ: 自動 spec レビューはプロセスの重要な部分です。AI は承認前に code-reviewer エージェントをディスパッチして spec をレビューします。これにより spec の漏れを防ぎます。詳しくは Brainstorming をご覧ください。


ステップ 2: Superpowers が詳細なプランを作成する

承認済みのデザイン仕様に基づき、AI は writing-plans スキルを呼び出し、作業を8つのタスクに分割します:

## Plan: Authentication Implementation

### Task 1: Hash Utility
- File: src/lib/hash.ts, src/lib/hash.test.ts
- Web Crypto API による SHA-256 ハッシュ
- Verification: npx vitest run src/lib/hash.test.ts

### Task 2: Auth Storage
- File: src/lib/auth-storage.ts, src/lib/auth-storage.test.ts
- localStorage でのユーザー CRUD + セッション管理
- Verification: npx vitest run src/lib/auth-storage.test.ts

### Task 3: Auth Context
- File: src/contexts/auth-context.tsx, src/contexts/auth-context.test.tsx
- AuthProvider + useAuth フック
- Login, register, logout, session restore, isLoading, stale session
- Verification: npx vitest run src/contexts/auth-context.test.tsx

### Task 4: Login Form
- File: src/components/login-form.tsx, src/components/login-form.test.tsx
- フォームバリデーション、送信、エラー表示
- Verification: npx vitest run src/components/login-form.test.tsx

### Task 5: Register Form
- File: src/components/register-form.tsx, src/components/register-form.test.tsx
- バリデーション、メール重複、パスワード長すぎ、送信
- Verification: npx vitest run src/components/register-form.test.tsx

### Task 6: Auth Page
- File: src/components/auth-page.tsx
- Split layout コンテナ、login/register の切り替え
- 個別テスト不要(フォームテスト + auth-context テストでカバー)

### Task 7: Wire Up
- 修正: src/main.tsx, src/App.tsx, src/components/header.tsx
- App を AuthProvider でラップ、条件付きレンダリング、ログアウトボタン
- Verification: npx tsc --noEmit && npx vitest run

### Task 8: Smoke Test
- フルテストスイート + TypeScript チェックを実行
- Verification: npx tsc --noEmit && npx vitest run

各タスクには具体的なファイル、具体的な検証コマンド、プラン内に詳細なテストコードが含まれています。

プランも 2ラウンドの自動レビュー を受け -- 問題を発見し(テスト環境用の crypto.subtle ポリフィルの欠如、stale session テストケースの欠如、password > 128 chars テストの欠如など)、すべて修正しました。

Superpowers メモ: 実際のプランには各テストファイルと各実装ファイルの完全なコードが含まれ、各ステップに - [ ] チェックボックス形式が使われています。詳しくは Writing Plans をご覧ください。

AI が質問します:

「プランは8タスクで完成しました。Subagent-Driven(並列)と Inline Execution(順次)のどちらで実行しますか?」

選択: Subagent-Driven -- 複数のエージェントを並列にディスパッチして速度を向上。


ステップ 3: Subagent-Driven Development による実装

AI は subagent-driven-development スキルを使用してプランを実行します。各タスクを順番に行う代わりに、AI はタスク間の依存関係を分析し、可能な場合は並列でディスパッチします。

Batch 1: Task 1 + Task 2(並列)

Task 1(Hash Utility)と Task 2(Auth Storage)は互いに依存しないため、2つの別々のエージェントに並列でディスパッチされます:

エージェントタスクテストケース結果
Agent 1Hash Utility (hash.ts + hash.test.ts)3テスト: hash consistency, different inputs → different hashes, returns hex string3/3 PASS
Agent 2Auth Storage (auth-storage.ts + auth-storage.test.ts)6テスト: get/save users, add user, find by email, session CRUD, user validation6/6 PASS

両方のエージェントが完了し、AI はテストを検証してコミットします:

git commit -m "feat: add SHA-256 password hashing utility"
git commit -m "feat: add auth storage with user and session management"

Batch 2: Task 3 + Task 4/5(並列)

Task 3(Auth Context)は Task 1+2 が必要ですが、Task 4(Login Form)と Task 5(Register Form)は props インターフェースのみ必要なので、並列実行が可能です:

エージェントタスクテストケース結果
Agent 3Auth Context (auth-context.tsx + test)6テスト: initial state, register + auto-login, login after register, session restore, logout, stale session cleanup6/6 PASS
Agent 4Login + Register Forms12テスト: validation, submit, error display, duplicate email, password too long12/12 PASS

検証後のコミット:

git commit -m "feat: add AuthContext with login, register, session management"
git commit -m "feat: add login and register form components"

Batch 3: Task 6 + Task 7(順次、インライン)

Task 6(Auth Page)と Task 7(Wire Up)は小さく、互いに依存するため、AI が直接実装します:

  • auth-page.tsx を作成 -- split layout コンテナ
  • main.tsx を修正 -- App を <AuthProvider> でラップ
  • App.tsx を修正 -- AuthPage / TodoApp の条件付きレンダリング + ローディング状態
  • header.tsx を修正 -- ユーザーメール + ログアウトボタンを追加
git commit -m "feat: add AuthPage with split layout"
git commit -m "feat: wire up authentication — AuthProvider, conditional render, header logout"

各タスクでの TDD プロセス: 各エージェントはサイクルに従います: テストを先に記述(RED)→ 最小限のコードを実装(GREEN)→ テストの PASS を確認 → コミット。詳しくは TDD をご覧ください。


ステップ 4: Verification -- 全体の検証

プランの8タスクすべてが完了しました。Task 8: Smoke Test -- フル検証を実行します。

TypeScript チェック

npx tsc --noEmit
# (No output) — クリーン、エラーなし

フルテストスイート

npx vitest run
✓ src/lib/hash.test.ts (3 tests)
✓ src/lib/auth-storage.test.ts (6 tests)
✓ src/contexts/auth-context.test.tsx (6 tests)
✓ src/components/login-form.test.tsx (5 tests)
✓ src/components/register-form.test.tsx (7 tests)
  ... (プロジェクトの他のテストファイル)

Test Files  8 passed
Tests       39 passed

Git Log -- 7つのクリーンコミット

6b92624 feat: wire up authentication — AuthProvider, conditional render, header logout
37d68f1 feat: add AuthPage with split layout
...     feat: add login and register form components
...     feat: add AuthContext with login, register, session management
...     feat: add auth storage with user and session management
878af65 feat: add SHA-256 password hashing utility
cc6e2f9 initial: todo app before authentication

39/39 テスト PASS。TypeScript クリーン。7コミット。 これは実際の証拠に基づく正当な宣言です。


結果

プロセス全体を完了した後、以下のものが得られます:

完全な Authentication 機能:

  • Login ページ -- メール + パスワードでログイン
  • Register ページ -- 完全なバリデーション付きで新規アカウント登録
  • Login gate -- ログインしないとアプリにアクセスできない
  • Logout -- ヘッダーにログアウトボタン、ユーザーメールを表示
  • Session persistence -- ページリロードしてもログイン状態を維持

39のテストケースが100%パス:

  • ユーティリティ層: ハッシュ関数、localStorage CRUD
  • Context 層: login/register フロー、session restore、stale session cleanup
  • UI 層: フォームバリデーション、エラー表示、送信処理
  • エッジケース: メール重複、パスワードが長すぎる(>128文字)、無効なセッション

新しいファイル構造:

src/
  contexts/
    auth-context.tsx          ← AuthProvider + useAuth フック
  components/
    auth-page.tsx             ← Split layout コンテナ
    login-form.tsx            ← ログインフォーム
    register-form.tsx         ← 登録フォーム
  lib/
    hash.ts                   ← SHA-256 ヘルパー
    auth-storage.ts           ← localStorage でのユーザー CRUD + セッション

修正ファイル:
  src/main.tsx                ← App を AuthProvider でラップ
  src/App.tsx                 ← auth/todo の条件付きレンダリング + ローディング状態
  src/components/header.tsx   ← メール + ログアウトボタンを追加

重要なポイント

1. ソロ開発者にもプロセスは必要

コードをレビューしてくれる人がいない場合、Superpowers のプロセスは「仮想の同僚」の役割を果たします。ブレインストームはコードを書く前に十分に考えることを強制します。TDD は実装前にテストを書くことを強制します。Verification はすべてが動作することを証明してから完了を宣言することを強制します。

プロセスがないと、ソロ開発者は罠にはまりやすくなります: 気ままにコードを書き、テストがなく、検証せずに「完了」と宣言してしまいます。

2. 事前のブレインストームがオーバーエンジニアリングを防ぐ

ブレインストームのステップで、AI は React Router と TanStack Router も提案しました。しかし、最初から要件を明確にしていたため(login gate、シングルページアプリ、バックエンドなし)、最もシンプルな方法を選択しました: React Context + localStorage + 条件付きレンダリング。

ブレインストームがなければ、多くの開発者は「念のため」ルーター、バックエンド、データベースを自動的に追加してしまいます。結果として、まだ必要のない機能に3倍の時間を費やすことになります。

3. 自動 spec レビューが漏れを発見する

3ラウンドの spec レビューにより、見落とす可能性のある7件の問題が発見されました: ローディング状態の欠如(リロード時に AuthPage がフラッシュする)、パスワード最大長の欠如(DoS リスク)、古いセッション処理の欠如など。これらの漏れはコードを1行も書く前に修正されました。

4. Subagent-Driven Development が大幅な高速化を実現

8タスクを順次実行する代わりに、AI は並列でディスパッチします: Task 1+2 を同時に、Task 3 + Task 4/5 を同時に。並列化により総実装時間が大幅に短縮されました。

5. 詳細なプランが道を見失うことを防ぐ

8つの明確なタスクがあり、各タスクにはプラン内にコードが用意されているため、次のタスクが何かを常に把握できます。「次に何をすればいいか」と考え込む瞬間はありません。

ソロ開発者にとって、これは特に重要です。一人で作業していると、気が散ったりプロジェクトの各部分を行き来したりしがちです。

6. 39のテストケースが「自動レビュアー」として機能する

各テストケースは明確なアサーションです。コードを変更する時 -- リファクタリング、新機能追加、バグ修正 -- 何かが壊れたらすぐにわかります。39のテストは数秒で実行されます。どんな手動テストよりも速いです。

7. Verification gate が「実際には未完了なのに完了宣言」を防ぐ

何回テストを実行せずに「完了」と言ったことがありますか?何回 AI がアウトプットを見せずに「実装完了」と言いましたか?

最後の Smoke Test -- TypeScript クリーン + 39/39 テストパス -- は誤った宣言の可能性を完全に排除します。ターミナルに実際の証拠がある場合にのみ「完了」と言えます。


ソロ開発者であることは、規律なく作業することを意味しません。 Superpowers は、大規模チームでさえ尊重すべきプロセスを提供します: コードを書く前にブレインストーム、作業前にプランを立て、実装前にテストを書き、承認前に自動レビューし、宣言前に検証する。良いプロセスを持つ一人の人間は、プロセスを持たない人に常に勝ちます -- 経験の多寡に関わらず。