docs: reorganize into project/ + reference/, expand Storybook Foundations

Move working docs (backlog, prd, roadmap) under docs/project/ and durable
docs (architecture ADRs, guides, audits) under docs/reference/; add a
docs/README.md index. Update every path reference in code comments, CLAUDE.md,
READMEs, and the new-ssp skill. Expand the Storybook Foundations curriculum
(Overview, BDD, i18n; rename Layers→Domain-Driven Design) and reorder the sidebar.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
eho
2026-07-20 20:33:32 +02:00
co-authored by Claude Opus 4.8
parent 55a0a2d166
commit d4e5a76873
40 changed files with 1699 additions and 1087 deletions
+36
View File
@@ -0,0 +1,36 @@
# Documentation
Docs are split by **kind**, and kept out of each other's way:
- **`reference/` — information.** How the system works and why: architecture, decisions
(ADRs), the FP/TEA/atomic learning guide, accessibility and UX reference. Stable
knowledge, not tied to a sprint.
- **`project/` — administration.** Planning and tracking: the work-package backlog,
product requirements (PRDs), and the (superseded) roadmap. This is the moving,
process-facing material.
Teaching material that is best read **next to the components** lives in Storybook, not
here — see the **Foundations** section (`src/docs/*.mdx`), starting at *Foundations →
Overview*. The `reference/` docs are the long-form source; the Foundations pages are the
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. |
| [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. |
| [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. |
+1 -1
View File
@@ -1,6 +1,6 @@
# Showcase roadmap — superseded
**This roadmap is superseded by [`docs/backlog/`](backlog/README.md)** (2026-07-02).
**This roadmap is superseded by [`docs/project/backlog/`](backlog/README.md)** (2026-07-02).
The backlog absorbs and corrects this document: its Storybook-as-curriculum track became
WP-14/15 (+ per-invariant MDX pages in WP-05/07/08/13/17), its enforcement track became
+1 -1
View File
@@ -5,7 +5,7 @@ design-system fidelity, DDD/FP consistency, Storybook as curriculum, and WCAG co
with automated gates. Source: the architecture/CIBG/a11y audit of 2026-07-02 (plan:
"Showcase hardening").
This backlog **supersedes `docs/SHOWCASE-ROADMAP.md`**.
This backlog **supersedes `docs/project/SHOWCASE-ROADMAP.md`**.
## Session protocol
+1 -1
View File
@@ -55,7 +55,7 @@ build", so every story added or changed by later WPs is automatically covered.
6. Run locally against a fresh `build-storybook`; triage violations: fix trivial ones
(labels, roles, contrast via `--rhc-*` tokens); anything structural gets the escape
hatch + comment + WP cross-ref.
7. Update `docs/backlog/README.md`: GREEN now includes `npm run test-storybook:ci`.
7. Update `docs/project/backlog/README.md`: GREEN now includes `npm run test-storybook:ci`.
## Acceptance criteria
@@ -11,7 +11,7 @@ Phase 0 — a pure move of wiring, no behavior change.
## Read first
- `CLAUDE.md` §1, `docs/ARCHITECTURE.md`
- `CLAUDE.md` §1, `docs/reference/architecture/ARCHITECTURE.md`
- `eslint.config.mjs`
- `src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts` (lines
~18-19: `BrpAdapter`/`parseBrpAddress`, `DuoAdapter`/`parseDuoLookup`)
@@ -38,7 +38,7 @@ Phase 0 — a pure move of wiring, no behavior change.
lookups move behind a registratie `application/` facade (command or store methods)
- `src/app/herregistratie/ui/intake-wizard/intake-wizard.component.ts` — policy resource
moves behind **new** `src/app/herregistratie/application/` (folder doesn't exist yet)
- `docs/ARCHITECTURE.md` — fix "three contexts, four layers" → six contexts
- `docs/reference/architecture/ARCHITECTURE.md` — fix "three contexts, four layers" → six contexts
(shared, auth, registratie, herregistratie, brief, showcase), five layers (+ contracts);
add the showcase sanction
- `CLAUDE.md` §1 — add `brief` to the context list; note the showcase sanction
@@ -10,7 +10,7 @@ principle (every response through a hand-written `parse*` returning `Result`).
## Read first
- `CLAUDE.md` §3 + §4; `docs/architecture/0001-bff-lite-decision-dtos.md`
- `CLAUDE.md` §3 + §4; `docs/reference/architecture/0001-bff-lite-decision-dtos.md`
- `src/app/registratie/infrastructure/applications.adapter.ts` (+ its spec — the pattern
to copy)
- The three offenders below
+2 -2
View File
@@ -5,7 +5,7 @@ Phase: 1 — FP/DDD core
## Why
Docs (`docs/fp-tea-atomic-design.md`, ARCHITECTURE §2c) teach `createStore` as THE
Docs (`docs/reference/fp-tea-atomic-design.md`, ARCHITECTURE §2c) teach `createStore` as THE
wiring, but the wizard pages hand-wire `signal(model)` + local `dispatch()` — juniors see
two idioms and copy the wrong one. Machine naming also drifts:
`change-request.machine.ts` exports bare `State`/`Msg`; `upload.machine.ts` exports
@@ -14,7 +14,7 @@ two idioms and copy the wrong one. Machine naming also drifts:
## Read first
- `src/app/shared/application/store.ts` (`createStore`) + its spec
- `docs/fp-tea-atomic-design.md` Part on TEA-in-Angular
- `docs/reference/fp-tea-atomic-design.md` Part on TEA-in-Angular
- All `*.machine.ts` files (6) and their UI wiring sites (wizard components/pages)
## Decisions (pre-made, don't relitigate)
+1 -1
View File
@@ -59,7 +59,7 @@ no spec despite "domain and pure logic must have a spec" (CLAUDE.md §5).
(`draft-sync.spec.ts`, `submit-change-request.spec.ts`).
- [x] `map3` removed (found in `shared/application/remote-data.ts`, not
`shared/kernel/fp.ts` as the WP text guessed — updated the three docs that
mentioned it: CLAUDE.md, `docs/ARCHITECTURE.md`, `remote-data.mdx`). The
mentioned it: CLAUDE.md, `docs/reference/architecture/ARCHITECTURE.md`, `remote-data.mdx`). The
`variant` input on `confirmation.component.ts` no longer exists — already
cleaned up before this WP ran; nothing to do.
- [x] CLAUDE.md rule added (`Conventions` — DatePipe in templates, `formatDatumNl` in
@@ -35,7 +35,7 @@ the list-family rationale to document.
## Read first
- `docs/architecture/0003-*.md` (ADR-0003 — the token-bridge rationale this extends)
- `docs/reference/architecture/0003-*.md` (ADR-0003 — the token-bridge rationale this extends)
- The audit's gap list (below)
## Decisions (pre-made, don't relitigate)
+3 -3
View File
@@ -41,7 +41,7 @@ Three app-level gaps close the WCAG story:
- `src/app/app.config.ts` + a new small `shared/` focus-on-navigation service
- `eslint.config.mjs`, `package.json` (angular-eslint)
- Any template the new lint rules flag
- New `docs/wcag-checklist.md`
- New `docs/reference/wcag-checklist.md`
- New `src/docs/a11y.mdx` — title `Foundations/Accessibility`
## Steps
@@ -50,7 +50,7 @@ Three app-level gaps close the WCAG story:
focus lands on the new page's heading).
2. Add angular-eslint; enable the template rules on inline templates; plant a bad
pattern, see it fail, remove it; fix real hits.
3. `docs/wcag-checklist.md`: manual checks per page (dashboard, wizards, brief, login) —
3. `docs/reference/wcag-checklist.md`: manual checks per page (dashboard, wizards, brief, login) —
keyboard walk & focus order, no traps, 200% zoom/reflow, NVDA or VoiceOver pass,
visible focus, error announcement; status columns (page × check).
4. `src/docs/a11y.mdx`: the layered approach — axe gate (WP-01) + template lint + play
@@ -75,7 +75,7 @@ Three app-level gaps close the WCAG story:
setup. Less code to hand-maintain, same coverage plus more.
- The dashboard's checklist pass surfaced a **real bug**: `aanvraag-block`'s warning
`app-alert` (two `app-button` actions) overflows the viewport at 320px — its
`.feedback` flex row doesn't wrap. Documented in `docs/wcag-checklist.md` with the
`.feedback` flex row doesn't wrap. Documented in `docs/reference/wcag-checklist.md` with the
root cause, **not fixed** — fixing live component CSS found via the checklist is the
"full manual audit" scope this WP's Out-of-scope section explicitly defers, not this
WP's own deliverable. Flagged here so it isn't lost.
@@ -30,9 +30,9 @@ a real foundation to extend.
## Read first
- `docs/architecture/0002-user-groups-and-bounded-contexts.md` (the `Principal`
- `docs/reference/architecture/0002-user-groups-and-bounded-contexts.md` (the `Principal`
union, identity-vs-authorization split — see the deviation noted below)
- `docs/prd/0002-attribute-based-access-control.md` §5a, §6, §7, §9-P1
- `docs/project/prd/0002-attribute-based-access-control.md` §5a, §6, §7, §9-P1
- `backend/src/BigRegister.Api/Domain/Authorization/Authz.cs` (new — the single
authorization helper)
- `backend/src/BigRegister.Api/Data/BriefStore.cs` (`Review` — now delegates its
@@ -31,7 +31,7 @@ speculatively.
`static Dictionary` + `lock`
- `backend/src/BigRegister.Api/Data/SeedData.cs` (current in-memory seed — becomes
a first-run DB seed)
- `docs/architecture/0001-bff-lite-decision-dtos.md` (confirm this WP doesn't touch
- `docs/reference/architecture/0001-bff-lite-decision-dtos.md` (confirm this WP doesn't touch
the decision-DTO contracts — persistence is purely behind the existing store
interfaces)
@@ -14,11 +14,11 @@ WP-25, editor WP-26) reads what this WP serves.
## Read first
- `docs/prd` — the Brief v2 PRD §2a/§3 (two axes, OrgTemplate model, invariants)
- `docs/project/prd` — the Brief v2 PRD §2a/§3 (two axes, OrgTemplate model, invariants)
- `backend/src/BigRegister.Api/Data/BriefStore.cs` (store idiom + `BriefSeed`)
- `backend/src/BigRegister.Api/Domain/Authorization/Authz.cs` (emit+enforce single source)
- `backend/src/BigRegister.Api/Data/AppDbContext.cs` (JSON-column precedent, WP-22)
- `docs/backlog/WP-18-abac-capability-spine.md` (how the capability spine works)
- `docs/project/backlog/WP-18-abac-capability-spine.md` (how the capability spine works)
## Decisions (pre-made, don't relitigate)
+1 -1
View File
@@ -15,7 +15,7 @@ domain model, `brief.machine.ts`, and every `BriefMsg` stay byte-identical.
- PRD Brief v2 §2b (fidelity note), §4, §10; the sample `voorbeeldbrief-inschrijving.pdf`
- `src/app/brief/ui/letter-composer/letter-composer.component.ts` (the `canEdit` pivot)
- `src/app/brief/ui/letter-preview/letter-preview.component.ts` (rendering that migrates in)
- `docs/backlog/WP-23-org-template-backend.md` (the `orgTemplate` on `BriefViewDto`)
- `docs/project/backlog/WP-23-org-template-backend.md` (the `orgTemplate` on `BriefViewDto`)
## Decisions (pre-made, don't relitigate)
@@ -12,7 +12,7 @@ same composition is archived with the brief, making sent letters immutable.
## Read first
- PRD Brief v2 §2b, §8; `docs/backlog/WP-24-letter-canvas.md` (the `letter.css` contract)
- PRD Brief v2 §2b, §8; `docs/project/backlog/WP-24-letter-canvas.md` (the `letter.css` contract)
- `backend/src/BigRegister.Api/Program.cs` — upload `content` endpoint (binary house
pattern: `.ExcludeFromDescription()` + hand-written FE fetch)
- `src/app/shared/upload/upload.adapter.ts` (hand-written transport precedent)
@@ -12,7 +12,7 @@ content a read-only sample). PRD Brief v2 §5, §7h.
## Read first
- PRD Brief v2 §5, §7h; `docs/backlog/WP-23/24/25` (endpoints, canvas, proefbrief)
- PRD Brief v2 §5, §7h; `docs/project/backlog/WP-23/24/25` (endpoints, canvas, proefbrief)
- `src/app/shared/application/access.store.ts` (`can('orgtemplate:edit')`)
- `.claude/skills/form-machine` — the house form idiom this editor follows
- `src/app/shared/ui/upload/single-upload` (logo upload reuse)
@@ -22,7 +22,7 @@ that keep CLAUDE.md and the backlog truthful.
already covers all `/api/` calls, the new endpoints included), and
`POST /brief/reset`. The demo script documents the mapping; no new interceptor
cases, no scenario code.
- Demo script lives at `docs/prd/0003-brief-v2-demo-script.md` and follows the §6
- Demo script lives at `docs/project/prd/0003-brief-v2-demo-script.md` and follows the §6
choreography (compose → preview → switch sub-org seed → "two axes, one render").
- One e2e spec, not a suite: drafter composes on canvas → submit → approve → send
pins the org-template version; admin publishes → drafter canvas reflects it.
@@ -31,10 +31,10 @@ that keep CLAUDE.md and the backlog truthful.
## Files
- `docs/prd/0003-brief-v2-demo-script.md` (new)
- `docs/project/prd/0003-brief-v2-demo-script.md` (new)
- `e2e/brief-v2.spec.ts` (new)
- story gap-fill where WP-24..27 left holes
- `docs/backlog/README.md` (statuses), `CLAUDE.md` (roles/routes touch-up)
- `docs/project/backlog/README.md` (statuses), `CLAUDE.md` (roles/routes touch-up)
## Steps
+1 -1
View File
@@ -10,7 +10,7 @@ professional logs in, sees their registration, and can apply for
re-registration — "herregistratie").
> New to functional programming or The Elm Architecture? Start with the progressive
> learning guide [`fp-tea-atomic-design.md`](./fp-tea-atomic-design.md), which teaches
> learning guide [`fp-tea-atomic-design.md`](../fp-tea-atomic-design.md), which teaches
> the concepts (with Elm ↔ this-app examples) and the recipes; this document is the
> reference deep-dive it points back to.
+7 -7
View File
@@ -17,7 +17,7 @@ feature." A senior can skim Parts 14 and jump to **Part 5** (FP × atomic des
defined in plain words on first use and again in the **glossary** (Part 8).
This guide is the _teaching_ layer. For the reference deep-dives it points to
[`ARCHITECTURE.md`](./ARCHITECTURE.md) and
[`ARCHITECTURE.md`](./architecture/ARCHITECTURE.md) and
[ADR-0001](./architecture/0001-bff-lite-decision-dtos.md) rather than repeating them.
Every code snippet below is real code from this repo, with its file path.
@@ -127,7 +127,7 @@ Two kinds of type do most of the work:
The decisive move is choosing types so that **illegal states can't be written down**.
Compare three booleans (2³ = 8 combinations, most nonsense) with one union of the 4 real
states — see [`ARCHITECTURE.md` §2a](./ARCHITECTURE.md#2a-remotedata--one-value-instead-of-three-booleans)
states — see [`ARCHITECTURE.md` §2a](./architecture/ARCHITECTURE.md#2a-remotedata--one-value-instead-of-three-booleans)
for the full `RemoteData` treatment and diagram. The wizard's own Model is the same
idea (`herregistratie.machine.ts`):
@@ -216,7 +216,7 @@ This app implements TEA with Angular **signals**. There is no extra state librar
important shape difference from textbook Elm: **state is per-wizard, not one global
Model** — each flow (`herregistratie`, `intake`, `registratie`) has its own little
store. Cross-page state that _must_ be shared lives in one root singleton
(`BigProfileStore`, see [`ARCHITECTURE.md` §2e](./ARCHITECTURE.md#2e-optimistic-update--rollback-and-shared-state-across-pages)).
(`BigProfileStore`, see [`ARCHITECTURE.md` §2e](./architecture/ARCHITECTURE.md#2e-optimistic-update--rollback-and-shared-state-across-pages)).
### 4a. The store — TEA's runtime in ~10 lines
@@ -424,7 +424,7 @@ Molecules compose atoms; organisms compose molecules — exactly like composing
functions, where the composite is still pure. `address-fields` is pure because the
`form-field` and `text-input` it's built from are pure. Each atomic level only uses the
level(s) below it (see the hierarchy diagram in
[`ARCHITECTURE.md` §1](./ARCHITECTURE.md#1-the-big-picture-three-contexts-four-layers)).
[`ARCHITECTURE.md` §1](./architecture/ARCHITECTURE.md#1-the-big-picture-three-contexts-four-layers)).
### 5c. Pages / containers are the TEA runtime (the shell)
@@ -474,7 +474,7 @@ Each property maps to a tangible benefit you can point at in this repo:
- **Illegal states won't compile.** `Submitting` carries `Valid` data and has no `errors`
field, so "submit with errors showing" is unwritable. A whole bug class disappears
before runtime — contrast the 8-state boolean soup in
[`ARCHITECTURE.md` §2a](./ARCHITECTURE.md#2a-remotedata--one-value-instead-of-three-booleans).
[`ARCHITECTURE.md` §2a](./architecture/ARCHITECTURE.md#2a-remotedata--one-value-instead-of-three-booleans).
- **Pure presentational components.** `address-fields` is tested by inputs → DOM and
reused in two call-sites (the registratie wizard and the change-request form) with no
@@ -500,7 +500,7 @@ Each recipe follows the existing pattern and naming, and ends with the same remi
### Recipe A — Add an atomic component (atom / molecule / organism)
**When:** you genuinely need a new building block (not a one-off; reuse must earn it —
see [CLAUDE.md §2](../CLAUDE.md)).
see [CLAUDE.md §2](../../CLAUDE.md)).
**Where:** `shared/ui/` if generic; a context's `ui/` if domain-specific. Pick the level
by composition: composes nothing → **atom**; composes atoms → **molecule**; composes
@@ -634,7 +634,7 @@ _This is the same loop, again — now nested inside the wizard._
---
_See also:_ [`ARCHITECTURE.md`](./ARCHITECTURE.md) (reference deep-dive on RemoteData,
_See also:_ [`ARCHITECTURE.md`](./architecture/ARCHITECTURE.md) (reference deep-dive on RemoteData,
the store, parse-don't-validate, and the .NET backend seam) and
[ADR-0001](./architecture/0001-bff-lite-decision-dtos.md) (the BFF-lite + decision-DTO
decision). Live demo: `/concepts` in the running app.