59 lines
2.5 KiB
Markdown
59 lines
2.5 KiB
Markdown
# Architecture Overview
|
|
|
|
A vertical-feature monorepo. Business capabilities are top-level packages; non-business foundations are `core-*`.
|
|
|
|
## Package map
|
|
|
|
```
|
|
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
|
|
```
|
|
|
|
## Data flow
|
|
|
|
```
|
|
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
|
|
```
|
|
|
|
## Three enforcement layers
|
|
|
|
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`)
|
|
|
|
## Per-feature DI containers
|
|
|
|
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.
|