Files
agentic-dev/docs/architecture/overview.md
Danijel Martinek 2c2375920f docs: reflect tooling-package rename + Turbo boundaries enforcement
- Rename eslint-config → core-eslint, typescript-config → core-typescript
  in all docs (package map, AGENTS.md, overview.md, dependency-flow.md, etc.)
- Document the five-tag model (app, feature, core, core-composition,
  tooling) — refinement of ADR-006's three-tag mention
- Document core-trpc's core-composition tag (transitively reaches features
  through core-api's AppRouter type)
- Note Turborepo boundaries as a second enforcement layer alongside ESLint
- Add ADR-010 explaining the two-layer enforcement decision and
  five-tag refinement

Files updated:
- docs/architecture/overview.md: package map, enforcement layers, five-tag section
- docs/architecture/dependency-flow.md: boundary rules, enforcement strategy
- docs/architecture/vertical-feature-spec.md: package names, five-tag model
- AGENTS.md: package map, boundary rules, commands
- CLAUDE.md: tooling package names, quick-start command
- packages/core-eslint/AGENTS.md: tag clarification
- packages/core-typescript/AGENTS.md: tag clarification
- packages/core-api/AGENTS.md: core-composition tag
- packages/core-cms/AGENTS.md: core-composition tag
- packages/core-trpc/AGENTS.md: core-composition tag + rationale
- docs/decisions/adr-010-turbo-boundaries.md: new ADR

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 12:24:04 +02:00

88 lines
3.6 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
core-eslint/ Shared ESLint flat config + boundary rules
core-typescript/ 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. **Two parallel automated checks**:
- **ESLint `eslint-plugin-boundaries`** (lint-time) — enforces boundary rules at linting
- **Turborepo `boundaries`** (build-graph time) — validates entire workspace dependency graph, including transitive reaches
Both use the same five-tag model; see "Five tags" section below.
## Five tags
The workspace is organized into five mutually exclusive tags:
- **app** (4 packages): `apps/cms`, `apps/web-next`, `apps/web-tanstack`, `apps/storybook`
- **core-composition** (3 packages): `packages/core-api`, `packages/core-cms`, `packages/core-trpc`
- **core** (2 packages): `packages/core-shared`, `packages/core-ui`
- **feature** (5 packages): `packages/auth`, `packages/blog`, `packages/media`, `packages/marketing-pages`, `packages/navigation`
- **tooling** (2 packages): `packages/core-eslint`, `packages/core-typescript`
**Allowed dependency directions:**
| Tag | May depend on |
|---|---|
| app | app, core, core-composition, feature, tooling |
| core-composition | core, core-composition, feature, tooling |
| core | core, core-composition, tooling |
| feature | core, tooling |
| tooling | tooling |
**Composition exceptions:**
- `core-api` may import from `@repo/<feature>/api` subpath exports only
- `core-cms` may import from `@repo/<feature>/cms` subpath exports only
- `core-trpc` reaches features transitively through `core-api`'s `AppRouter` type
## 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.