diff --git a/docs/README.md b/docs/README.md index 7995ee5..276e854 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,25 +16,29 @@ condensed, cross-linked curriculum. ## `reference/` — information -| Doc | What it is | -| ------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | -| [architecture/ARCHITECTURE.md](reference/architecture/ARCHITECTURE.md) | The architecture walkthrough: contexts/layers, state management, parse-don't-validate, the feature recipe, the .NET backend seam. | -| [architecture/0001-bff-lite-decision-dtos.md](reference/architecture/0001-bff-lite-decision-dtos.md) | ADR — BFF-lite endpoints + decision DTOs (backend decides, FE renders). | -| [architecture/0002-user-groups-and-bounded-contexts.md](reference/architecture/0002-user-groups-and-bounded-contexts.md) | ADR — user groups as actors; identity vs authorization. | -| [architecture/0003-cibg-huisstijl.md](reference/architecture/0003-cibg-huisstijl.md) | ADR — adopt CIBG Huisstijl (vendored Bootstrap 5.2) + the token bridge. | -| [architecture/0004-stamdata-as-code.md](reference/architecture/0004-stamdata-as-code.md) | ADR — business-tunable reference data as typed, compile-time-validated config (not a production DB). | -| [stamdata.md](reference/stamdata.md) | How stamdata (config-as-code reference data) is laid out, how to add a table with zero UI code, and why coupling stays low. | -| [audit-log.md](reference/audit-log.md) | How the data-minimised authz/PII-reveal audit trail is built, how to audit a new action, and the one-producer-hub coupling. | -| [feature-flags.md](reference/feature-flags.md) | How runtime feature flags work (catalog-as-code + runtime state), how to add one, and the hand-wired gating coupling to watch. | -| [fp-tea-atomic-design.md](reference/fp-tea-atomic-design.md) | Long-form learning guide: FP + The Elm Architecture + atomic design. | -| [wcag-checklist.md](reference/wcag-checklist.md) | Manual WCAG checks automation can't catch (tab order, focus traps, reflow). | -| [ui-ux-audit.md](reference/ui-ux-audit.md) | Early UI/UX audit against NL Design System (predates ADR-0003 — read in that light). | +| Doc | What it is | +| ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [architecture/ARCHITECTURE.md](reference/architecture/ARCHITECTURE.md) | The architecture walkthrough: contexts/layers, state management, parse-don't-validate, the feature recipe, the .NET backend seam. | +| [architecture/0001-bff-lite-decision-dtos.md](reference/architecture/0001-bff-lite-decision-dtos.md) | ADR — BFF-lite endpoints + decision DTOs (backend decides, FE renders). | +| [architecture/0002-user-groups-and-bounded-contexts.md](reference/architecture/0002-user-groups-and-bounded-contexts.md) | ADR — user groups as actors; identity vs authorization. | +| [architecture/0003-cibg-huisstijl.md](reference/architecture/0003-cibg-huisstijl.md) | ADR — adopt CIBG Huisstijl (vendored Bootstrap 5.2) + the token bridge. | +| [architecture/0004-stamdata-as-code.md](reference/architecture/0004-stamdata-as-code.md) | ADR — business-tunable reference data as typed, compile-time-validated config (not a production DB). | +| [stamdata.md](reference/stamdata.md) | How stamdata (config-as-code reference data) is laid out, how to add a table with zero UI code, and why coupling stays low. | +| [audit-log.md](reference/audit-log.md) | How the data-minimised authz/PII-reveal audit trail is built, how to audit a new action, and the one-producer-hub coupling. | +| [feature-flags.md](reference/feature-flags.md) | How runtime feature flags work (catalog-as-code + runtime state), how to add one, and the hand-wired gating coupling to watch. | +| [scaffolding.md](reference/scaffolding.md) | How code generation & scaffolding work: plop generators (`gen:value-object`/`gen:form-machine`), the NSwag client (`gen:api`), showcase snippets, and the skill recipes. | +| [roles-and-access.md](reference/roles-and-access.md) | The roles/actors + capability model: who can do what, how to switch roles in dev, and what each unlocks. | +| [architecture/dependencies.md](reference/architecture/dependencies.md) | Bounded-context + atomic-layer boundaries: the allowed-import rules, how they're enforced (`dep:check`) and visualized (`dep:graph`). | +| [architecture/dependency-graph.md](reference/architecture/dependency-graph.md) | Generated mermaid graph of contexts × layers (regenerate with `npm run dep:graph`). | +| [fp-tea-atomic-design.md](reference/fp-tea-atomic-design.md) | Long-form learning guide: FP + The Elm Architecture + atomic design. | +| [wcag-checklist.md](reference/wcag-checklist.md) | Manual WCAG checks automation can't catch (tab order, focus traps, reflow). | +| [ui-ux-audit.md](reference/ui-ux-audit.md) | Early UI/UX audit against NL Design System (predates ADR-0003 — read in that light). | ## `project/` — administration | Doc | What it is | | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | -| [backlog/README.md](project/backlog/README.md) | The work-package backlog index (WP-01…WP-28) — the live tracker. | +| [backlog/README.md](project/backlog/README.md) | The work-package backlog index (WP-01…WP-48) — the live tracker. | | [prd/0001-mijn-aanvragen-en-wizardstatus.md](project/prd/0001-mijn-aanvragen-en-wizardstatus.md) | PRD — "Mijn aanvragen": running wizards, application status, document preview. | | [prd/0002-attribute-based-access-control.md](project/prd/0002-attribute-based-access-control.md) | PRD — attribute-based access control in the UI. | | [SHOWCASE-ROADMAP.md](project/SHOWCASE-ROADMAP.md) | Superseded roadmap (absorbed into `project/backlog/`) — kept for history. | diff --git a/docs/project/backlog/README.md b/docs/project/backlog/README.md index 944042f..c20bb92 100644 --- a/docs/project/backlog/README.md +++ b/docs/project/backlog/README.md @@ -76,7 +76,7 @@ for its existing violations, so every WP ends green. | [WP-29](WP-29-stamdata-beheer-editor.md) | Stamdata beheer editor (low-code, PR-emitting) | follow-on · ADR-0004 | done | | [WP-30](WP-30-ci-perf-followups.md) | CI performance follow-ups (node_modules cache, runner image, path filters) | follow-on · CI/infra | todo | | [WP-31](WP-31-shared-store-helpers.md) | Shared store helpers (ActionState/SaveState, history, debounced-save, RemoteData) | 7 · refinements | done | -| [WP-32](WP-32-stamdata-undo.md) | Undo/redo in the stamdata editor | 7 · refinements | done | +| WP-32 | Undo/redo in the stamdata editor (folded into WP-31 — no separate file) | 7 · refinements | done | | [WP-33](WP-33-dev-switchers.md) | In-app dev switchers (scenario + role) | 7 · refinements | done | | [WP-34](WP-34-adres-phone-brp-readonly.md) | Adres: phone field + BRP address read-only | 7 · refinements | done | | [WP-35](WP-35-one-concept-per-type.md) | One Concept per case type (server-enforced) | 7 · refinements | done | diff --git a/docs/reference/scaffolding.md b/docs/reference/scaffolding.md new file mode 100644 index 0000000..2b5b791 --- /dev/null +++ b/docs/reference/scaffolding.md @@ -0,0 +1,86 @@ +# Scaffolding & code generation — how it works + +How new code and boilerplate get generated in this repo. Three mechanisms, by design: +**runnable plop generators** for the pure-TS leaf patterns, **standalone node generators** +for the two committed-but-generated artifacts (`gen:api`, `gen:snippets`), and +**skill-driven recipes** (`.claude/skills/`) for the patterns too awkward to templatize. +The split is deliberate — [WP-43](../project/backlog/WP-43-scaffold-generators.md) +shipped only the two leaf generators and kept the harder patterns as skills. + +## The rule: generate the boilerplate, not the judgement + +Anything mechanical and shape-stable gets a generator (value objects, form machines — each +ships with its co-located spec so the "pure logic must have a spec" rule holds by default). +Anything that spans a template `{{ }}` clash, the C# backend, or a design decision stays a +**skill recipe** — a generator there adds little over the prose. + +## Plop generators (runnable) + +Config: `plopfile.mjs`; templates: `plop-templates/*.hbs` (Handlebars, prettier-ignored). + +- **`npm run gen:value-object`** — branded value object + `parseX` parser + spec + ("parse, don't validate"). Prompts for `context` + PascalCase `name`; emits + `src/app/{context}/domain/value-objects/{name}.ts` and its `.spec.ts`. +- **`npm run gen:form-machine`** — Elm-style Model/Msg/pure-`reduce` state machine + spec. + Prompts for `context` + `name`; emits `src/app/{context}/domain/{name}.machine.ts` + spec. +- **`npm run gen`** — interactive menu (pick a generator). +- Positional args skip the prompts: `npx plop value-object registratie KvkNummer`. + +> ⚠ Each generated `$localize` id needs an English `` in +> `src/locale/messages.en.xlf` before `npm run ci` — the localize gate fails otherwise. + +## Typed API client — `npm run gen:api` + +Regenerates the FE⇄BE seam from the backend's OpenAPI doc (config: `nswag.json`). +The script builds `BigRegister.Api`, emits `backend/swagger.json` via `dotnet swagger`, then +NSwag regenerates the Fetch-based client into +`src/app/shared/infrastructure/api-client.ts`. Both `swagger.json` and `api-client.ts` are +**committed and never hand-edited** — a CI drift gate fails if they're stale. Run it after +any backend contract change (see the `bff-endpoint` skill). + +## Showcase snippets — `npm run gen:snippets` + +`scripts/gen-snippets.mjs` extracts `// #region showcase:` … `// #endregion` blocks +from real source files into `src/app/showcase/snippets.generated.ts`, so the teaching +showcase shows code identical to what ships. Committed, prettier-ignored, and drift-gated in +CI (`gen:snippets && git diff --exit-code`). + +## Skill recipes (`.claude/skills/`) + +Patterns kept as recipes rather than generators — invoke by name (`/`): + +- **`new-feature`** — the house pipeline: domain → infrastructure → application → UI last. +- **`new-context`** — scaffold a new bounded context (folders, alias, boundary rule, route). +- **`value-object`** / **`form-machine`** — the two above; each points at its `gen:*` command. +- **`bff-endpoint`** — screen-shaped read: C# endpoint + DTO + `gen:api` + adapter + store + + ``. Skill, not generator (spans backend + regen). +- **`mutation-command`** — a write op: adapter method + `submit-*` command returning `Result`. +- **`ui-component`** — shared atom/molecule/organism + Storybook story. Skill because the + Angular template `{{ }}` collides with Handlebars. +- **`new-ssp`** — bootstrap a whole new portal from this template (keep/strip/rename/re-seed). +- **`document-feature`** — ship docs in the same diff (this doc came from it). +- **`test-strategy`** — where specs live by layer. + +## Bootstrapping a whole new SSP + +Today the `new-ssp` skill is a **manual** fork-and-strip recipe (keep `shared/` + tooling, +strip the business contexts, re-seed the backend, re-run `gen:api`). See the skill for the +step-by-step and its GREEN-at-every-step verify gate. + +## Not yet built + +- **`gen:context`** ([WP-44](../project/backlog/WP-44-context-generator.md)) — a runnable + version of the `new-context` skill. Planned, not shipped. +- **`create-ssp`** ([WP-45](../project/backlog/WP-45-create-ssp-generator.md)) — + mechanised `new-ssp`. Planned, not shipped. + +Don't assume either command exists — use the corresponding skill until they land. + +## See also + +- `plopfile.mjs` + `plop-templates/` — the leaf generators. +- `.claude/skills/` — the recipe library. +- `nswag.json` — the typed-client generation config. +- `scripts/gen-snippets.mjs` — the showcase snippet extractor. +- [ARCHITECTURE.md](architecture/ARCHITECTURE.md) — the NSwag client seam in context. +- [WP-43](../project/backlog/WP-43-scaffold-generators.md) — why only leaves got generators.