Files
agentic-dev/CLAUDE.md
Danijel Martinek bffc6a96b3 docs(plan-8): partial Lazar doc-update pass (CLAUDE.md, overview.md, ADR-012, Plan 7 annotations)
First slice of the Plan 8 deferred doc-update checklist:
- CLAUDE.md Key Conventions: factory-function use cases/controllers,
  entities/models/<x>.ts paths, .toDynamicValue DI bindings, direct
  injection in tests
- docs/architecture/overview.md data-flow box updated to factory style
  (controller resolved via container.get<IXController>; use case factory
  takes deps as args)
- docs/decisions/adr-012-lazar-conformance.md created — records the
  conformance decision and four intentional divergences
- docs/superpowers/plans/2026-05-05-plan-7-tdd-foundation.md and the
  matching spec annotated with a "pre-Plan-8 layout" note pointing at
  the refactor log

Remaining Plan 8 doc-update items (root AGENTS.md, per-feature AGENTS.md,
adding-a-feature.md, tdd-workflow.md, testing-strategy.md,
vertical-feature-spec.md §6/§10, core-testing AGENTS.md) intentionally
paused — Plan 9 (input/output unification) will change overlapping
content, so resuming after Plan 9 lands avoids double-churn.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 09:17:35 +02:00

3.6 KiB

Clean Architecture Monorepo Template

Quick Start

pnpm install          # Install all dependencies
pnpm dev              # Start all dev servers
pnpm build            # Build all packages
pnpm test             # Run all tests
pnpm turbo boundaries # Validate workspace dependency graph
docker compose up -d  # Start PostgreSQL

TDD

pnpm test --watch --filter @repo/<feature>   # watch one feature
pnpm test -- --coverage                      # full run with coverage
pnpm test:stories                            # Storybook smoke tests
pnpm test:e2e                                # Playwright e2e

See docs/guides/tdd-workflow.md for the full cycle.

Project Overview

Turborepo + pnpm monorepo organized by vertical features. Each feature (auth, blog, media, marketing-pages, navigation) owns its Clean Architecture layers. Core packages (core-shared, core-cms, core-api, core-trpc, core-ui) provide foundation. Two tooling packages (core-eslint, core-typescript) provide shared configs. Workspace boundaries are enforced by ESLint (lint-time) and Turborepo (build-graph time). Supports Next.js and TanStack Start as frontend frameworks, Payload CMS for content management, and comprehensive agent-optimized documentation.

Read First

  • AGENTS.md — Package map, boundary rules, per-package conventions
  • docs/architecture/overview.md — High-level architecture and package responsibilities
  • docs/architecture/vertical-feature-spec.md — Design spec with rationale and decision log
  • docs/guides/adding-a-feature.md — End-to-end new feature walkthrough

Key Conventions

  • Relative imports in src/ — Source files use relative paths (../repositories/...), not @/ alias
  • @/ alias in tests — Test files (*.test.ts) use @/ to import from src/
  • vitest.config.ts — Every package must define resolve.alias: { "@": path.resolve(__dirname, "./src") }
  • tsconfig.json rootDir — Set "rootDir": "." so TypeScript finds both src/ and test files
  • Lazar-conformant file layout — Entities live at entities/models/<x>.ts; errors at entities/errors/<domain>.ts + entities/errors/common.ts; mock siblings use the .mock.ts suffix (<x>.repository.mock.ts); real repository impls drop the payload- prefix (<x>.repository.ts); interface filenames are dot-separated (<x>.repository.interface.ts)
  • Factory-function use cases & controllers — Every use case and controller is (deps) => async (input) => result; each exports export type I*UseCase = ReturnType<typeof xUseCase> (and the analogous I*Controller); one controller per use case (no multi-method controllers)
  • DI uses .toDynamicValue() for factoriesbind<IXUseCase>(SYMBOL).toDynamicValue((ctx) => xUseCase(ctx.container.get(...))); mocks remain the default binding
  • Tests inject mocks directly — Construct MockXRepository and pass into the factory: signInUseCase(mockUsers, mockAuth)(input). No container rebinding in unit tests
  • Payload repositories via constructor — Feature packages receive Payload config at constructor time, not as a direct dependency
  • App bootstrap — Each app calls bindProduction*() per feature at startup to swap mocks for real Payload-backed impls in the InversifyJS containers

MCP Servers

Start Storybook before UI work: pnpm dev --filter @repo/storybook

Storybook MCP available at http://localhost:6006/mcp — use list-all-documentation to discover existing components before creating new ones.

Key Ports

Service Port
Next.js 3000
Payload CMS 3001
TanStack Start 3002
PostgreSQL 5432
Storybook 6006