モノレポ概要
モノレポの構造とアプリの整理方法を理解する。
モノレポとは?
モノレポ(モノリシックリポジトリ)は、複数のプロジェクト、アプリケーション、共有コードを含む単一のリポジトリです。各アプリに個別のリポジトリを持つ代わりに、すべてが1か所にまとめられています。
Vibe Coderにとってのメリット
- 共有コード:共通のユーティリティ、型、設定がすべてのアプリで共有される
- 一貫したパターン:すべてのアプリが同じ構造と規則に従う
- 単一の情報源:1つの
CLAUDE.mdファイルにすべてのガイドラインが含まれる - 簡単なコラボレーション:Claudeがコードベース全体のコンテキストを理解できる
リポジトリ構造
vibe-coding-platform/
├── apps/ # すべてのアプリケーションがここに
│ ├── example-app/ # アプリの例
│ ├── breakfast-tracker/ # 別のアプリ
│ └── your-new-app/ # あなたのアプリはここに
├── shared/ # 共有リソース(この3つだけ)
│ ├── database/ # データベーススキーマ(Prisma)
│ ├── auth/ # Auth API + Auth UI
│ └── schema.md # 全テーブルの一覧(人間が読む用)
├── templates/ # 新規プロジェクト用テンプレート
├── CLAUDE.md # AI開発ガイドライン
└── package.json # ルートワークスペース設定
プラットフォーム構成
このファウンデーション版では次を提供します。
- 認証の一元化(Auth UI + Auth API:マジックリンク、パスキー、端末パスワード)
- 会社ごとの 1 つの Postgres(Neon の
DATABASE_URL)— 認証テーブルとアプリデータ - 全アプリのランチャー App Portal
- GitHub Actions → Railway デプロイと Cloudflare DNS によるカスタムドメイン
apps/ 配下の各アプリは独立した Next.js サービスです。共有 middleware で認証し、pg で会社 DB にデータを保存します。
カスタムドメイン(staging / production)
各デプロイ後、CI が Railway カスタムドメインと Cloudflare DNS レコードを作成します。
- ドメイン形式:
{service-name}.{RAILWAY_APP_DOMAIN_SUFFIX} - GitHub Environment ごとに
RAILWAY_APP_DOMAIN_SUFFIXを設定(例:apps.staging.acme.com/apps.acme.com) - 同環境に
CLOUDFLARE_API_TOKENとCLOUDFLARE_ZONE_IDが必要
apps/ディレクトリ
apps/ディレクトリ内の各アプリは、以下を持つスタンドアロンのNext.jsアプリケーションです:
package.json- 依存関係とスクリプトapp/ディレクトリ - Next.js App Routerページdeploy.config.yml- Railwayデプロイ設定
アプリの命名規則
アプリはケバブケース(小文字とハイフン)を使用します:
| ✅ 正しい | ❌ 間違い |
|---|---|
app-portal | AppPortal |
breakfast-tracker | breakfast_tracker |
my-new-app | myNewApp |
shared/ディレクトリ
複数のアプリが使用できる共有リソース。中身はちょうど次の3つです(ls shared/ で確認できます):
| パス | 目的 | 編集権限 |
|---|---|---|
shared/database/ | すべてのテーブルのPrismaスキーマ | Vibe coder(レビュー付き) |
shared/auth/ | 中央集約型の認証サービス(auth-api/、auth-ui/) | 開発者のみ |
shared/schema.md | 全テーブルを人間が読める形でまとめた一覧 | Vibe coder(レビュー付き) |
さらに詳しく: データベース、認証とアクセス制御、ファイルストレージ。
ストレージや型が shared/ にない理由
各アプリは独立してビルド・デプロイされるため、アプリが shared/ のランタイムコードをimportすることはできません。アプリが実行するコードは、必ずそのアプリの中に置きます。次の機能はどれも実際に使えます。共有ディレクトリに置く代わりに、アプリごとに有効にする形になっているだけです:
| 機能 | 有効にする方法 |
|---|---|
| ファイルストレージ | apps/example-app/app/_lib/storage.ts を自分のアプリにコピーし、自分の deploy.config.yml の secrets: に BUCKET_* を対応付ける。詳しい手順はファイルストレージ |
| 通知メール | 同じ要領で apps/example-app/app/_lib/email.ts をコピーし、secrets: に APP_EMAIL_* を対応付ける |
| TypeScript型 | 使うコードのそばで、アプリの中に宣言する |
アプリごとに有効にするのは意図的な設計です。ファイルを保存しないアプリはバケットの鍵を持たず、メールを送らないアプリはメールの鍵を持ちません。
データベースアクセス
アプリはランタイムのデータベースクエリにpgライブラリ(Prismaクライアントではなく)を使用します。テンプレート付属のgetDb()ヘルパーを使い、SQLインジェクション対策として必ずパラメータ化クエリ($1, $2, …)を使ってください:
import { getDb } from '@/app/_lib/db';
const db = getDb();
const result = await db.query(
'SELECT * FROM my_app_users WHERE id = $1',
[userId]
);
const users = result.rows;注意: データベースクエリはデプロイ環境(PRプレビューまたは本番)でのみ実行されます。スキーマとマイグレーションの全体フローはデータベースを参照してください。
知っておくべき重要ファイル
CLAUDE.md(ルート)
AI開発で最も重要なファイル。以下を含みます:
- コーディング標準と規則
- Gitワークフロールール
- データベースガイドライン
- デプロイ手順
アプリ固有のファイル
各アプリには独自のドキュメントがある場合があります:
| ファイル | 目的 |
|---|---|
README.md | アプリの概要とセットアップ手順 |
CLAUDE.md | アプリ固有のAIガイドライン |
PLAN.md | 開発進捗と計画された作業 |
モノレポでの作業
コマンドの実行
常にリポジトリルートからコマンドを実行します。アプリをローカルで動かすことはありません — PRを開けばステージングと本番ですべて動きます(デプロイ参照)。ローカルで実行するのは、コミット前にCIと同じチェックを再現するビルドだけです:
# コミット前にビルドを確認(CIが走らせるのと同じチェック)
pnpm build:your-app-name依存関係のインストール
アプリディレクトリ内でpnpm installを実行しないでください:
# ✅ 正しい:リポジトリルートから実行
pnpm install
# ❌ 間違い:アプリディレクトリ内で実行しない
cd apps/my-app && pnpm install新しい依存関係の追加
# 特定のアプリに追加
pnpm --filter my-app-name add date-fns
# 開発依存関係として追加
pnpm --filter my-app-name add -D @types/some-packageクイズ
pnpm installはどこで実行すべきですか?