Files
agentic-dev/docs/architecture/overview.md

2.5 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
  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.