Last verified: 2026-05-05
Use this process when adding or changing application behavior. Keep changes small, preserve the layered architecture, and let tests follow the testing pyramid.
- Read the relevant domain's
types/layer first. Domain schemas define the shape everything else must obey. - Check quality.md for known gaps in the area you are touching.
- Check testing.md before choosing test coverage.
- Check react.md before changing UI components or hooks.
- Check openapi.md before changing HTTP routes, API payloads, or generated client usage.
- Prefer existing domain patterns over new abstractions.
Domain dependencies flow forward:
Types -> Config -> Repo -> Service -> Runtime -> UI
For a new feature, usually work in this order:
types/: add or update Zod schemas, inferred types, constants, and boundary-safe value objects.config/: add defaults or environment parsing when behavior needs configuration.repo/: add database or external data access and parse returned rows before leaving the layer.service/: add business rules and orchestration. Keep this testable with injected dependencies.runtime/: add route contracts, routes, handlers, jobs, or adapters. Parse request input at the boundary.ui/: add React components and hooks for browser-visible behavior. UseuseStatefor local interaction state and TanStack Query for server state. Use the generated API client for HTTP calls. Do not useuseEffect.
Skip layers that do not apply. Do not bypass lower layers just to make the change faster.
When a feature adds or changes HTTP behavior:
- Define request, response, and path parameter schemas in the domain
types/layer. Response schemas must describe JSON payloads, not internal service objects. - Add or update the domain route contract in
runtime/contract.ts, includingmethod,operationId,path,responses, andclientmetadata for browser-callable routes. - Register the contract from
src/api-contracts.ts. - Run
pnpm api:generateto refreshsrc/generated/openapi.generated.jsonandsrc/generated/api-client.generated.ts. - Use the generated TanStack Query helpers from UI code instead of hand-written
fetch,queryKey,queryFn, ormutationFnwrappers.
Use openapi.md for the exact contract shape, client metadata fields, and verification checklist.
Generated API artifacts are committed source artifacts. pnpm build runs pnpm api:check, so stale OpenAPI/client output should fail validation before merge.
- Add or update co-located unit tests for most logic.
- Add integration tests when the behavior depends on Postgres, route wiring, provider behavior, migrations, or another real boundary.
- Add e2e tests for critical browser journeys and visible failure states.
- Add contract/generator tests when route metadata, generated OpenAPI output, or generated client behavior changes.
- Avoid duplicating the same assertion at every layer. Unit tests should cover combinations; e2e tests should prove the journey works.
For source-only changes:
pnpm lint
pnpm test:unit
pnpm buildFor API, database, UI, or browser-visible changes:
pnpm lint
pnpm api:check
pnpm test
pnpm check:docsFor Docker, production startup, or image changes:
pnpm lint
pnpm test:unit
pnpm build
pnpm build:image
pnpm check:docsUse pnpm start, pnpm seed, pnpm health, pnpm logs, and pnpm stop when you need to inspect the running stack manually. Use pnpm preview for a built pseudo-production smoke check.
- Update testing.md when commands or test expectations change.
- Update react.md when UI patterns or component rules change.
- Update openapi.md when API contract generation or generated client conventions change.
- Update production.md when production image, Compose, runtime, or deployment commands change.
- Update quality.md when you improve coverage or identify a durable gap.
- Update architecture.md only when the layer model or dependency rules change.
- Add a focused design note only for decisions that future agents must understand to modify the feature safely.