音声ガイド機能付きの革新的な料理体験を提供するWebアプリケーション
- Node.js 22.x
- pnpm 10.x (推奨パッケージマネージャー)
-
リポジトリをクローン
git clone https://github.com/kantacky/vibe-cooking-web.git cd vibe-cooking-web
-
依存関係をインストール
pnpm install
-
環境設定
.env.development.example
を参考に.env.development
を作成- 必要なFirebase、データベース、API設定を記入
-
開発サーバーを起動
pnpm dev
-
ブラウザでアクセス http://localhost:3000 を開いてアプリケーションを確認
# 開発サーバー起動(Turbopack使用)
pnpm dev
# 本番ビルド
pnpm build
# 本番サーバー起動
pnpm start
# リンティング
pnpm lint
# フォーマット(リンティング修正とPrettierフォーマット)
pnpm format
# テスト実行
pnpm test
# テスト監視
pnpm test:watch
# テストカバレッジ
pnpm test:coverage
# Storybook開発サーバー起動
pnpm storybook
# Storybookビルド
pnpm build-storybook
# APIクライアント生成(OpenAPI仕様からTypeScript型定義を再生成)
pnpm api:generate
# APIドキュメントプレビュー(ブラウザでRedoclyドキュメントを開く)
pnpm api:preview
# Prismaクライアント生成
pnpm db:generate
# Prismaマイグレーション(開発環境)
pnpm db:migrate:dev
# Prismaマイグレーション(本番環境)
pnpm db:migrate:prod
# Prisma Studio(開発環境)
pnpm db:studio:dev
# Prisma Studio(本番環境)
pnpm db:studio:prod
# データベース完全リセット(開発環境)
pnpm db:reset:dev
# データベース完全リセット(本番環境)
pnpm db:reset:prod
# Dockerビルド
docker build -t vibe-cooking .
# ローカルテスト
docker run -p 3000:3000 vibe-cooking
# Google Cloud Runデプロイ
pnpm deploy:gcr
このプロジェクトはNext.js 15.3.3 App RouterをベースとしたAPIファースト開発アプローチで、クライアントサイドとサーバーサイドの両方でレイヤードアーキテクチャを採用しています。**PWA(Progressive Web App)**対応もされており、オフライン機能やホーム画面への追加が可能です。
APIファースト開発: プロジェクトはOpenAPI仕様(openapi/openapi.yaml
)を使用して型安全なTypeScriptクライアントコードを生成します。API仕様はフロントエンドとバックエンド間のデータ契約の信頼できる情報源です。
現在のAPIエンドポイント:
GET /recipes
- レシピ一覧を取得(テキスト検索、タグフィルター、カテゴリフィルター対応)GET /recipes/{id}
- IDで特定のレシピを取得GET /categories
- カテゴリ一覧を取得POST /vibe-recipe
- バイブレシピを作成(音声入力から対話的にレシピを生成)
レイヤードアーキテクチャ
UI Layer (Presentation)
↓
Presenter Layer
↓
Service Layer
↓
Repository Layer
↓
External API / Data Source
- UI Layer: React Components, Next.js Pages, shadcn/ui, Tailwind CSS
- Presenter Layer: React Hooks, Custom Hooks - UIの状態管理
- Service Layer: ビジネスロジック、データ変換
- Repository Layer: データアクセスの抽象化、APIクライアントの管理
- DI Container: 依存関係管理、インスタンス生成
レイヤードアーキテクチャ
API Routes Layer (Next.js App Router)
↓
Controller Layer
↓
Service Layer
↓
Repository Layer
↓
Database Layer (Prisma + PostgreSQL)
- API Routes Layer: HTTPリクエストのルーティング、基本的な認証・認可
- Controller Layer: リクエスト・レスポンスの変換、バリデーション
- Service Layer: ビジネスロジック、トランザクション管理
- Repository Layer: データアクセスの抽象化、Prismaクライアントの管理
- Database Layer: データ永続化、スキーマ管理(Prisma ORM + PostgreSQL)
- DI Container: サーバーサイド各レイヤー間の依存関係管理
vibe-cooking-web/
├── src/
│ ├── app/ # Next.js App Router(UI Layer)
│ │ ├── api/ # API Routes
│ │ ├── recipes/ # レシピ関連ページ
│ │ │ ├── [id]/ # レシピ詳細
│ │ │ └── page.tsx # レシピ一覧
│ │ ├── cooking/ # 調理モードページ
│ │ │ └── [id]/ # 調理手順表示
│ │ ├── candidates/ # バイブレシピ候補ページ
│ │ ├── layout.tsx # ルートレイアウト
│ │ ├── page.tsx # ホームページ
│ │ ├── firebase-init.tsx # Firebase初期化コンポーネント
│ │ ├── manifest.ts # PWAマニフェスト
│ │ ├── service-worker-registration.tsx # Service Worker登録
│ │ └── globals.css # グローバルスタイル
│ ├── components/ # UIコンポーネント
│ │ └── ui/ # shadcn/ui再利用可能コンポーネント
│ ├── client/ # クライアントサイドレイヤー
│ │ ├── di/ # 依存性注入コンテナ
│ │ ├── presenters/ # Presenter Layer
│ │ ├── repositories/ # Repository Layer
│ │ └── services/ # Service Layer
│ ├── server/ # サーバーサイドレイヤー
│ │ ├── controllers/ # Controller Layer
│ │ ├── di/ # 依存性注入コンテナ
│ │ ├── repositories/ # Repository Layer
│ │ │ ├── interfaces/ # リポジトリインターフェース
│ │ │ └── implementations/ # リポジトリ実装
│ │ ├── services/ # Service Layer
│ │ ├── types/ # サーバー固有の型定義
│ │ └── utils/ # ユーティリティ
│ ├── lib/ # 共通ライブラリ
│ │ ├── api-client.ts # 手動実装HTTPクライアント
│ │ ├── database.ts # データベース接続管理
│ │ ├── firebase.ts # Firebase設定
│ │ ├── firebase-admin.ts # Firebase Admin SDK
│ │ ├── middleware/ # ミドルウェア
│ │ │ └── app-check.ts # App Check検証
│ │ └── utils.ts # shadcn/ui用ユーティリティ
│ └── types/ # 型定義
│ └── api.d.ts # 自動生成されたAPI型定義
├── openapi/
│ └── openapi.yaml # OpenAPI仕様書
├── prisma/ # データベーススキーマとマイグレーション
│ ├── schema.prisma
│ └── migrations/
├── components.json # shadcn/ui設定
├── tailwind.config.ts # Tailwind CSS設定
├── jest.config.js # Jest設定
├── .storybook/ # Storybook設定
│ ├── main.ts # Storybook設定
│ └── preview.ts # プレビュー設定
├── public/ # 静的ファイル
│ ├── sw.js # Service Worker
│ ├── icon-192x192.png # PWAアイコン
│ └── icon-512x512.png # PWAアイコン
├── .env.development.example # 開発環境設定例
├── .env.production.example # 本番環境設定例
└── CLAUDE.md # Claude Code向けガイド
- React: 19.1.0 - UIライブラリ
- Next.js: 15.3.3 - React フレームワーク (App Router)
- TypeScript: 5.8.3 - 型安全性
- Tailwind CSS: 4.1.8 - スタイリング
- shadcn/ui: コンポーネントライブラリ
- lucide-react: 0.514.0 - アイコンライブラリ
- embla-carousel-react: 8.6.0 - カルーセルコンポーネント
- sonner: 2.0.5 - トースト通知
- next-themes: 0.4.6 - テーマ管理
- Prisma: 6.9.0 - ORM
- @prisma/client: 6.9.0 - Prismaクライアント
- @google-cloud/cloud-sql-connector: 1.8.1 - Cloud SQL接続
- openapi-fetch: 0.14.0 - API クライアント
- PostgreSQL: データベース
- @google/genai: 1.5.1 - Gemini API
- firebase: 11.9.1 - Firebase SDK
- firebase-admin: 13.4.0 - Firebase Admin SDK
- @firebase/app-check: 0.10.0 - App Check (reCAPTCHA v3)
- Jest: 30.0.0 - テストフレームワーク
- @testing-library/react: 16.3.0 - React テストユーティリティ
- Storybook: 9.0.8 - コンポーネント開発環境
- ESLint: 9.28.0 - コード品質チェック
- Prettier: 3.5.3 - コードフォーマット
- openapi-typescript: 7.8.0 - OpenAPI型定義生成
- @redocly/cli: 1.34.3 - API ドキュメント生成
- dotenv-cli: 8.0.0 - 環境変数管理
- pnpm: 10.x - パッケージマネージャー
- Google Cloud Run: デプロイ
- PWA: Service Worker による オフライン対応
このプロジェクトは API ファースト開発 を採用しています。
openapi/openapi.yaml
を編集してAPIエンドポイントを定義
pnpm api:generate
TypeScript型定義が src/types/api.d.ts
に自動生成されます
pnpm api:preview
ブラウザでインタラクティブなAPIドキュメントを表示
🎵 バイブレシピ機能 (/candidates
)
- 音声入力から対話的にレシピ候補を生成・選択
- 複数のレシピを組み合わせた革新的な料理体験
- Gemini APIによるパーソナライズされたレシピ提案
- 音声認識とAIチャットによる自然な対話
🍳 調理モード (/cooking/{id}
)
- カルーセル形式の手順表示とナビゲーション
- 進捗トラッキングとステップ管理
- 各手順の音声ガイド自動再生機能
- オーディオファイル対応(audioUrl)
📚 レシピ管理
- カテゴリ別フィルター、テキスト検索、タグ検索
- レスポンシブデザイン対応
- リアルタイムデータ取得
- 材料リスト、手順表示、時間管理
📱 PWA機能
- オフライン対応(Service Worker)
- ホーム画面への追加が可能
- アプリライクな体験(スタンドアローンモード)
- プッシュ通知対応
- Recipe: レシピの基本情報、準備・調理時間、材料、手順、カテゴリ、タグ
- Ingredient: 材料名、分量、単位、備考
- Instruction: 手順番号、タイトル、説明、推定時間、画像URL、音声URL
- Category: カテゴリ名(ご飯、おかず、デザート、汁物など)
- VibeRecipe: 音声入力から生成されるレシピ候補、関連レシピIDsと手順配列
- VibeInstruction: VibeRecipeの手順、手順ID、バイブレシピの手順番号、レシピID
- Tailwind CSS 4 を使用
- shadcn/ui コンポーネントライブラリ
- CSS変数でテーマカスタマイズ
- ダークモード自動対応(
prefers-color-scheme
)
- 厳密な型チェック有効
- パスマッピング:
@/*
→./src/*
- 自動生成されたAPI型を活用
- ESLint with Next.js設定
- Prettier自動フォーマット
- Jestでユニットテスト
- テスト駆動開発(TDD)を推奨
- Turbopackで高速開発
プロジェクトは環境に応じて異なるデータベース接続方式をサポートします:
- ローカル開発: 従来のURL接続文字列を使用
- Cloud Run本番環境: Unix Socket + IAM認証を使用
開発環境 (.env.development.example
を参考に作成):
# データベース接続
MAIN_DATABASE_URL="postgres://user:pass@host:port/name"
SHADOW_DATABASE_URL="postgres://user:pass@host:port/name_shadow"
# Firebase設定
NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_project.appspot.com
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=your_measurement_id
NEXT_PUBLIC_RECAPTCHA_SITE_KEY=your_recaptcha_site_key
# 開発環境用デバッグトークン(オプション)
FIREBASE_DEBUG_TOKENS=debug-token-1,debug-token-2
本番環境 (.env.production.example
を参考に作成):
# Cloud SQL IAM認証
GOOGLE_CLOUD_PROJECT=your_project_id
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-key.json
# Unix Socket接続(本番環境)
MAIN_DATABASE_URL="postgres://service-account@email/database?host=/cloudsql/project:region:instance"
データベーススキーマは prisma/schema.prisma
で管理し、マイグレーションでバージョン管理しています。
prisma/schema.prisma
を編集pnpm db:migrate:dev
(開発環境用マイグレーション作成・適用)pnpm db:migrate:prod
(本番環境用マイグレーション適用)- マイグレーションファイルをコミット
プロジェクトは現代的で再利用可能なUIコンポーネントライブラリ shadcn/ui を採用しています。
- スタイル: New York
- ベースカラー: Slate
- CSS変数: 使用
- Tailwind CSS prefix: なし
- アイコンライブラリ: Lucide React
- TypeScript: 完全対応
基本コンポーネント:
Button
: 複数バリアント対応ボタン(default, destructive, outline, secondary, ghost, link)Card
: カードコンポーネント(Header, Title, Description, Content, Footer)Input
: 入力フィールドコンポーネントCarousel
: 画像カルーセルコンポーネント(embla-carousel-reactベース)Progress
: プログレスバーコンポーネントSonner
: トースト通知コンポーネント
ビジネスコンポーネント:
RecipeCard
: レシピカード表示コンポーネントRecipeCardList
: レシピカード一覧表示コンポーネントRecipeDetailHeader
: レシピ詳細ヘッダーコンポーネントCookingInstructionCard
: 調理手順カードコンポーネントInstructionProgress
: 調理進捗表示コンポーネントIngredients
: 材料リスト表示コンポーネントIngredientsItem
: 材料アイテムコンポーネントInstructions
: 手順リスト表示コンポーネントInstructionsItem
: 手順アイテムコンポーネントStepBadge
: ステップ番号バッジコンポーネントTimeCard
: 時間表示カードコンポーネントSelectCount
: 数量選択コンポーネント
ツールコンポーネント:
Loading
: ローディング表示コンポーネントNoContent
: コンテンツなし表示コンポーネント
class-variance-authority
: バリアント管理clsx
: 条件付きクラス名管理tailwind-merge
: TailwindCSSクラスのマージlucide-react
: アイコンライブラリ@radix-ui/react-slot
: プリミティブコンポーネント@radix-ui/react-progress
: プログレスバーコンポーネントembla-carousel-react
: カルーセルライブラリsonner
: トースト通知ライブラリnext-themes
: テーマ管理ライブラリtw-animate-css
: TailwindCSS用アニメーションユーティリティ
コンポーネント開発環境: Storybookを使用してUIコンポーネントの開発・テスト・ドキュメント化を行います。
設定:
- フレームワーク:
@storybook/nextjs
- ストーリーファイル:
src/**/*.stories.@(js|jsx|mjs|ts|tsx)
- アドオン:
@storybook/addon-docs
,@storybook/addon-onboarding
利用可能なストーリー:
- 全UIコンポーネント(Button、Card、Input、Carousel、Progress、Sonner)
- 全ビジネスコンポーネント(Recipe関連、Instruction関連、時間関連コンポーネント)
- ツールコンポーネント(Loading、NoContent)
プロジェクトはFirebase SDKとApp Checkを統合し、セキュリティを強化しています。
src/lib/firebase.ts
: Firebase初期化とApp Check設定src/app/firebase-init.tsx
: クライアントサイドFirebase初期化コンポーネント
- Provider: reCAPTCHA v3
- 初期化: クライアントサイドのみ
- 自動トークンリフレッシュ: 有効
- 開発環境: デバッグトークン対応
- 本番環境: 厳密な検証
AppCheck 検証ミドルウェア:
src/lib/firebase-admin.ts
: Firebase Admin SDK初期化とAppCheckトークン検証src/lib/middleware/app-check.ts
: AppCheck検証ミドルウェアwithAppCheck()
: HOF(高階関数)でAPIハンドラーをラップ- Authorizationヘッダーから
Bearer
トークンを取得・検証
セキュリティレベル:
- 本番環境: サービスアカウントキーによる厳密な検証
- 開発環境: デバッグトークンまたは緩い検証モード
サービスアカウント設定:
- Firebase Consoleでサービスアカウントキーファイルをダウンロード
- Cloud Runにファイルをマウントして
GOOGLE_APPLICATION_CREDENTIALS
にパスを設定 - 環境変数でJSONコンテンツを直接設定する方法も可能
プロジェクトはPWA機能を提供し、ユーザーがアプリのようにWebサイトを使用できます。
設定ファイル:
src/app/manifest.ts
: PWAマニフェストファイル(アプリ名、アイコン、表示モード等)src/app/service-worker-registration.tsx
: Service Worker登録コンポーネントpublic/sw.js
: Service Workerファイル(キャッシュ戦略、オフライン対応等)public/icon-192x192.png
,public/icon-512x512.png
: PWAアイコン
PWA機能:
- インストール可能: ホーム画面への追加が可能
- オフライン対応: Service Workerによるキャッシュとオフライン機能
- アプリライクな体験: スタンドアローンモードでの表示
- レスポンシブデザイン: モバイルファーストのデザイン
PWAマニフェスト設定:
- アプリ名: "Vibe Cooking"
- 表示モード: standalone
- 背景色: #ffffff
- テーマカラー: #000000
- アイコン: 192x192、512x512のPNGファイル
プロダクションアプリケーションはGoogle Cloud Runでホストされています。
Cloud Runデプロイ要件:
- Cloud SQL接続設定が必要(
--set-cloudsql-instances
フラグ) - サービスアカウントにCloud SQL Client権限が必要
- Dockerfileでstandalone出力モードを使用
# Dockerイメージビルド
docker build -t vibe-cooking .
# ローカルテスト
docker run -p 3000:3000 vibe-cooking
# Google Cloud Runデプロイ
pnpm deploy:gcr
- パッケージマネージャー: pnpm 10.x を使用(npm/yarnではない)
- Node.js: バージョン 22.x を使用
- 開発サーバー: 高速ビルドのためにTurbopackを含む(
pnpm dev
) - 生成された型定義を手動編集しない:
src/types/api.d.ts
はpnpm api:generate
で再生成されます - API変更ワークフロー: OpenAPI仕様変更後は必ずクライアントコードを再生成してください
- テスト駆動開発: 新機能実装時はテストを先に実装してください
- shadcn/ui使用: UIコンポーネントは
src/components/ui/
から使用してください - Firebase環境変数: 本番環境では適切なFirebase設定が必要です
- TypeScript厳格モード:
any
型の使用を禁止、具体的な型定義を使用 - ファイル命名規則:
.ts
および.tsx
ファイルはkebab-case
で命名
openapi/openapi.yaml
を修正pnpm api:generate
を実行- 仕様と生成された型定義をコミット
pnpm api:preview
でドキュメント確認
prisma/schema.prisma
を修正pnpm db:migrate:dev
(開発)またはpnpm db:migrate:prod
(本番)を実行- マイグレーションファイルをコミット
- ユニットテストを先に実装
- テストが失敗することを確認
- 機能を実装
- テストが成功することを確認
- CLAUDE.md - Claude Code向けの詳細な開発ガイド
- OpenAPI仕様書 - API仕様の詳細
- Next.js公式ドキュメント - フレームワーク公式ドキュメント
- Tailwind CSS公式ドキュメント - スタイリング公式ドキュメント
- shadcn/ui公式ドキュメント - UIコンポーネント公式ドキュメント
- Prisma公式ドキュメント - ORM公式ドキュメント
- Issueで議論
- フィーチャーブランチを作成
- 変更を実装(TDD方式)
pnpm format
でコードフォーマット- プルリクエストを作成
このプロジェクトは私的使用のため、ライセンスは設定されていません。
開発チーム: ギャFUN!! (gyafun@furari.co)