docs(architecture): rewrite overview for vertical feature architecture
This commit is contained in:
@@ -1,55 +1,58 @@
|
||||
# Architecture Overview
|
||||
|
||||
## Clean Architecture Monorepo
|
||||
A vertical-feature monorepo. Business capabilities are top-level packages; non-business foundations are `core-*`.
|
||||
|
||||
This template implements Uncle Bob's Clean Architecture in a Turborepo + pnpm monorepo. The core principle: **dependencies point inward only**.
|
||||
## Package map
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ Frameworks & Drivers (outermost) │
|
||||
│ Next.js, TanStack Start, Payload CMS, │
|
||||
│ Storybook, PostgreSQL, Docker │
|
||||
│ ┌─────────────────────────────────────────┐ │
|
||||
│ │ Interface Adapters │ │
|
||||
│ │ tRPC routers, Controllers, Presenters │ │
|
||||
│ │ ┌─────────────────────────────────┐ │ │
|
||||
│ │ │ Application (Use Cases) │ │ │
|
||||
│ │ │ Business logic, interfaces │ │ │
|
||||
│ │ │ ┌─────────────────────────┐ │ │ │
|
||||
│ │ │ │ Entities (innermost) │ │ │ │
|
||||
│ │ │ │ Models, Errors, Zod │ │ │ │
|
||||
│ │ │ └─────────────────────────┘ │ │ │
|
||||
│ │ └─────────────────────────────────┘ │ │
|
||||
│ └─────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
packages/
|
||||
# Foundation (no business logic)
|
||||
core-shared/ Generic primitives — Payload field/block helpers, tRPC init/context, lib utilities
|
||||
core-cms/ Composition only: assembles feature CMS exports into one Payload config
|
||||
core-api/ Composition only: aggregates feature tRPC routers into one appRouter
|
||||
core-trpc/ Frontend tRPC client + per-framework providers (Next.js, TanStack)
|
||||
core-ui/ Design-system primitives (atoms, molecules, generic organisms, templates)
|
||||
|
||||
# Business capabilities
|
||||
auth/ Users + sign-in/sign-up/sign-out + session/cookie domain
|
||||
blog/ Articles collection + publishing flow
|
||||
media/ Media upload collection (skeleton; expand with optimization, CDN, etc.)
|
||||
marketing-pages/ Pages collection + SiteSettings global
|
||||
navigation/ Header global + menu items
|
||||
|
||||
# Tooling
|
||||
eslint-config/ Shared ESLint flat config + boundary rules
|
||||
typescript-config/ Shared tsconfig + vitest base
|
||||
```
|
||||
|
||||
## Package Map
|
||||
## Data flow
|
||||
|
||||
```
|
||||
packages/core → Clean architecture (entities, use cases, infra, DI)
|
||||
packages/api → tRPC routers (calls core controllers)
|
||||
packages/api-client → Shared React Query hooks + provider
|
||||
packages/cms-core → Payload CMS config, collections, hooks
|
||||
packages/cms-client → Dual-mode Payload client (local + HTTP)
|
||||
packages/ui → Atomic Design + shadcn/ui + Tailwind v4
|
||||
|
||||
apps/web-next → Next.js 15 reference app
|
||||
apps/web-tanstack → TanStack Start reference app
|
||||
apps/cms → Thin Next.js shell for Payload admin
|
||||
apps/storybook → Centralized Storybook instance
|
||||
React component
|
||||
↓ useQuery(trpc.blog.articleBySlug.queryOptions(...)) ← ui/query.ts (typed tRPC client)
|
||||
HTTP /api/trpc
|
||||
↓
|
||||
tRPC procedure ← integrations/api/router.ts
|
||||
↓ .input(zod).query(...)
|
||||
Controller (Zod safeParse) ← interface-adapters/controllers/
|
||||
↓
|
||||
Use case ← application/use-cases/
|
||||
↓ container.get(SYMBOL)
|
||||
Repository implementation ← infrastructure/repositories/ (@injectable)
|
||||
↓ getPayload({ config })
|
||||
Payload Local API → Postgres
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
## Three enforcement layers
|
||||
|
||||
```
|
||||
UI → useQuery(trpc.content.list) → tRPC Router → Controller → Use Case → Repository → Payload Local API → PostgreSQL
|
||||
```
|
||||
1. **`package.json` deps** — only declare allowed deps
|
||||
2. **`exports` map** — each package exposes a small public surface (`.`, `./cms`, `./api`, `./di/bind-production`)
|
||||
3. **ESLint `eslint-plugin-boundaries`** — three tags (`app`, `feature`, `core`); two composition exceptions (`core-api` may import `@repo/<feature>/api`; `core-cms` may import `@repo/<feature>/cms`)
|
||||
|
||||
## Key Design Decisions
|
||||
## Per-feature DI containers
|
||||
|
||||
- **InversifyJS DI** — symbol-based resolution, documented in di/AGENTS.md
|
||||
- **Dual-mode CMS client** — Local API for server-side (no HTTP overhead), HTTP for external
|
||||
- **Atomic Design** — atoms/molecules/organisms/templates, co-located stories
|
||||
- **tRPC single data path** — all data (including CMS content) flows through tRPC
|
||||
- **Agent-optimized docs** — AGENTS.md at every level with rules, recipes, tables
|
||||
Each feature owns its own InversifyJS `Container` + symbol table. No shared symbols, no cross-feature DI coupling. Tests rebind per feature without touching others. Apps call `bindProduction*(config)` per feature at boot to swap the default mock implementations for Payload-backed ones.
|
||||
|
||||
## Spec reference
|
||||
|
||||
`docs/architecture/vertical-feature-spec.md` is the canonical design.
|
||||
|
||||
Reference in New Issue
Block a user