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

3.6 KiB

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.