Files
atomic-design-poc/.claude/skills/new-feature/SKILL.md
Edwin van den Houdt e82309786d style: format frontend, docs and skills with prettier; add .prettierignore
One-time prettier --write so the new format:check CI gate starts green.
.prettierignore excludes generated (api-client.ts, documentation.json),
vendored (public/cibg-huisstijl), and backend (dotnet format owns it).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 13:39:31 +02:00

2.3 KiB

name, description
name description
new-feature Add a feature (screen, flow, capability) to this Angular SSP following the house pipeline — domain first, then infrastructure, application, UI last. Use whenever building anything user-facing that has business rules or data.

New feature (the pipeline)

Every feature is built inward-out. Never start with the component.

Steps

  1. Domain (<context>/domain/, pure TS, no Angular imports — lint-enforced)

    • Data types + pure rules. Forms/wizards get a *.machine.ts → use the form-machine skill.
    • Raw input that must be valid → branded value object → use the value-object skill.
    • Co-locate a .spec.ts; test the pure functions directly, no TestBed.
    • Server-owned rules stay here only as reference impl + test, marked server-owned; the FE renders the server's decision (ADR-0001).
  2. Infrastructure (<context>/infrastructure/, the only layer that touches HTTP)

    • Read → screen-shaped endpoint + adapter → use the bff-endpoint skill.
    • Write → command adapter returning Result → use the mutation-command skill.
  3. Application (<context>/application/)

    • Shared cross-page state → providedIn: 'root' store exposing RemoteData signals.
    • Page-local flow state → createStore(initial, reduce) from @shared/application/store, held in the component.
    • Side effects live in commands (submit-*.ts), never in the reducer.
  4. UI last (<context>/ui/)

    • A page is composition of existing blocks<app-page-shell>, <app-async>, atoms/molecules from shared/ui. Adding a new building block is the exception → ui-component skill.
    • Templates dispatch messages, never mutate. Async data always renders through <app-async>.
    • All copy via $localize with stable @@context.key ids.
    • Route: lazy loadComponent under the ShellComponent parent in app.routes.ts, canActivate: [authGuard] when protected.

Worked example

The intake wizard slice, end to end:

  • src/app/herregistratie/domain/intake.machine.ts (+ spec)
  • src/app/herregistratie/infrastructure/
  • src/app/herregistratie/ui/ (wizard component + page)

Verify (GREEN gate)

npm run lint && npm run check:tokens && npm test && npm run build
cd backend && dotnet test   # if the backend changed