SasaTech Architecture
概要
Feature-Based Layered Architecture for Next.js (App Router) with Supabase のスキル。
Handler / Service / Repository / Adapter の4レイヤー構成と、機能(Features)単位のモジュール分割パターンを定義する。 ガイド(設計思想・実装方法)とルール(制約・判定基準)の2種類のドキュメントで構成する。
ガイドとルール
| 項目 | ガイド | ルール |
|---|---|---|
| 目的 | アーキテクチャの理解を深める | 実装時の制約を定義する |
| 内容 | HOW/WHY — 設計思想、実装方法、コード例 | DO/DON'T — 判定基準、NG/OK例 |
| 形式 | チュートリアル形式 | 構造化されたルール形式 |
| 使用場面 | 学習時、設計判断時 | 実装時、コードレビュー時 |
| 配置 | guides/ | rules/ |
How to Use
このスキルと併せて、以下の外部スキルの導入を推奨する。
npx skills add https://github.com/supabase/agent-skills --skill supabase-postgres-best-practices
npx skills add https://github.com/vercel-labs/agent-skills --skill vercel-react-best-practices
npx skills add https://github.com/vercel-labs/agent-skills --skill web-design-guidelines
| スキル | 用途 |
|---|---|
supabase-postgres-best-practices | Supabase / PostgreSQL のクエリ最適化、RLS、マイグレーション |
vercel-react-best-practices | React / Next.js のコンポーネント設計、パフォーマンス最適化 |
web-design-guidelines | アクセシビリティ、レスポンシブデザイン、UI/UX |
Default Stack
| カテゴリ | 技術 |
|---|---|
| Framework | Next.js (App Router) |
| Database / BaaS | Supabase |
| Language | TypeScript |
| Validation | Zod |
| Data Fetching | SWR |
| Logging | pino |
| Formatter | Biome |
| Linter | Biome + ESLint |
About Feature-Based Layered Architecture
Feature-Based Layered Architecture for Next.js (App Router) with Supabase
レイヤー構成
Handler リクエスト/レスポンス、バリデーション、楽観的認証
↓
Service ビジネスロジック、厳密な認可、複数 Repository 連携
↓
Repository データアクセス
Adapter 外部 API 連携(Stripe, Resend 等)
ディレクトリ構成
src/
├── app/ # Next.js App Router
│ ├── (auth)/ # 認証が必要なルートグループ
│ ├── (public)/ # 公開ルートグループ
│ └── api/ # API Routes (薄いエントリーポイント)
│
├── features/ # 機能単位のモジュール
│ └── [feature]/
│ ├── index.server.ts # サーバー専用の公開API(Service, Handler)
│ ├── index.client.ts # クライアント利用可の公開API(Fetcher, 型)
│ └── core/
│ ├── schema.ts # Zodスキーマ + 型定義
│ ├── handler.ts # リクエスト / レスポンス処理 (server-only)
│ ├── service.ts # ビジネスロジック (server-only)
│ ├── repository.ts # データアクセス (server-only)
│ ├── adapter.ts # 外部API連携 (server-only)
│ ├── fetcher.ts # API呼び出し
│ └── hooks.ts # SWR Hook等
│
├── components/ # 共通UIコンポーネント
├── hooks/ # 共通Hooks
├── lib/ # ユーティリティ
│ └── adapters/ # 外部サービス連携
└── types/ # 共通型定義、Supabase生成型
Guides
| ガイド | 説明 |
|---|---|
| architecture.md | Feature-based Layer Architecture の全体設計。レイヤー構成、責務分離、ディレクトリ構成 |
| architecture/handler.md | Handler層の実装。リクエスト処理、バリデーション、楽観的認証、エラーハンドリング |
| architecture/service.md | Service層の実装。ビジネスロジック、厳密な認可、Repository/Adapter連携、トランザクション管理 |
| architecture/repository.md | Repository層の実装。データアクセスの抽象化、Supabaseクエリのカプセル化 |
| architecture/adapter.md | Adapter層の実装。外部サービス(決済、メール、AI等)との連携をカプセル化 |
| authentication.md | 二段階認証・認可戦略。楽観的認証(Handler)と厳密な認可(Service)の実装パターン |
| testing.md | レイヤーごとのテスト戦略。Unit / Integration テストの範囲とモック方針 |
| database.md | データベース設計。コメント規約、マイグレーション、Supabase との連携 |
| logging.md | pino を使用した構造化ログの実装。レイヤーごとのログ出力方針 |
| setup.md | 新規プロジェクトのセットアップ手順。依存パッケージ、基盤ファイルの配置 |
| fetch-strategy.md | データ取得戦略。SSR/CSRの選択基準と実装パターン |
| error-handling.md | AppErrorクラスとwithHTTPErrorによるエラーハンドリング設計 |
| wrappers.md | withHTTPError(Handler)のラッパーユーティリティ |
Rules
カテゴリ
| カテゴリ | Prefix |
|---|---|
| アーキテクチャ | arch- |
| データ | data- |
| サーバーサイド保護 | server- |
| スキーマ・型定義 | schema- |
| レスポンス | response- |
| テスト | test- |
| バリデーション | validation- |
| 命名規則 | naming- |
| フロントエンド | frontend- |
インパクト
Impact は、違反時にアーキテクチャへ与える影響の深刻度で定義する。
| Impact | 基準 |
|---|---|
| CRITICAL | アーキテクチャの根幹が壊れる。違反するとこの設計パターン自体が成立しない |
| HIGH | アーキテクチャの整合性や保守性を大きく損なう |
| MEDIUM | コードの品質や一貫性を低下させる |
| LOW | 開発体験やパターンの統一に関する推奨事項 |
アーキテクチャ (arch-)
| ルール | Impact | 説明 |
|---|---|---|
| arch-three-layers | CRITICAL | Handler → Service → Repository, Adapter の構成を必ず経由 |
| arch-feature-structure | CRITICAL | 機能単位で features/ にモジュール化 |
| arch-external-services | HIGH | Stripe, Resend 等の外部サービスは Adapter 経由 |
| arch-logging-strategy | MEDIUM | pino で構造化ログ、console.log 禁止 |
| arch-fetch-strategy | CRITICAL | SSR/CSR問わず、fetcher経由でAPI Route呼び出し |
| arch-logging-levels | MEDIUM | ログレベルをレイヤーと状況に応じて使い分け |
| arch-auth-strategy | HIGH | Handler層で楽観的認証、Service層で厳密な認可。共有ヘルパー関数禁止 |
| arch-auth-operations | HIGH | SignOut、SignInWithOTP等の認証操作はService層に実装、Handler層での直接実行禁止 |
| arch-public-api | MEDIUM | Feature の公開APIは index.server.ts(Service, Handler)と index.client.ts(Fetcher, 型)で分離管理 |
| arch-handler-route-separation | HIGH | API Routeは薄いエントリーポイントに限定、ロジックはHandler層に分離 |
| arch-transaction-rpc-required | HIGH | 複数テーブル更新のトランザクション処理はSupabase RPC関数を使用 |
| arch-adapter-placement | MEDIUM | 汎用Adapterはlib/adapters/、Feature固有Adapterはfeatures/*/core/に配置 |
| arch-feature-adapter-isolation | MEDIUM | Feature内Adapterが他Featureの内部Adapterに依存することを禁止 |
データ (data-)
| ルール | Impact | 説明 |
|---|---|---|
| data-pagination | HIGH | 全件取得禁止、MAX_LIMITでサーバー側上限を強制、ページネーション必須 |
| data-comment-required | LOW | テーブル・カラムに日本語コメント必須 |
| data-rls-required | CRITICAL | 全テーブルでRLS有効化必須、最低1つのポリシーを定義 |
| data-migration-cli-required | MEDIUM | マイグレーションファイルはSupabase CLIで生成、手動作成禁止 |
| data-update-trigger-required | MEDIUM | 全テーブルにupdated_at/update_user自動更新トリガーを適用 |
| data-select-minimal | MEDIUM | select('*')を避け、必要なカラムのみを指定 |
サーバーサイド保護 (server-)
| ルール | Impact | 説明 |
|---|---|---|
| server-supabase-via-api | CRITICAL | クライアントから Supabase 直接使用禁止、API Route 経由必須 |
| server-only-directive | HIGH | Handler/Service/Repository/Adapter に import 'server-only' を必須で記述 |
| server-no-public-env | HIGH | 機密情報(Supabase, API キー)に NEXT_PUBLIC_ 禁止 |
| server-webhook-signature-validation | CRITICAL | Webhook署名検証必須、署名なしでのペイロードパース禁止 |
スキーマ・型定義 (schema-)
| ルール | Impact | 説明 |
|---|---|---|
| schema-single-source | HIGH | 型定義は schema.ts に一元化、types.ts 作成禁止 |
| schema-zod-infer | MEDIUM | Input 型は手書きせず z.infer<typeof schema> で導出 |
レスポンス (response-)
| ルール | Impact | 説明 |
|---|---|---|
| response-with-http-error | HIGH | Handler関数は withHTTPError でラップ必須 |
| response-apperror | MEDIUM | エラーは AppError クラスでスロー、生の Error 禁止 |
| response-helpers | LOW | AppResponse.ok(), AppResponse.created() 等のレスポンスヘルパーを使用 |
| response-adapter-errors | HIGH | Adapter層は外部APIエラーをAppErrorに変換してスロー |
テスト (test-)
| ルール | Impact | 説明 |
|---|---|---|
| test-layer-mocking | HIGH | 各レイヤーは直下の依存のみをモック |
| test-server-only | MEDIUM | server-only はテスト環境でモック必須 |
| test-file-location | LOW | テストファイルは __tests__ に配置 |
| test-naming | LOW | テストは日本語で意図を明確に |
バリデーション (validation-)
| ルール | Impact | 説明 |
|---|---|---|
| validation-request | MEDIUM | リクエスト入力値(ボディ、パスパラメータ、クエリパラメータ)をZodでバリデーション |
命名規則 (naming-)
| ルール | Impact | 説明 |
|---|---|---|
| naming-files | LOW | ファイル・ディレクトリ名は kebab-case(フレームワーク規約ファイルを除く) |
| naming-methods | LOW | Repository: findMany/findById、Service: get*/create* |
| naming-exports | MEDIUM | _ prefix内部実装 + ファイル末尾でexport集約 |
フロントエンド (frontend-)
| ルール | Impact | 説明 |
|---|---|---|
| frontend-data-fetching | LOW | Featureごとにfetcher.tsとhooks.tsを作成、コンポーネントから直接fetch禁止 |