スターターの内側

Sushi SaaS の構造

スターターが強制するルート、サービス、モデル、データベースの各レイヤーと、独立した管理アプリを解説します。

Sushi SaaS は「データは明確なレイヤーを下方向に流れる」という一つの規則で構成されています。単なるフォルダーの推奨ではなく、境界を越える import はアーキテクチャテストで拒否されます。

アプリケーション内の流れ

src/app/**       ルートとページ

src/services/**  業務ルールとオーケストレーション

src/models/**    型付き永続化

src/db/**        スキーマ、マイグレーション、接続

ルートは HTTP を変換します。サービスは冪等性、認可、台帳ルール、副作用などの不変条件を持ちます。db() を呼べるアプリケーション層はモデルだけで、データベース制約が並行処理に対する最後の境界です。

ブラウザー側にも明確な分離があります。Server Component はサービスを直接呼び、Client Component は src/api/** のラッパーと共通 API client を使います。サーバーから自分自身への HTTP 呼び出しと、コンポーネントごとの独自なレスポンス処理を避けるためです。

実行可能な規則とエラー形式はアーキテクチャとエラー契約を参照してください。

全ドメインが同じレイヤーを使う

組織、課金、クレジット、ストレージ、予約、タスクは、別々の小さなアプリではありません。各ドメインが同じ水平レイヤーを横断します。たとえばクレジット消費はルートから入り、サービスで認可と冪等性を保証し、モデルで保存し、台帳制約で保護します。

この一貫性により、新しい責務を置く場所が一つに決まります。テナント境界については組織とチームを参照してください。

管理コンソールは独立アプリ

apps/admin は独自のページ、管理 API、データアクセス、MFA ゲート、読み書きロールを持つ別の Next.js アプリです。スキーマと中核認証は共有しますが、別オリジンにデプロイでき、顧客アプリから運用ルートを分離します。

デプロイ前に管理コンソールの設定とアクセスを確認してください。

拡張時に守る境界

  • 業務不変条件はルートではなくサービスに置く。
  • DB アクセスはコンポーネントやサービスではなくモデルに置く。
  • プラン名の比較ではなく capability を確認する。
  • 管理専用のクエリと endpoint は apps/admin に置く。
  • 実装契約が変わったらバージョン管理された runbook も更新する。

このガイドは starter commit 7580470 に照らして確認済みです。

Sushi SaaS の構造 · Sushi SaaS