🐡

文字通りの「0」から Claude Code でWebアプリを作る

に公開

はじめに

最近「Claude Codeがやばい!」という話しか聞かないので、以前からやりたかった「購読しているサブスクリプションを可視化するWebアプリケーション」を Next.js + Typescript で作らせてみました。
自分は Next.js も Typescript も、なんなら Claude Code すらほぼ初めて触りましたが、なんと わずか1日でデプロイまでできてしまいました! かなりの衝撃だったのでとりあえず記事にしてみた次第です。

成果

はじめに成果を簡潔に紹介しておくと

# やりたいこと
- 個人で購読しているサブスクリプションを可視化するアプリケーションを作りたい
- 実装したい機能としては
	- 年間いくらかかっているかの可視化
	- 有効に使えているかどうかのラベル付け
	- 複数プランがあるサービスでよりお得なプランの提案

というメモのみをInputとし、ほぼClaude CodeのみでWebアプリケーションの開発に成功しました! しかもこのアイデアを思いついてからアプリのデプロイが完了するまでにかかった時間は 1日未満 でした!

  • Next, Typescriptはほぼ初心者
  • Claude Codeは一昨日から使い始めた

という状況も加味すると、この速さは驚異的ではないでしょうか...

ソースコードは下記で公開しています。

どうやって「0」から作ったの?

今回は 「Claude Codeに与える指示文もClaude Codeで事前に作成しておく」 というアプローチを試してみました。Claude Code に関する知識も「0」からなので、下手に自分の言葉で指示を出すよりも、はじめからすべての指示書を作ったほうがよいのではないか? というアイデアでした。
思いついたらとりあえずやってみろの精神です。

実際の作業内容

1. Claude Code のベストプラクティスを作成する

Claude Codeに関する記事を集め、それらの記事から「Claude Codeによるシステム開発のベストプラクティス」をClaude Codeで生成させました。冗談ではなく大真面目です。
記事の収集には obsidian web clipper を使用しました。Web記事を簡単にローカルに持ってこれるのでClaude Codeですぐつかえるのがいいですね。(obsidian + claude code によるナレッジ管理もかなり熱いと思います)
ベストプラクティスの生成はだいたい以下のような指示で作成しました。

> LiteratureディレクトリにClaude Codeに関する資料を格納しています。
これらの資料を要約し、「Claude Codeによるシステム開発ベストプラクティス」を生成してください。
参考にした資料は、もとのWeb記事のURLを参照記事として記載してください。

以下のようなまとめ記事が生成されました。

Claude Codeによるシステム開発ベストプラクティス

Claude Codeによるシステム開発ベストプラクティス

はじめに

Claude Codeは、Anthropicが開発したagentic codingツールとして、AI主導の開発プロセスを可能にする革新的なシステムです。本記事では、既存の知見やベストプラクティスを統合し、システム開発におけるClaude Codeの効果的な活用方法を包括的に解説します。

1. 基本セットアップと環境構築

1.1 初期環境の構築

# Claude Codeのインストール
npm install -g @anthropic-ai/claude-code

# プロジェクトでClaude Codeを起動
claude

1.2 プロジェクト初期化のベストプラクティス

Claude Codeを新しいプロジェクトで使用する際は、以下の手順を推奨します:

  1. プロジェクト要約の実行

    > summarize this project
    

    このステップにより、Claudeがコードベース、ディレクトリ構成、技術スタックを正確に理解し、後続のタスクの精度が飛躍的に向上します。

  2. CLAUDE.mdファイルの作成

    > /init
    

    プロジェクト固有の情報を自動的にCLAUDE.mdに記録し、セッション間での情報継承を実現します。

1.3 CLAUDE.mdの最適化

CLAUDE.mdは、Claude Codeのメモリとして機能する重要なファイルです。効果的な運用には以下の要素を含めましょう:

# プロジェクト概要
- プロジェクトの目的と概要
- 主要な技術スタック
- アーキテクチャパターン

# 開発ガイドライン
- コーディング規約
- テスト戦略
- セキュリティ要件

# 開発コマンド
- `npm run build` - プロダクションビルド
- `npm run test` - テスト実行
- `npm run lint` - リンティング

# 重要な制約事項
**重要**: セキュリティ上の理由により、機密情報はログに出力しないこと

2. 開発設定とツール設定

2.1 Permission設定の最適化

Claude Codeの効率的な利用には、適切なPermission設定が重要です。

{
  "permissions": {
    "allow": [
      "Edit",
      "MultiEdit", 
      "Write",
      "Bash(git *)",
      "Bash(npm *)",
      "Bash(npx *)",
      "WebFetch(domain:docs.example.com)"
    ],
    "deny": [
      "Bash(rm *)",
      "Bash(sudo *)"
    ]
  }
}

2.2 MCP(Model Context Protocol)サーバーの活用

外部サービスとの連携にはMCPサーバーを活用します:

# AWS Documentation MCPサーバーの追加例
claude mcp add aws-docs \
    --scope project \
    -e AWS_DOCUMENTATION_PARTITION=aws \
    -- uvx awslabs.aws-documentation-mcp-server@latest

2.3 通知設定とユーザビリティ向上

長時間のタスク完了を確認するための通知設定:

claude config set --global preferredNotifChannel terminal_bell

3. 効果的な開発フローとワークフロー

3.1 Explore-Plan-Code-Commitサイクル

Claude Codeにおける最も効果的な開発パターンは、段階的なアプローチです:

Explore(探索)フェーズ

> find the files that handle user authentication
> analyze the current error handling implementation

この段階ではコードを書かせないことが重要です。

Plan(計画)フェーズ

拡張思考モードを活用した設計:

> ultrathink how to implement Role Based User Authentication

Code(実装)フェーズ

計画に基づいた具体的な実装:

> implement the planned authentication system

Commit(コミット)フェーズ

変更内容の確定:

> commit this implementation with appropriate tests

3.2 テスト駆動開発(TDD)の実践

Claude CodeでのTDDアプローチ:

  1. テスト先行実装

    > write comprehensive tests for the user authentication feature, covering edge cases and error scenarios
    
  2. 実装コード作成

    > implement the authentication functionality to pass all the tests without modifying the test code
    

3.3 Git Worktreeを活用した並列開発

複数のアプローチを同時に検証するためのワークフロー:

# 複数のworktreeを作成
git worktree add ../feature-async feature-async
git worktree add ../feature-sync feature-sync

# 各worktreeで独立したClaude Codeセッションを実行
cd ../feature-async && claude
cd ../feature-sync && claude

4. 実践的なTipsとテクニック

4.1 効果的な指示の与え方

具体的で明確な指示

  • ❌ 曖昧:「テストを追加」
  • ✅ 具体的:「foo.py に新しいテストケースを作成、ログアウト状態のエッジケースをカバー」

コンテキスト情報の提供

  • タスクの最終目的
  • 対象ユーザー層
  • 成功の判定基準

4.2 画像とファイルの効果的な活用

  • スクリーンショット: エラー画面や設計資料の共有
  • ドラッグ&ドロップ: 設計図やワイヤーフレームの直接投入
  • Tab補完: プロジェクト内ファイルの迅速な参照

4.3 コンテキスト管理とセッション最適化

コンテキストの圧縮

> /compact コードサンプルとAPIの使い方を中心に

セッションのリセット

> /clear  # 完全なリセット

セッションの再開

claude --resume  # 過去のセッション一覧から選択

5. 高度な自動化とヘッドレスモード

5.1 ヘッドレスモードの基本

非対話的な環境での実行:

# 基本的なヘッドレスモード実行
claude -p "lintエラーを修正してください"

# JSON形式での出力ストリーミング
claude -p "テストを実行し結果を報告" --output-format stream-json

5.2 CI/CDパイプラインとの統合

# 処理パイプラインへの組み込み例
cat build_log.txt | claude -p "ビルドエラーを分析し修正提案を生成" --json | next_process

5.3 カスタムスラッシュコマンドの作成

繰り返し作業の自動化:

.claude/commands/fix-github-issue.md

GitHubのissue #$ARGUMENTS を分析し、適切な修正を実装してください。

手順:
1. `gh issue view $ARGUMENTS` でissue詳細を確認
2. 関連ファイルを特定
3. 修正を実装
4. テストを追加
5. コミットを作成

使用例:

> /project:fix-github-issue 1234

6. チーム開発でのベストプラクティス

6.1 設定ファイルの共有

チーム全体で一貫した環境を構築するため、以下をバージョン管理に含めます:

  • CLAUDE.md: プロジェクト固有の情報
  • .claude/settings.json: ツール許可設定
  • .mcp.json: MCPサーバー設定
  • .claude/commands/: カスタムスラッシュコマンド

6.2 GitHub連携の活用

# GitHub CLIの設定
gh auth login

# プルリクエストの自動レビュー
> /review

# プルリクエストコメントの取得
> /pr-comments

6.3 開発ワークフローの標準化

CLAUDE.mdに開発ワークフローを明記:

## 開発ワークフロー

### タスク開始時
1. `feature/<タスクID>` ブランチを作成
2. 空コミットを作成してPRを作成
3. タスクの実行計画をユーザーに確認

### タスク完了時  
1. PRをレディ状態に変更
2. レビュー後にマージ
3. タスクステータスを「完了」に更新

**注意**: ユーザーの許可なしにPRをマージしないこと

7. パフォーマンス最適化とコスト管理

7.1 拡張思考の効果的な活用

思考深度レベルの使い分け:

  • think: 基本レベル(単純な問題解決)
  • think hard: 中級レベル(複雑な設計判断)
  • think harder: 上級レベル(アーキテクチャ決定)
  • ultrathink: 最高レベル(全体最適化)

7.2 トークン使用量の最適化

# 使用量の確認
npx ccusage

# コンテキストの効率的な管理
> /compact [要約の指示]

7.3 マルチインスタンス運用

複数のClaude Codeインスタンスで並列開発:

# 3-4個のGitチェックアウトを作成
git worktree add ../project-feature-1 feature-1
git worktree add ../project-feature-2 feature-2

# 各ディレクトリで独立したタブを開いてClaude Code起動

8. トラブルシューティングと対処法

8.1 よくある問題と解決策

問題: Claude Codeが期待と異なる動作をする
解決策:

  • より具体的で明確な指示を提供
  • Escキーでタスクを中断し、方向修正
  • /clearでセッションをリセット

問題: MCPサーバーが接続できない
解決策:

claude --mcp-debug  # デバッグ情報を確認

問題: 権限エラーが頻発する
解決策: Permission設定を見直し、適切なallow/denyルールを設定

8.2 デバッグとモニタリング

# 詳細ログの出力
claude --verbose

# 設定状態の確認
> /status

# MCPサーバーの状態確認
> /mcp

9. セキュリティとベストプラクティス

9.1 セキュリティ考慮事項

  • 機密情報をCLAUDE.mdに記載しない
  • 本番環境での作業時は追加の権限制限を実施
  • APIキーや認証情報の適切な管理

9.2 コード品質の保証

## コード品質チェックリスト
- [ ] リンティングツールの実行
- [ ] タイプチェックの完了
- [ ] テストカバレッジの確認
- [ ] セキュリティスキャンの実施

まとめ

Claude Codeは単なるAIアシスタントではなく、開発プロセス全体を変革するパワフルなツールです。適切な設定、明確な指示、段階的なワークフロー、そしてチーム全体での標準化により、その真価を発揮できます。

継続的な学習と改善により、Claude Codeを活用した開発効率の向上を実現し、より高品質なソフトウェア開発を実現しましょう。

参考文献

本記事は以下の資料を参考にして作成されました:

参照記事

公式リソース

ただ他人の記事をまとめただけではあるのですがなかなかうまくまとまっています。Claude Codeについてあまり知らない方は、この要約記事だけでも目を通しておくと、この後の話が理解しやすくなると思います。

2. 手順書を作成する

作りたいWebアプリの仕様書から先ほど作成したベストプラクティスを参考に、Claude CodeでWebアプリを作る際の手順書を生成します。ちなみに仕様書と言っても実際に用意したのははじめに提示したものと同じこれです。

# やりたいこと
- 個人で購読しているサブスクリプションを可視化するアプリケーションを作りたい
- 実装したい機能としては
	- 年間いくらかかっているかの可視化
	- 有効に使えているかどうかのラベル付け
	- 複数プランがあるサービスでよりお得なプランの提案
- Claude codeで0から作らせてみたい
	- Obsidianでこのノートを手始めの企画書として、最終成果物作成までのすべてをやらせてみる
	- 要約したベストプラクティス記事があるのでそれを参考にしてもらう

自分でもふざけてるとは思いましたがとりあえずやってみます。Claudeへの指示は以下のものを使用しました。

> 「自分が購読しているサブスクリプションを可視化するWebアプリケーションを作りたい」に記載され
ている項目を実現するために、手始めに「Claude Codeによるシステム開発ベストプラクティス」を参考
にしながら、システム開発の手順書を作ってみてほしい

そして生成された手順書は...

サブスクリプション可視化Webアプリ開発手順書

サブスクリプション可視化Webアプリ開発手順書

プロジェクト概要

自分が購読しているサブスクリプションを可視化するWebアプリケーションをClaude Codeを使って開発するための詳細な手順書です。

目標機能

  1. 年間コスト可視化 - 年間でどのくらいの費用がかかっているかの表示
  2. 利用効果ラベル付け - 有効に使えているかどうかの評価機能
  3. プラン最適化提案 - より効率的なプランの提案機能

開発手順

フェーズ1: プロジェクト初期設定 (Explore-Plan-Code-Commit)

1.1 環境構築

# Claude Codeの準備
npm install -g @anthropic-ai/claude-code

# プロジェクトディレクトリ作成
mkdir subscription-visualizer
cd subscription-visualizer

# Claude Code初期化
claude

1.2 プロジェクト初期設定

> /init
> summarize this project

1.3 CLAUDE.md設定

以下の内容を含むCLAUDE.mdを作成:

  • プロジェクト概要とゴール
  • 技術スタック(React/Next.js + TypeScript推奨)
  • アーキテクチャパターン
  • 開発ガイドライン
  • テスト戦略
  • セキュリティ要件

フェーズ2: 要件分析と設計 (Explore Phase)

2.1 要件詳細化

> ultrathink サブスクリプション可視化アプリの詳細要件を分析し、ユーザーストーリーを作成

2.2 技術選定の調査

> find examples of subscription management web applications
> analyze best practices for financial data visualization

2.3 アーキテクチャ設計

> think hard about the optimal architecture for a subscription visualization web app

フェーズ3: 基盤開発 (Plan-Code Phase)

3.1 プロジェクト構造の計画

> ultrathink plan the project structure and initial setup for a React/Next.js subscription management app

3.2 基本セットアップ

> implement the planned project structure with Next.js and TypeScript
> set up the basic routing and component structure

3.3 データモデル設計

> design and implement the data models for subscriptions, including:
- Subscription entity (name, cost, billing cycle, category, effectiveness rating)
- User preferences
- Plan comparison data

フェーズ4: コア機能開発

4.1 サブスクリプション管理機能

> implement CRUD operations for subscription management
> add form validation and error handling

4.2 コスト可視化機能

> implement annual cost visualization with charts and graphs
> add filtering and sorting capabilities

4.3 効果ラベル機能

> implement effectiveness rating system
> add usage tracking and evaluation features

4.4 プラン最適化機能

> implement plan comparison and optimization suggestions
> add cost-benefit analysis features

フェーズ5: UI/UX開発

5.1 レスポンシブデザイン

> implement responsive design for mobile and desktop
> add dark/light theme support

5.2 データビジュアライゼーション

> implement interactive charts and graphs using Chart.js or D3.js
> add dashboard with key metrics

フェーズ6: テスト実装 (TDD Approach)

6.1 単体テスト

> write comprehensive unit tests for all components and utilities
> ensure 90%+ code coverage

6.2 統合テスト

> implement integration tests for API endpoints and data flow
> add end-to-end testing with Playwright or Cypress

フェーズ7: セキュリティ・パフォーマンス最適化

7.1 セキュリティ対策

> implement security best practices for financial data handling
> add input validation and sanitization

7.2 パフォーマンス最適化

> optimize bundle size and loading performance
> implement caching strategies

フェーズ8: デプロイと運用準備 (Commit Phase)

8.1 プロダクションビルド

> configure production build settings
> set up environment variables and configuration

8.2 デプロイメント

> deploy to Vercel/Netlify with CI/CD pipeline
> set up monitoring and error tracking

品質保証チェックリスト

開発段階での確認事項

  • リンターの実行完了
  • 型チェックの完了
  • テストカバレッジの確認
  • セキュリティスキャンの実行
  • パフォーマンステストの実行

機能完成度の確認

  • 年間コスト可視化機能の動作確認
  • 利用効果ラベル機能の動作確認
  • プラン最適化提案機能の動作確認
  • レスポンシブデザインの確認
  • クロスブラウザ対応の確認

拡張計画

将来的な機能追加

  1. 通知機能 - 支払い期日の通知
  2. レポート機能 - 月次・年次レポートの生成
  3. カテゴリ分析 - 支出カテゴリ別の詳細分析
  4. 共有機能 - 家族間でのサブスクリプション共有
  5. API連携 - 銀行口座やクレジットカードとの連携

参考文献

...正直想像以上でした。ベストプラクティスのテクニックをフル活用してClaude Codeへの指示の出し方まで生成してくれています。あとはこれに従って指示を送るだけでアプリができてしまうかもしれないと期待せずにはいられません。

3. 開発する

ということであとは手順書通りClaude Codeに指示を出すだけでアプリができることに期待して早速開発していきたいと思います。仕様書がフェーズごとに作業を分けているので従っていきます。

フェーズ1: プロジェクト初期設定

CLAUDE.mdを作成します。Claude Codeを効果的に使うためにClaude.md は重要なファイルだとされています。指示書にならい以下の内容を含むCLAUDE.mdを生成させました。

  • プロジェクト概要とゴール
  • 技術スタック(React/Next.js + TypeScript推奨)
  • アーキテクチャパターン
  • 開発ガイドライン
  • テスト戦略
  • セキュリティ要件
CLAUDE.md

Subscription Visualizer

プロジェクト概要

個人のサブスクリプションサービスを管理・可視化するWebアプリケーション。ユーザーが契約している各種サブスクリプションの支払い情報、更新日、利用状況を一元管理し、支出の最適化を支援する。

ゴール

  • サブスクリプション契約の可視化と管理
  • 月次・年次支出の分析とレポート機能
  • 解約忘れ防止のためのアラート機能
  • 支出削減の提案機能

技術スタック

フロントエンド

  • フレームワーク: Next.js 14.x (App Router)
  • 言語: TypeScript 5.x
  • UI フレームワーク: Tailwind CSS 3.x
  • UI コンポーネント: shadcn/ui
  • アイコン: Lucide React

バックエンド・API

  • API: Next.js API Routes (REST)
  • データベース: PostgreSQL
  • ORM: Prisma
  • 認証: NextAuth.js v5

開発環境

  • Node.js: 18.x LTS
  • パッケージマネージャー: pnpm
  • リンター: ESLint
  • フォーマッター: Prettier
  • テスト: Jest + React Testing Library

アーキテクチャパターン

  • ディレクトリ構成: Next.js App Router準拠
  • コンポーネント設計: Atomic Design原則
  • API設計: RESTful API (Next.js API Routes)
  • データベース: Prismaを使用したスキーマファースト設計

開発ガイドライン

コード規約

  • ESLint + Prettier使用
  • 関数型コンポーネント推奨
  • TypeScript strict mode有効
  • コンポーネント名はPascalCase
  • ファイル名はkebab-case

ブランチ戦略

  • main: 本番環境
  • develop: 開発環境
  • feature/*: 機能開発
  • hotfix/*: 緊急修正

コミット規約

Conventional Commitsに準拠:

  • feat: 新機能
  • fix: バグ修正
  • docs: ドキュメント
  • style: フォーマット
  • refactor: リファクタリング
  • test: テスト追加・修正

テスト戦略

ユニットテスト

  • コンポーネント: React Testing Library
  • ユーティリティ関数: Jest
  • カバレッジ目標: 80%以上

統合テスト

  • API Routes: Jest + Supertest
  • データベース操作: Prisma Test Environment

E2Eテスト

  • 後日実装予定(Playwright使用予定)
  • 主要なユーザーフローをカバー予定

テスト実行コマンド

pnpm test:unit         # ユニットテスト
pnpm test:integration  # 統合テスト
pnpm test:all         # すべてのテスト
pnpm test:coverage    # カバレッジレポート

セキュリティ要件

認証・認可

  • NextAuth.jsによるセッション管理
  • CSRF保護有効
  • セッションタイムアウト設定

データ保護

  • パスワードハッシュ化(bcrypt)
  • 機密データの暗号化
  • SQLインジェクション対策(Prisma使用)

API セキュリティ

  • Rate Limiting実装
  • CORS設定
  • 入力値バリデーション(Zod)

環境設定

  • 環境変数による機密情報管理
  • .env.local使用(Gitignore必須)
  • 本番環境での適切な環境変数設定

特に重要だと感じたのは 技術スタックやアーキテクチャパターンをきちんと1つに定義しておくこと です。たとえば使用するフレームワークのバージョンを指定していないとタスクの中で整合性がとれなくなっていったり、アーキテクチャパターンを指定しないと構成がはじめに指定した構成からどんどん離れていったり、みたいなことが起こりやすくなる印象です。

フェーズ2: 要件分析と設計 (Explore Phase)

Explore-Plan-Code-Commitサイクルと呼ばれるワークフローの Explorer に当たります。コードを書かせず機能の設計のみをさせることで後続のコーディングの精度が向上するらしい。正直このフェーズが一番衝撃が大きかったかもしれないです。1つずつ言われたとおりにやってみました。

2.1 要件詳細化

> ultrathink サブスクリプション可視化アプリの詳細要件を分析し、ユーザーストーリーを作成
生成されたユーザーストーリー

サブスクリプション可視化アプリ - 詳細要件分析とユーザーストーリー

1. プロジェクト概要

個人のサブスクリプションサービスを管理・可視化するWebアプリケーション。ユーザーが契約している各種サブスクリプションの支払い情報、更新日、利用状況を一元管理し、支出の最適化を支援する。

2. ターゲットユーザー(ペルソナ)

ペルソナ1: 山田太郎(30歳、IT企業勤務)

  • 特徴: 複数のSaaSツールやエンタメサービスに加入
  • 課題: 月々の支出が把握できず、使っていないサービスへの支払いが継続
  • ニーズ: 支出の可視化と最適化

ペルソナ2: 佐藤花子(25歳、フリーランスデザイナー)

  • 特徴: 仕事用ツールと個人用サービスが混在
  • 課題: 更新日を忘れて自動更新されることが多い
  • ニーズ: 更新日管理と事前通知

ペルソナ3: 鈴木一郎(40歳、家族4人)

  • 特徴: 家族それぞれのサブスクを管理
  • 課題: 家族全体での重複契約や無駄な支出
  • ニーズ: 家族単位での支出管理と最適化提案

3. エピック

エピック1: ユーザー管理

ユーザー登録、ログイン、プロフィール管理の機能群

エピック2: サブスクリプション管理

サブスクリプションの登録、編集、削除、カテゴリ分けの機能群

エピック3: 支出分析

月次・年次レポート、グラフ表示、支出傾向分析の機能群

エピック4: アラート・通知

更新日通知、支払い予定通知、異常検知の機能群

エピック5: 最適化提案

利用状況分析、重複検出、代替サービス提案の機能群

4. ユーザーストーリー

エピック1: ユーザー管理

US-001: ユーザー登録

As a 新規ユーザー
I want to メールアドレスとパスワードでアカウントを作成する
So that サービスを利用開始できる

受け入れ基準:

  • メールアドレスの形式検証が行われる
  • パスワードは8文字以上で大文字・小文字・数字を含む
  • 登録確認メールが送信される
  • 既存のメールアドレスでは登録できない

US-002: ログイン

As a 登録済みユーザー
I want to メールアドレスとパスワードでログインする
So that 自分のデータにアクセスできる

受け入れ基準:

  • 正しい認証情報でログインできる
  • 誤った認証情報ではエラーメッセージが表示される
  • 「ログイン状態を保持」オプションが利用できる
  • パスワードリセット機能へのリンクがある

エピック2: サブスクリプション管理

US-003: サブスクリプション登録

As a ログインユーザー
I want to 新しいサブスクリプションを登録する
So that 支出を管理できる

受け入れ基準:

  • サービス名、月額/年額料金、支払日、カテゴリを入力できる
  • 通貨を選択できる(円、ドル、ユーロ)
  • 無料トライアル期間を設定できる
  • 登録後、一覧に表示される

US-004: サブスクリプション一覧表示

As a ログインユーザー
I want to 登録したサブスクリプションの一覧を見る
So that 現在の契約状況を把握できる

受け入れ基準:

  • 全てのサブスクリプションがカード形式で表示される
  • カテゴリ別にフィルタリングできる
  • 月額換算の合計金額が表示される
  • アクティブ/非アクティブの状態が分かる

US-005: サブスクリプション編集

As a ログインユーザー
I want to 登録済みのサブスクリプション情報を編集する
So that 最新の情報を維持できる

受け入れ基準:

  • 全ての登録情報を編集できる
  • 料金変更履歴が記録される
  • 編集内容が即座に反映される
  • 編集前の状態に戻すことができる

エピック3: 支出分析

US-006: 月次レポート表示

As a ログインユーザー
I want to 月別の支出レポートを見る
So that 月々の支出傾向を把握できる

受け入れ基準:

  • 当月の合計支出額が表示される
  • カテゴリ別の内訳が円グラフで表示される
  • 前月比の増減が表示される
  • 過去6ヶ月の推移グラフが表示される

US-007: 年次レポート表示

As a ログインユーザー
I want to 年間の支出レポートを見る
So that 年間支出を把握し予算計画を立てられる

受け入れ基準:

  • 年間合計支出額が表示される
  • 月別推移グラフが表示される
  • カテゴリ別年間支出が表示される
  • PDFでダウンロードできる

エピック4: アラート・通知

US-008: 更新日通知設定

As a ログインユーザー
I want to サブスクリプションの更新日通知を設定する
So that 意図しない自動更新を防げる

受け入れ基準:

  • 通知タイミングを選択できる(1日前、3日前、1週間前)
  • 通知方法を選択できる(メール、アプリ内通知)
  • サブスクリプション毎に個別設定できる
  • 一括設定もできる

US-009: 支払い予定通知

As a ログインユーザー
I want to 今後の支払い予定を確認する
So that キャッシュフローを管理できる

受け入れ基準:

  • 今後30日間の支払い予定が表示される
  • カレンダー形式で確認できる
  • 支払い予定額の合計が表示される
  • カレンダーをエクスポートできる

エピック5: 最適化提案

US-010: 利用状況分析

As a ログインユーザー
I want to サブスクリプションの利用状況を記録する
So that 無駄な支出を特定できる

受け入れ基準:

  • 最終利用日を記録できる
  • 利用頻度を5段階で評価できる
  • 長期間未使用のサービスがハイライトされる
  • 利用状況レポートが生成される

US-011: 重複サービス検出

As a ログインユーザー
I want to 機能が重複するサービスを検出する
So that 統合や解約の判断ができる

受け入れ基準:

  • カテゴリ内の類似サービスが検出される
  • 重複の可能性が%で表示される
  • 統合による節約額が試算される
  • 解約推奨リストが生成される

US-012: 代替サービス提案

As a ログインユーザー
I want to より安価な代替サービスの提案を受ける
So that 支出を最適化できる

受け入れ基準:

  • 現在のサービスと同等機能の代替案が表示される
  • 切り替えによる節約額が表示される
  • ユーザーレビューが参照できる
  • 提案を却下/検討中にマークできる

5. 非機能要件

パフォーマンス要件

  • ページロード時間: 3秒以内
  • API レスポンス: 1秒以内
  • 同時接続ユーザー数: 1000人

セキュリティ要件

  • HTTPS通信の強制
  • パスワードのハッシュ化(bcrypt)
  • セッションタイムアウト: 30分
  • 2要素認証のサポート

使いやすさ要件

  • モバイルレスポンシブ対応
  • ダークモード対応
  • 多言語対応(日本語、英語)
  • アクセシビリティ対応(WCAG 2.1 AA準拠)

6. 今後の検討事項

  • 家族アカウント機能
  • API連携による自動取り込み
  • 支出予算設定と警告機能
  • サブスクリプション共有機能

何事??という感じですが...。アジャイル開発みたいなノリでユーザーストーリーやらエピックやらを考えてくれたみたいですね。

2.2 技術選定の調査

> find examples of subscription management web applications
生成された競合比較

サブスクリプション管理アプリ 競合分析

1. 市場概要

  • 米国の成人は平均して月額$91をサブスクリプションに支出
  • 消費者は月額$86と推定しているが、実際の平均支出は$219
  • 調査対象の48%が無料トライアルに登録後、キャンセルを忘れた経験あり
  • 平均的な消費者は7種類以上のサブスクリプションを保有

2. B2C(個人向け)サブスクリプション管理アプリ

2.1 Bobby - Track Subscriptions

特徴:

  • シンプルでミニマリストなインターフェース
  • 数百の既存サブスクリプションから選択可能
  • カスタムサブスクリプションの作成も可能
  • 支払い期日の通知機能

価格:

  • 基本機能:無料
  • 無制限サブスクリプション追跡:$2.99(アプリ内購入)

プラットフォーム: iOS専用

強み:

  • シンプルで使いやすい
  • 低価格
  • 既存サービスのデータベースが充実

2.2 Rocket Money(旧Truebill)

特徴:

  • 銀行口座との連携により自動でサブスクリプションを識別
  • ワンクリックでのサブスクリプション解約サービス
  • 予算管理ツール
  • 請求額の交渉サービス(SiriusXM、AT&Tなどで成功例あり)

価格:

  • 基本プラン:無料
  • プレミアムプラン:月額$6〜$12(7日間無料トライアルあり)

強み:

  • 自動識別機能
  • 解約代行サービス
  • 請求額交渉サービス

2.3 Trim by OneMain

特徴:

  • Webブラウザベース(モバイルアプリなし)
  • サブスクリプション監視
  • 請求額交渉サービス
  • 貯蓄に4%のボーナス提供

価格:

  • 基本サービス:無料
  • 請求額交渉成功時:節約額の年間15%を手数料として徴収

強み:

  • 成功報酬型の価格設定
  • 貯蓄ボーナス

2.4 Subby(Android専用)

特徴:

  • 無制限のサブスクリプション手動入力(無料)
  • 支払い期日の通知
  • 月次・年次の支出合計表示

プラットフォーム: Android専用

強み:

  • 完全無料
  • シンプルな機能

2.5 TrackMySubs

特徴:

  • ブラウザベースのプラットフォーム
  • 小規模ビジネス向けだが個人でも利用可能
  • 詳細な支出分析

価格:

  • 無料:10サブスクリプションまで
  • 有料プラン:月額$10(無制限)〜$30(エンタープライズ)

強み:

  • Web版で様々なデバイスから利用可能
  • ビジネス利用にも対応

2.6 その他の注目アプリ

  • PocketGuard:予算管理に特化(CNBC Select評価)
  • Simplifi from Quicken:使いやすさで高評価(CNBC Select評価)

3. B2B(企業向け)SaaS管理ツール

主要プレイヤー

  1. Zylo
  2. BetterCloud
  3. Vendr
  4. Chargebee(月額$299〜$599)
  5. Maxio(ChargifyとSaaSOpticsの合併)
  6. Stripe Billing
  7. Recurly
  8. Zoho Subscriptions
  9. Billsby

B2B市場の特徴

  • SaaS市場は年間18%の成長率
  • 自動化されたサブスクリプションワークフロー
  • コスト最適化機能
  • コンプライアンス管理
  • 一元的なダッシュボード

4. 競合分析から得られる示唆

必須機能

  1. サブスクリプション追跡

    • 手動入力 or 自動識別
    • カテゴリ分類
    • 支払いスケジュール管理
  2. 通知機能

    • 支払い期日リマインダー
    • 価格変更アラート
    • 無料トライアル終了通知
  3. 分析・レポート

    • 月次・年次支出サマリー
    • カテゴリ別分析
    • 支出トレンド

差別化要素

  1. 自動化機能

    • 銀行連携による自動識別
    • ワンクリック解約
    • 請求額交渉サービス
  2. 価格戦略

    • フリーミアムモデル
    • 成功報酬型
    • 段階的な価格設定
  3. プラットフォーム戦略

    • モバイルファースト vs Webベース
    • クロスプラットフォーム対応

市場のギャップ

  1. 日本市場への最適化

    • 日本特有のサービスへの対応
    • 日本語UI/UX
    • 円建て管理
  2. 家族向け機能

    • 家族メンバー間での共有
    • 家族全体の支出管理
    • 子供向けサブスクリプション管理
  3. AIによる最適化提案

    • 利用状況に基づく解約提案
    • 類似サービスの統合提案
    • 支出予測と予算提案

5. 推奨戦略

  1. MVP段階:Bobby型のシンプルなトラッカーから開始
  2. 成長段階:Rocket Money型の自動化機能を追加
  3. 差別化段階:日本市場特化機能と家族向け機能で独自性を確立

いきなり競合分析が始まりそこから取るべき戦略まで提案してくれました。。。ちなみここは1つの分岐点になっていて、推奨戦略のうち「MVP段階:Bobby型のシンプルなトラッカーから開始」で進めるよう指示を出しました。これによりこれ以降の方針が明確になり、各フェーズでの生成の質が大きく高まったと感じました。

> analyze best practices for financial data visualization
生成された可視化ベストプラクティス

金融データ可視化のベストプラクティス

1. コアデザイン原則

1.1 プログレッシブディスクロージャー(段階的情報開示)

  • 概念: 情報を段階的に表示し、ユーザーが圧倒されないようにする
  • 実装例:
    • 初期表示: 合計支出額のサマリー
    • 第2階層: カテゴリ別の内訳
    • 第3階層: 個別サブスクリプションの詳細
  • 効果: 認知負荷の軽減と探索的な分析の促進

1.2 視覚的階層(ビジュアルヒエラルキー)

  • 原則: 最も重要な情報を最初に目に入るように配置
  • 実装方法:
    • サイズ: 重要な数値は大きく表示
    • 色: アクションが必要な項目は目立つ色で
    • 配置: 左上から右下への視線の流れを意識
    • コントラスト: 重要度に応じた明暗の使い分け

1.3 適切なチャート選択

  • 折れ線グラフ: 時系列データ(支出トレンド)
  • 棒グラフ: カテゴリ比較(サービス別支出)
  • 円グラフ: 構成比(支出内訳)
  • ヒートマップ: 支払い頻度やパターンの可視化
  • ウォーターフォール: 月次支出の増減分析

2. サブスクリプション管理に特化した可視化

2.1 ダッシュボード構成

┌─────────────────────────────────────────────┐
│  月次合計支出    前月比      年間予測        │
│   ¥15,240      +¥1,200     ¥182,880        │
├─────────────────┬───────────────────────────┤
│                 │  支出トレンド(6ヶ月)    │
│  カテゴリ別     │  [折れ線グラフ]           │
│  円グラフ       │                           │
│                 ├───────────────────────────┤
│                 │  今後の支払い予定         │
│                 │  [カレンダービュー]       │
└─────────────────┴───────────────────────────┘

2.2 カード型UI

  • メリット: 情報の区分けが明確
  • 推奨数: 初期表示は5-6枚まで
  • 内容例:
    • 総支出カード
    • カテゴリ別支出カード
    • 更新予定カード
    • 節約提案カード
    • 未使用サービスアラートカード

2.3 インタラクティブ要素

  • ホバー効果: 詳細情報の表示
  • クリック動作: ドリルダウン分析
  • フィルタリング: カテゴリ、期間、金額範囲
  • ソート機能: 金額、更新日、利用頻度

3. 色彩設計

3.1 カラーパレット

  • プライマリ: ブランドカラー(アクション)
  • セカンダリ: 補助情報
  • 成功: 緑系(節約、良好な状態)
  • 警告: 黄系(注意が必要)
  • 危険: 赤系(即座の対応が必要)
  • ニュートラル: グレー系(背景、非アクティブ)

3.2 データ可視化の配色

  • カテゴリ別配色: 最大12色まで識別可能
  • グラデーション: 数値の大小を表現
  • アクセシビリティ: 色覚多様性への配慮

4. タイポグラフィ

4.1 フォント階層

見出し1: 24px - 32px(重要な合計値)
見出し2: 18px - 20px(セクションタイトル)
本文: 14px - 16px(通常のテキスト)
キャプション: 12px - 13px(補助情報)

4.2 数値表示

  • 通貨記号: 常に同じ位置に配置
  • 桁区切り: 3桁ごとにカンマ
  • 小数点: 金額は整数表示を基本
  • 単位: 明確に表示(円、ドル等)

5. レスポンシブデザイン

5.1 ブレークポイント

  • デスクトップ: 1200px以上
  • タブレット: 768px - 1199px
  • モバイル: 767px以下

5.2 モバイル最適化

  • 縦スクロール: 横スクロールは避ける
  • タップターゲット: 最小44px × 44px
  • 簡略化: 重要情報のみ表示
  • ジェスチャー: スワイプでカード切り替え

6. パフォーマンス最適化

6.1 データ読み込み

  • 遅延読み込み: 表示領域外のデータ
  • キャッシング: 頻繁にアクセスするデータ
  • ページネーション: 大量データの分割表示

6.2 アニメーション

  • duration: 200-300ms
  • easing: ease-in-out
  • 用途: 状態変化の明確化

7. アクセシビリティ

7.1 WCAG 2.1 AA準拠

  • コントラスト比: 最小4.5:1(通常テキスト)
  • 代替テキスト: すべてのグラフに説明文
  • キーボード操作: 完全対応
  • スクリーンリーダー: ARIA属性の適切な使用

7.2 国際化対応

  • 通貨: 複数通貨の同時表示
  • 日付形式: ロケールに応じた表示
  • 数値形式: 地域別の桁区切り

8. エラー処理とフィードバック

8.1 エラー状態

  • データなし: 明確なメッセージと次のアクション
  • 読み込みエラー: リトライオプション
  • 接続エラー: オフライン時の対応

8.2 フィードバック

  • 読み込み中: スケルトンスクリーン
  • 成功: トースト通知
  • 警告: インライン表示

9. 実装例(React + Tailwind CSS)

// 支出サマリーカード
<div className="bg-white rounded-lg shadow-md p-6">
  <div className="flex justify-between items-start mb-4">
    <h3 className="text-lg font-semibold text-gray-900">月次支出</h3>
    <span className="text-sm text-gray-500">2024年1月</span>
  </div>

  <div className="mb-2">
    <span className="text-3xl font-bold text-gray-900">¥15,240</span>
  </div>

  <div className="flex items-center text-sm">
    <span className="text-green-600 flex items-center">
      <ArrowDownIcon className="w-4 h-4 mr-1" />
      -¥560
    </span>
    <span className="text-gray-500 ml-2">前月比</span>
  </div>
</div>

10. 参考デザインリソース

Dribbbleコレクション

注目のデザイン例

  1. Submaster - Nikita Bedaralli
  2. finpal: AI Finance Assistant - finterface
  3. Elfee - Ansh Tyagi
  4. Subscription Manager App - Zakariya Buhari

まとめ

金融データの可視化において最も重要なのは、ユーザーが「一目で理解できる」ことです。複雑なデータを簡潔に表現し、必要に応じて詳細を探索できる設計が、優れたサブスクリプション管理アプリの鍵となります。

可視化に関する知見を収集しています。ちなみに実装されたダッシュボードは下のようになっていて、若干の差はあるもののおおむねここで提示されたデザイン構成になっているのがわかります。カード型UIも採用されていますしここで生成したベストプラクティスは、美しいUIの開発に大きく貢献していそうです。

2.3 アーキテクチャ設計

> think hard about the optimal architecture for a subscription visualization web app
生成されたアーキテクチャ設計

サブスクリプション可視化アプリ - シンプルアーキテクチャ設計(Bobby型)

1. 設計方針

1.1 基本原則

Bobby型のシンプルなサブスクリプショントラッカーとして、以下の原則で設計:

  • シンプリシティファースト: 複雑な機能は避け、コア機能に集中
  • モノリシックアーキテクチャ: 管理・開発の簡素化
  • 手動入力中心: 自動連携機能は実装しない
  • 低コスト運用: 最小限のインフラストラクチャ

1.2 MVP機能

  1. ユーザー登録・ログイン
  2. サブスクリプションの手動登録・編集・削除
  3. 月次支出の可視化
  4. 支払い期日の通知
  5. カテゴリ別の支出表示

2. 技術スタック

2.1 選定理由

  • 開発効率: フルスタックTypeScriptで統一
  • デプロイ簡易性: Vercelへのワンクリックデプロイ
  • コスト効率: サーバーレス実行で従量課金

2.2 具体的な技術

フロントエンド:
  - Next.js 14 (App Router)
  - TypeScript
  - Tailwind CSS
  - shadcn/ui
  - React Hook Form + Zod

バックエンド:
  - Next.js API Routes
  - Prisma ORM
  - NextAuth.js v5

データベース:
  - PostgreSQL (Supabase or Neon)

インフラ:
  - Vercel (ホスティング)
  - Resend (メール送信)
  - Uploadthing (画像アップロード)

3. アーキテクチャ概要

3.1 シンプルな3層構造

┌─────────────────────────────────────┐
│     クライアント (Next.js App)      │
│  - React Components                 │
│  - Client-side State (Zustand)     │
└──────────────┬──────────────────────┘
               │
┌──────────────┴──────────────────────┐
│      API層 (Next.js API Routes)     │
│  - RESTful Endpoints               │
│  - Authentication (NextAuth)        │
│  - Validation (Zod)                │
└──────────────┬──────────────────────┘
               │
┌──────────────┴──────────────────────┐
│     データ層 (PostgreSQL)           │
│  - Prisma ORM                      │
│  - Database Migrations             │
└─────────────────────────────────────┘

4. データベース設計

4.1 最小限のテーブル構成

// schema.prisma

model User {
  id              String          @id @default(cuid())
  email           String          @unique
  name            String?
  emailVerified   DateTime?
  image           String?
  createdAt       DateTime        @default(now())
  updatedAt       DateTime        @updatedAt

  accounts        Account[]
  sessions        Session[]
  subscriptions   Subscription[]
}

model Subscription {
  id              String          @id @default(cuid())
  userId          String
  name            String
  amount          Decimal         @db.Decimal(10, 2)
  currency        String          @default("JPY")
  billingCycle    BillingCycle    @default(MONTHLY)
  nextBillingDate DateTime
  category        Category
  isActive        Boolean         @default(true)
  notes           String?
  createdAt       DateTime        @default(now())
  updatedAt       DateTime        @updatedAt

  user            User            @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([userId])
  @@index([nextBillingDate])
}

enum BillingCycle {
  MONTHLY
  YEARLY
  QUARTERLY
  CUSTOM
}

enum Category {
  ENTERTAINMENT
  PRODUCTIVITY
  EDUCATION
  CLOUD_STORAGE
  MUSIC
  VIDEO
  NEWS
  FINANCE
  HEALTH
  OTHER
}

// NextAuth.js用のテーブル
model Account {
  // NextAuth標準スキーマ
}

model Session {
  // NextAuth標準スキーマ
}

5. API設計

5.1 RESTful エンドポイント

// Subscription CRUD
GET    /api/subscriptions          // 一覧取得
POST   /api/subscriptions          // 新規作成
PUT    /api/subscriptions/:id      // 更新
DELETE /api/subscriptions/:id      // 削除

// Analytics
GET    /api/analytics/summary      // 支出サマリー
GET    /api/analytics/category     // カテゴリ別分析
GET    /api/analytics/trend        // トレンド分析

// User
GET    /api/user/profile          // プロフィール取得
PUT    /api/user/profile          // プロフィール更新
DELETE /api/user/account          // アカウント削除

5.2 API実装例

// app/api/subscriptions/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { z } from 'zod'
import prisma from '@/lib/prisma'

const subscriptionSchema = z.object({
  name: z.string().min(1),
  amount: z.number().positive(),
  currency: z.string().default('JPY'),
  billingCycle: z.enum(['MONTHLY', 'YEARLY', 'QUARTERLY', 'CUSTOM']),
  nextBillingDate: z.string().datetime(),
  category: z.enum(['ENTERTAINMENT', 'PRODUCTIVITY' /* ... */]),
  notes: z.string().optional(),
})

export async function POST(req: NextRequest) {
  const session = await getServerSession()
  if (!session?.user?.id) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
  }

  try {
    const body = await req.json()
    const data = subscriptionSchema.parse(body)

    const subscription = await prisma.subscription.create({
      data: {
        ...data,
        userId: session.user.id,
      },
    })

    return NextResponse.json(subscription)
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json({ error: error.errors }, { status: 400 })
    }
    return NextResponse.json({ error: 'Server error' }, { status: 500 })
  }
}

6. フロントエンド設計

6.1 ページ構成

app/
├── (auth)/
│   ├── login/
│   └── register/
├── (dashboard)/
│   ├── page.tsx              # ダッシュボード
│   ├── subscriptions/
│   │   ├── page.tsx          # 一覧
│   │   └── [id]/
│   │       └── page.tsx      # 詳細・編集
│   ├── analytics/
│   │   └── page.tsx          # 分析
│   └── settings/
│       └── page.tsx          # 設定
└── api/
    └── ...                   # API Routes

6.2 コンポーネント構成

// components/subscription-card.tsx
interface SubscriptionCardProps {
  subscription: Subscription;
  onEdit: () => void;
  onDelete: () => void;
}

export function SubscriptionCard({ subscription, onEdit, onDelete }: SubscriptionCardProps) {
  const daysUntilBilling = differenceInDays(
    new Date(subscription.nextBillingDate),
    new Date()
  );

  return (
    <Card>
      <CardHeader>
        <div className="flex justify-between items-start">
          <div>
            <h3 className="text-lg font-semibold">{subscription.name}</h3>
            <p className="text-sm text-muted-foreground">
              {CATEGORY_LABELS[subscription.category]}
            </p>
          </div>
          <Badge variant={daysUntilBilling <= 7 ? "destructive" : "secondary"}>
            {daysUntilBilling}日後
          </Badge>
        </div>
      </CardHeader>
      <CardContent>
        <p className="text-2xl font-bold">
          ¥{subscription.amount.toLocaleString()}
          <span className="text-sm font-normal text-muted-foreground">
            /{BILLING_CYCLE_LABELS[subscription.billingCycle]}
          </span>
        </p>
      </CardContent>
      <CardFooter className="flex justify-end gap-2">
        <Button variant="outline" size="sm" onClick={onEdit}>
          編集
        </Button>
        <Button variant="outline" size="sm" onClick={onDelete}>
          削除
        </Button>
      </CardFooter>
    </Card>
  );
}

7. 状態管理

7.1 Zustandによるクライアント状態管理

// stores/subscription-store.ts
import { create } from 'zustand'

interface SubscriptionStore {
  subscriptions: Subscription[]
  isLoading: boolean
  fetchSubscriptions: () => Promise<void>
  addSubscription: (data: CreateSubscriptionDto) => Promise<void>
  updateSubscription: (id: string, data: UpdateSubscriptionDto) => Promise<void>
  deleteSubscription: (id: string) => Promise<void>
}

export const useSubscriptionStore = create<SubscriptionStore>((set) => ({
  subscriptions: [],
  isLoading: false,

  fetchSubscriptions: async () => {
    set({ isLoading: true })
    try {
      const res = await fetch('/api/subscriptions')
      const data = await res.json()
      set({ subscriptions: data })
    } finally {
      set({ isLoading: false })
    }
  },
  // ... 他のメソッド
}))

8. 通知機能

8.1 シンプルなメール通知

// lib/notifications.ts
import { Resend } from 'resend'

const resend = new Resend(process.env.RESEND_API_KEY)

export async function sendBillingReminder(
  user: User,
  subscription: Subscription
) {
  await resend.emails.send({
    from: 'noreply@subscription-visualizer.com',
    to: user.email,
    subject: `${subscription.name}の支払い期日が近づいています`,
    html: `
      <p>${user.name}様</p>
      <p>${subscription.name}の次回支払い日は${formatDate(subscription.nextBillingDate)}です。</p>
      <p>金額: ¥${subscription.amount.toLocaleString()}</p>
    `,
  })
}

// Vercel Cronジョブで毎日実行
export async function checkUpcomingBillings() {
  const tomorrow = addDays(new Date(), 1)
  const weekLater = addDays(new Date(), 7)

  const subscriptions = await prisma.subscription.findMany({
    where: {
      nextBillingDate: {
        gte: tomorrow,
        lte: weekLater,
      },
      isActive: true,
    },
    include: {
      user: true,
    },
  })

  for (const subscription of subscriptions) {
    await sendBillingReminder(subscription.user, subscription)
  }
}

9. デプロイメント

9.1 環境変数

# .env.local
DATABASE_URL="postgresql://..."
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="..."
RESEND_API_KEY="..."

9.2 Vercelデプロイ設定

// vercel.json
{
  "crons": [
    {
      "path": "/api/cron/billing-reminder",
      "schedule": "0 9 * * *"
    }
  ]
}

10. セキュリティ

10.1 基本的なセキュリティ対策

  • 認証: NextAuth.jsによるセッション管理
  • 認可: API Routeでのセッション確認
  • 入力検証: Zodによるスキーマ検証
  • CSRF保護: NextAuth.js標準機能
  • SQLインジェクション対策: Prisma ORM使用

10.2 データ保護

// middleware.ts
import { withAuth } from 'next-auth/middleware'

export default withAuth({
  pages: {
    signIn: '/login',
  },
})

export const config = {
  matcher: [
    '/dashboard/:path*',
    '/api/subscriptions/:path*',
    '/api/analytics/:path*',
  ],
}

11. 今後の拡張計画

Phase 1 (MVP)

  • 基本的なCRUD機能
  • シンプルな分析機能
  • メール通知

Phase 2

  • CSVインポート/エクスポート
  • より詳細な分析機能
  • 複数通貨対応

Phase 3

  • モバイルアプリ(React Native)
  • 家族共有機能
  • APIの公開

このアーキテクチャにより、Bobby型のシンプルで使いやすいサブスクリプショントラッカーを、低コストで迅速に開発・運用することが可能です。

これまでに収集した情報や決定した方針に基いて設計資料を作成してくれました!!

...すごすぎて意味がわかりません。
改めて出しますけど最初のメモこれですからね?

# やりたいこと
- 個人で購読しているサブスクリプションを可視化するアプリケーションを作りたい
- 実装したい機能としては
	- 年間いくらかかっているかの可視化
	- 有効に使えているかどうかのラベル付け
	- 複数プランがあるサービスでよりお得なプランの提案

しかもここまでかかった時間が 10~20 分くらいです。すごい時代になったものです。

このように Phase 3 ではユーザーストーリーを作成し、そこから開発するアプリの設計書まで作成してしまいました。ネタバレになりますがこれ以降の実装はこのフェーズで作成した設計書ほぼそのまま通りに進行します。Exploreフェーズが最も大事というのは本当のようです...

あと特に指示は出してなかったのですが Claude Codeにコード生成以外の指示を出しても上述のように結果をファイルで返してくれるのはいいですね。後になってClaudeが改めて生成した設計書を確認することもありました。なにより人間にも扱いやすいです。

フェーズ3: 基盤開発(Plan-Code Phase)

基盤とありますが今回はかなり軽めのアプリ開発になったこともあり、このフェーズですべての実行コードが生成されました。正直眺めてるだけでした。

> ultrathink plan the project structure and initial setup for a React/Next.js subscription management app
生成された設計書

サブスクリプション管理アプリ - プロジェクト構造と初期セットアップ

プロジェクト構造

subscription-visualizer/
├── app/                          # Next.js App Router
│   ├── (auth)/                   # 認証関連ページ(グループルート)
│   │   ├── login/
│   │   │   └── page.tsx
│   │   ├── register/
│   │   │   └── page.tsx
│   │   └── layout.tsx
│   │
│   ├── (dashboard)/              # ダッシュボード(認証必須)
│   │   ├── layout.tsx
│   │   ├── page.tsx              # ダッシュボードトップ
│   │   ├── subscriptions/
│   │   │   ├── page.tsx          # サブスク一覧
│   │   │   ├── new/
│   │   │   │   └── page.tsx      # 新規登録
│   │   │   └── [id]/
│   │   │       ├── page.tsx      # 詳細・編集
│   │   │       └── loading.tsx
│   │   ├── analytics/
│   │   │   └── page.tsx          # 分析ページ
│   │   └── settings/
│   │       └── page.tsx          # 設定ページ
│   │
│   ├── api/                      # API Routes
│   │   ├── auth/
│   │   │   └── [...nextauth]/
│   │   │       └── route.ts
│   │   ├── subscriptions/
│   │   │   ├── route.ts          # GET(一覧), POST(作成)
│   │   │   └── [id]/
│   │   │       └── route.ts      # GET, PUT, DELETE
│   │   ├── analytics/
│   │   │   ├── summary/
│   │   │   │   └── route.ts
│   │   │   ├── category/
│   │   │   │   └── route.ts
│   │   │   └── trend/
│   │   │       └── route.ts
│   │   └── cron/
│   │       └── billing-reminder/
│   │           └── route.ts
│   │
│   ├── layout.tsx                # ルートレイアウト
│   ├── page.tsx                  # ランディングページ
│   ├── globals.css               # グローバルCSS
│   └── providers.tsx             # Context Providers
│
├── components/                   # 再利用可能なコンポーネント
│   ├── ui/                       # shadcn/ui コンポーネント
│   │   ├── button.tsx
│   │   ├── card.tsx
│   │   ├── dialog.tsx
│   │   ├── form.tsx
│   │   ├── input.tsx
│   │   ├── label.tsx
│   │   ├── select.tsx
│   │   └── ...
│   │
│   ├── auth/                     # 認証関連コンポーネント
│   │   ├── login-form.tsx
│   │   ├── register-form.tsx
│   │   └── user-menu.tsx
│   │
│   ├── subscriptions/            # サブスクリプション関連
│   │   ├── subscription-card.tsx
│   │   ├── subscription-form.tsx
│   │   ├── subscription-list.tsx
│   │   └── category-filter.tsx
│   │
│   ├── analytics/                # 分析関連
│   │   ├── spending-chart.tsx
│   │   ├── category-breakdown.tsx
│   │   └── trend-graph.tsx
│   │
│   └── layout/                   # レイアウト関連
│       ├── header.tsx
│       ├── sidebar.tsx
│       └── mobile-nav.tsx
│
├── lib/                          # ユーティリティ・設定
│   ├── auth.ts                   # NextAuth設定
│   ├── prisma.ts                 # Prismaクライアント
│   ├── utils.ts                  # ユーティリティ関数
│   ├── constants.ts              # 定数定義
│   ├── validations/              # Zodスキーマ
│   │   ├── auth.ts
│   │   └── subscription.ts
│   └── email/                    # メールテンプレート
│       └── billing-reminder.tsx
│
├── stores/                       # Zustand ストア
│   ├── subscription-store.ts
│   └── user-store.ts
│
├── hooks/                        # カスタムフック
│   ├── use-subscriptions.ts
│   ├── use-analytics.ts
│   └── use-toast.ts
│
├── types/                        # TypeScript型定義
│   ├── index.ts
│   ├── subscription.ts
│   ├── user.ts
│   └── analytics.ts
│
├── prisma/                       # Prisma設定
│   ├── schema.prisma
│   ├── seed.ts                   # シードデータ
│   └── migrations/               # マイグレーション
│
├── public/                       # 静的ファイル
│   ├── images/
│   └── icons/
│
├── tests/                        # テストファイル
│   ├── unit/
│   └── integration/
│
├── .env.example                  # 環境変数サンプル
├── .env.local                    # ローカル環境変数(gitignore)
├── .eslintrc.json               # ESLint設定
├── .gitignore
├── .prettierrc                   # Prettier設定
├── components.json              # shadcn/ui設定
├── middleware.ts                # Next.js Middleware
├── next.config.js               # Next.js設定
├── package.json
├── pnpm-lock.yaml               # pnpmロックファイル
├── postcss.config.js            # PostCSS設定
├── README.md                    # プロジェクト説明
├── tailwind.config.ts           # Tailwind CSS設定
├── tsconfig.json                # TypeScript設定
└── vercel.json                  # Vercel設定

初期セットアップ手順

1. プロジェクトの作成

# Next.jsプロジェクトの作成
pnpm create next-app@latest subscription-visualizer --typescript --tailwind --app --src-dir=false --import-alias "@/*"

# プロジェクトディレクトリに移動
cd subscription-visualizer

2. 必要な依存関係のインストール

# 認証
pnpm add next-auth@beta @auth/prisma-adapter

# データベース・ORM
pnpm add @prisma/client
pnpm add -D prisma

# UI コンポーネント
pnpm add @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-label @radix-ui/react-select @radix-ui/react-slot @radix-ui/react-tabs
pnpm add class-variance-authority clsx tailwind-merge lucide-react

# フォーム・バリデーション
pnpm add react-hook-form @hookform/resolvers zod

# 状態管理
pnpm add zustand

# 日付処理
pnpm add date-fns

# グラフ・チャート
pnpm add recharts

# メール送信
pnpm add resend

# 開発用ツール
pnpm add -D @types/node

3. shadcn/ui の初期化

# shadcn/ui の初期化
pnpm dlx shadcn-ui@latest init

# 基本コンポーネントの追加
pnpm dlx shadcn-ui@latest add button card dialog form input label select badge tabs toast

4. Prisma の初期化

# Prisma初期化
pnpm prisma init

# schema.prismaを編集後、マイグレーション実行
pnpm prisma migrate dev --name init

# Prismaクライアントの生成
pnpm prisma generate

5. 環境変数の設定

.env.local ファイルを作成:

# Database
DATABASE_URL="postgresql://user:password@localhost:5432/subscription_visualizer"

# NextAuth
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="your-secret-key-here"

# Email (Resend)
RESEND_API_KEY="re_xxxxxxxxxx"

# Optional: OAuth Providers
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""

6. 基本的な設定ファイル

tailwind.config.ts

import type { Config } from 'tailwindcss'

const config = {
  darkMode: ['class'],
  content: [
    './pages/**/*.{ts,tsx}',
    './components/**/*.{ts,tsx}',
    './app/**/*.{ts,tsx}',
    './src/**/*.{ts,tsx}',
  ],
  prefix: '',
  theme: {
    container: {
      center: true,
      padding: '2rem',
      screens: {
        '2xl': '1400px',
      },
    },
    extend: {
      colors: {
        border: 'hsl(var(--border))',
        input: 'hsl(var(--input))',
        ring: 'hsl(var(--ring))',
        background: 'hsl(var(--background))',
        foreground: 'hsl(var(--foreground))',
        primary: {
          DEFAULT: 'hsl(var(--primary))',
          foreground: 'hsl(var(--primary-foreground))',
        },
        secondary: {
          DEFAULT: 'hsl(var(--secondary))',
          foreground: 'hsl(var(--secondary-foreground))',
        },
        destructive: {
          DEFAULT: 'hsl(var(--destructive))',
          foreground: 'hsl(var(--destructive-foreground))',
        },
        muted: {
          DEFAULT: 'hsl(var(--muted))',
          foreground: 'hsl(var(--muted-foreground))',
        },
        accent: {
          DEFAULT: 'hsl(var(--accent))',
          foreground: 'hsl(var(--accent-foreground))',
        },
        popover: {
          DEFAULT: 'hsl(var(--popover))',
          foreground: 'hsl(var(--popover-foreground))',
        },
        card: {
          DEFAULT: 'hsl(var(--card))',
          foreground: 'hsl(var(--card-foreground))',
        },
      },
      borderRadius: {
        lg: 'var(--radius)',
        md: 'calc(var(--radius) - 2px)',
        sm: 'calc(var(--radius) - 4px)',
      },
      keyframes: {
        'accordion-down': {
          from: { height: '0' },
          to: { height: 'var(--radix-accordion-content-height)' },
        },
        'accordion-up': {
          from: { height: 'var(--radix-accordion-content-height)' },
          to: { height: '0' },
        },
      },
      animation: {
        'accordion-down': 'accordion-down 0.2s ease-out',
        'accordion-up': 'accordion-up 0.2s ease-out',
      },
    },
  },
  plugins: [require('tailwindcss-animate')],
} satisfies Config

export default config

middleware.ts

export { default } from 'next-auth/middleware'

export const config = {
  matcher: [
    '/dashboard/:path*',
    '/subscriptions/:path*',
    '/analytics/:path*',
    '/settings/:path*',
    '/api/subscriptions/:path*',
    '/api/analytics/:path*',
  ],
}

7. 開発サーバーの起動

# 開発サーバー起動
pnpm dev

# 別ターミナルでPrisma Studioを起動(データベース確認用)
pnpm prisma studio

VSCode 推奨設定

.vscode/settings.json:

{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "typescript.tsdk": "node_modules/typescript/lib",
  "typescript.enablePromptUseWorkspaceTsdk": true
}

.vscode/extensions.json:

{
  "recommendations": [
    "dbaeumer.vscode-eslint",
    "esbenp.prettier-vscode",
    "prisma.prisma",
    "bradlc.vscode-tailwindcss"
  ]
}

Git設定

.gitignore:

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local
.env

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

# prisma
prisma/*.db
prisma/*.db-journal

開発フロー

  1. 機能開発時

    • feature/機能名 ブランチを作成
    • コンポーネントは components/ に配置
    • APIエンドポイントは app/api/ に配置
  2. スタイリング

    • Tailwind CSSクラスを使用
    • 共通スタイルは globals.css に定義
    • shadcn/ui コンポーネントをベースに拡張
  3. 型安全性

    • Zodスキーマで入力検証
    • Prismaの型を活用
    • types/ に共通型定義
  4. テスト

    • ユニットテスト: Jest + React Testing Library
    • 統合テスト: Jest + Docker (PostgreSQL)
    • E2Eテスト: Playwright(後日実装予定)

この構造により、保守性が高く、拡張しやすいプロジェクトを構築できます。

フェーズ3で作成した設計書をさらに発展させ、実際に開発を始める準備をしています。ultrathink の最後の使い所です。

3.2 基本セットアップ

> implement the planned project structure with Next.js and TypeScript
> set up the basic routing and component structure
> design and implement the data models for subscriptions

設計書の内容を実装していきます。基本セットアップとありますがここですべてのコードが生成されました。

フェーズ3.5 ローカルでの動作確認

手順書には存在しませんが、フェーズ3で必要な機能がすべて実装されたので、ここで完成したWebアプリをローカルで起動してみました。一発で動けば自分はエンジニアを引退するつもりでいましたがそんなわけもなく、バグ取りを実施しました(もちろんClaude Codeで)。
例えば次のような問題があり、その都度設計書と実装を修正しました。

  • NextAuth.js v5 betaとNext.js 14.1.0の互換性問題
  • 認証周りでルーティングに不具合

地味に助かったのが、ローカルで動作確認するのに必要なDBの設定も爆速でやってくれたことです。案外沼ったりするので助かりますね。

フェーズ4: コア機能開発

手順書を書いた段階ではここで実装の予定だったのだと思います。今回はすでに実装を終えているので飛ばします。

フェーズ5: UI/UX開発

同じくです。

フェーズ6: テスト実装

テストの実装フェーズです。単体テスト → 統合テスト の順に作りました。

6.1 単体テスト

- write comprehensive unit tests for all components and utilities

この指示でテストを大量に生成しますが、この時点ではすべて通過しないです。しかし Claude Code に投げておけば勝手にテストの実行と失敗したテストの修正をしてくれるので特にやることはないです。

6.2 統合テスト

> implement integration tests for API endpoints and data flow

単体テストのときと同様です。
ちなみに手順書ではこのあと e2eテストの実装も計画されていましたが今回は割愛しました。

フェーズ7: セキュリティ・パフォーマンス最適化

いったんスキップしました。

フェーズ8: デプロイと運用準備(Commit Phase)

手順書ではプロダクションビルド用の設定を指示するよう記載されているが、今回はとりあえずデプロイして動けばいいので省略しました。
Next.jsアプリケーションのVercel + Supabase + Prisma構成における本番環境と開発環境での環境構築ガイド を参考に VercelSupabase をセットアップしました。(Claude Codeを使わない分この作業が一番時間かかったかも)
当初は Github Actions による自動デプロイも予定していましたが Vercel にはデフォルトでその機能が備わっているのでこちらも実装を見送りました。

感想

1. Explorer Phase と Plan Phase が大事

いろいろな人が言及している話ではあるがここがすべてを握っていると言っても過言ではないと感じました。というのもこのアプリ開発、一度途中で収集がつかなくなって0からやり直しています(それ込みで開発期間1日です)。そして一回目の開発で「Explorer Phaseで十分な設計ができないまま開発に進み、コードがぐちゃぐちゃになった」という事象が発生していました。「ExplorerフェーズとPlanフェーズで仕様を明確にしてからCodeフェーズへつなげる」というテクニックがどのようなタスクをさせる上でも有効だと思います。
また手順書ではExplorer Phase とPlan Phaseでのみ think を使っていました。これもテクニックとして有用だと感じました。特に「ここで設計をバチッと決める」みたいなところは惜しまず ultra think を使いましょう。

2. CLAUDE.md がむちゃくちゃ大事

これも一回目の開発で失敗したことから得られた知見です。CLAUDE.md さえしっかり記述されていれば、指示や設計が適当でも致命的なことにはならなそうな雰囲気を感じます。今回の場合、Next.jsやTypescriptについて何も知らない自分は CLAUDE.md の生成も Claude Codeに任せていましたが、これが大正解だったようです。
自分がClaude Codeの記事を片っ端から集めてベストプラクティスを作らせたのと同じ要領で、使ってみたい技術に関する記事を集めてそれらを集約して CLAUDE.md を作らせるというのもかなり有用な気がします。

3. 定期的に動作確認をすべき

実装に入ってからは Claude Code が1人で黙々とコードを生成するフェーズになります。しかしそれを黙ってみているとあとあと動作しないとなったときのデバッグが大変になります。Claude Codeに渡すタスクは適当に分割して、都度動作を確認するとよいでしょう。少なくとも今回のように「実装全部作る → テスト全部書く」はプロジェクトの規模が小さいから許されたのであって、現実的には避けるべきだと思います。
テスト駆動開発と Claude Code の相性の良さが取り上げられたりもしていますが 実際相性はいいと思います。今度はテスト駆動開発オンリーでやらせてみるのも面白そうです。

あとがき

あらためてバカみたいな内容ですが「Claude Codeを使ってみた」としてはかなり面白いと思いますし知見は多いと思います。「Claude使い倒してみたい!」、「Web開発やってみたいけどどこからはじめたらいいのか...」みたいな人にはおすすめです!
せっかくアプリを作ったのでちゃんとNext.jsとTypescriptを勉強して、アプリ開発も引き続き頑張っていく所存です。

最後に参考までに今回の開発で使用した Claude Codeの利用料金見積もりを載せておきます。Maxを契約しましょう!!

参考記事

Cloude Code公式ドキュメント
Cloude Code ベストプラクティス(公式)
Cloude Code ベストプラクティス
Claude Code 中級者ガイド
Claude Codeのあるコーディング
Claude Codeを徹底解説してみた(後編)
Next.js 14 + TypeScript + Tailwind + ESLint + Prettier 環境構築手順
Next.jsアプリケーションのVercel + Supabase + Prisma構成における本番環境と開発環境での環境構築ガイド

Discussion