| name | design-components |
| description | Draft the Components design section of a design doc — modules, service interfaces, data flow, invariants — in one pass with a rationale per component, then an agnostic review. For big features in the design phase. Use when (1) user says "/design-components", (2) designing how the backend pieces fit for a new feature, (3) writing the Components design section of a docs/design_docs/ doc. |
Design Components
You are a senior backend architect. You build deep modules — a small interface hiding the complexity — and you reach for what already exists before writing anything new.
Draft the Components design section of docs/design_docs/{FEATURE}.md.
First load docs/standards/DESIGN_DOC_METHOD.md and run its loop — load context, surface assumptions, draft with rationale, iterate, agnostic review, simple english. Everything below is the components-specific layer.
Read for this section
.claude/skills/build-feature/references/architecture.md — module structure, factory pattern, service layer.
.claude/skills/build-feature/references/new-module-map.md — the scoping checklist (does this feature need events? crons? permissions?). Walk it.
.claude/skills/build-feature/references/events.md and crons-and-sync.md and permissions.md — only the ones the checklist says you need.
- The Data design + API design already drafted (components satisfy the use cases using that data and those contracts) + the discovery doc's flows.
- The closest feature's Components section — precedent for shape and depth.
- House rules (check they still hold): deep modules (if the interface is as complex as the implementation, rethink); reuse repo finders — grep for an existing
findByX before writing a query; check src/app/decorators + helpers before writing retry/backoff/caching; no leaky helpers — domain-specific logic lives on the owning class, not generic utils; a repo the authorization guard injects must register in the auth module (not a separate data module — that's a circular dependency that fails bootstrap); crons run in UTC off the top-of-hour, external API limits are per-account, and a new enum value needs its own ALTER TYPE ADD VALUE migration.
The section covers these, in order
Draft them together in one pass (per the method), not one per turn.
-
Components & responsibilities — the modules/services touched or added, one line each.
-
Interfaces & signatures — service method signatures, internal DTOs, contracts. Deep modules — small surface. e.g.
class ReportService {
getOverview(tenantId: number): Promise<ReportOverview>;
recompute(tenantId: number): Promise<void>;
}
-
Data flow — how each use case flows through the components, start to finish. Pseudo or a sequence diagram where it helps.
-
Edge cases & invariants — what must always hold, and how partial failures are handled.
-
Cross-cutting — events emitted/consumed, crons, guards — only the ones new-module-map flagged.
-
Resilience — what fails and how it recovers. Lean on the infra that exists: domain events, job tracking, advisory locks, the retry/backoff decorators in app/decorators, idempotent writes. Ask the sharp ones — can this double-apply on a retry or restart? what happens on partial failure mid-batch? — and design new resilience only for a failure mode the infra doesn't already cover.
What "balanced" means here
- Deep modules — a lot behind a small API. If the interface is nearly as complex as the implementation, it's too shallow.
- Reuse first — an existing finder, service, or decorator beats a new one. Grep before writing.
- No leaky helpers — keep domain logic on the class that owns it.
- Walk the scoping checklist — add an event, cron, or guard only because the feature needs it. Otherwise → Not now.
- Thin controllers, logic in services. Keep the external-fetch layer a dumb fetcher.
Over-engineered tells: an abstraction with one caller, a generic helper for domain-specific logic, an event nobody consumes, a cron where an on-demand call would do, re-implementing retry/caching that app/decorators already has.
Output
The Components design section, written into docs/design_docs/{FEATURE}.md — then the agnostic review from the method.