Files
atomic-design-poc/docs/SHOWCASE-ROADMAP.md
Edwin van den Houdt 0aada9037e docs: showcase roadmap (Storybook-as-curriculum, FP primitives, enforcement)
Prioritised backlog from a three-part analysis of the atomic-design + FP showcase:
concrete P1-P3 items per track with file paths, teaching value, and effort.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 18:35:37 +02:00

97 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Showcase roadmap
Prioritised backlog for making this POC a stronger teaching showcase for **atomic
design + FP in the UI** — optimising for maintainability, speed, and low cognitive load
for junior *and* senior developers.
## How to read this
Each track below is a table of concrete items: **Item · Where · Why · Effort · Priority**.
Nothing here is built yet — pick items off the top. Priorities: **P1** = highest
teaching-value-per-effort, do first; **P2** = strengthens the showcase; **P3** = backlog.
Effort is a rough solo estimate.
This roadmap is deliberately scoped to three tracks (Storybook-as-curriculum, FP
primitives, Enforcement depth). A fourth track — onboarding docs (GETTING-STARTED,
GLOSSARY, layer-dependency diagram, ADR index) — was identified but de-scoped for now.
### Current strengths (what NOT to touch)
The foundations are already exemplary and should be preserved as-is:
- **Pure reducers / state machines** — `*.machine.ts` model illegal states away with
tagged unions; effects live in commands, never in `reduce`.
- **`RemoteData<E,T>`** (`src/app/shared/application/remote-data.ts`) — `map`/`map2`/
`map3`/`andThen`/`fromResource`/`foldRemote`, rendered via the `<app-async>` molecule.
- **Parse-don't-validate value objects** (`src/app/registratie/domain/value-objects/`) —
branded types built only through a `Result`-returning parser.
- **Anti-corruption parsers** at every DTO seam (`infrastructure/*.adapter.ts`).
- **ESLint-enforced layer boundaries** (`eslint.config.mjs`): no `any`, `domain/` imports
no Angular, cross-context direction locked.
- **Storybook** — 96% story coverage, a11y addon + docs addon on, titled `Layer/Name`.
- **Token linting** (`npm run check:tokens`) blocks hardcoded colours.
The gaps below are about *teaching reach*, not correctness.
---
## Track A — Storybook as a curriculum
Storybook is the showcase vehicle, but today it renders isolated components with no
narrative. `.storybook/main.ts` already globs `../src/**/*.mdx` and loads
`@storybook/addon-docs`, so MDX pages drop in with zero config.
| Item | Where | Why (teaching value / cognitive load) | Effort | Prio |
|------|-------|----------------------------------------|--------|------|
| **Atomic-design primer (MDX)** | `src/docs/atomic-design.mdx` | The pyramid + the "each layer imports only below" rule, with a *live* composition chain of real components: `button` (atom) → `form-field` (molecule) → `document-upload` (organism) → `page-shell` (template). Links to the ESLint rules that enforce it. Gives newcomers the mental model before they read code. | 23h | P1 |
| **Design-token gallery (MDX)** | `src/docs/design-tokens.mdx` | RHC colours, the `--rhc-space-max-*` spacing scale (with resolved px), typography; plus when to use a raw `--rhc-*` token vs. an `--app-*` wrapper from `src/styles.scss`. Answers the senior's "what's the actual value of `--rhc-space-max-md`?" and ties to `check:tokens`. | 2h | P1 |
| **FP-in-the-UI primer (MDX)** | `src/docs/fp-in-ui.mdx` | A Storybook front door to the concepts already in `src/app/showcase/concepts.page.ts` and `docs/fp-tea-atomic-design.md` (RemoteData, machine, parse-don't-validate) so the component library and the FP guide cross-link instead of living apart. | 1.5h | P1 |
| **`argTypes` / controls** | high-traffic atom stories: `button`, `text-input`, `radio-group`, `status-badge`, `alert` (`src/app/shared/ui/*/*.stories.ts`) | Lets devs explore every variant from the Controls panel instead of editing story code. Fastest "play with it" path for juniors. | 1.5h | P2 |
| **Anatomy story for `async`** | `src/app/shared/ui/async/async.stories.ts` | Show all four states (Loading / Empty / Failure / Success) in one view — it teaches the exhaustive fold but doesn't currently *display* it exhaustively. | 45m | P2 |
| **`play` / interaction tests** | 23 stories (button disabled-during-submit; `form-field` error announced via `role="alert"`; `async` retry calls `reload()`) | Demonstrates behaviour, not just appearance, and doubles as regression cover. Feeds Track C's CI gate. | 2h | P2 |
| **Shell story** | `src/app/shared/layout/shell/shell.stories.ts` | The only component with no story; a canvas showing the persistent header/footer completes the library. | 30m | P3 |
---
## Track B — FP primitives
The pure core is excellent but under-demonstrates a few composition tools; learners
currently hand-branch and reinvent them.
| Item | Where | Why (teaching value / cognitive load) | Effort | Prio |
|------|-------|----------------------------------------|--------|------|
| **`Result` combinators** | `src/app/shared/kernel/fp.ts` (+ new `fp.spec.ts`) | Add `map`, `mapErr`, `andThen`, `fold`, `getOrElse`. Today only direct `r.ok ? … : …` branching exists — fine for one step, painful across a pipeline. **Biggest single FP gap.** Then refactor **one** real call site to show `parse ▸ mapErr(localize) ▸ map(toDomain)`. | 1.5h | P1 |
| **Value-object specs** | `postcode.spec.ts`, `uren.spec.ts`, `big-nummer.spec.ts` next to `src/app/registratie/domain/value-objects/*.ts` | The repo's own rule is "domain must have a spec," yet only `email` does. Cover normalisation (`"1234AB"``"1234 AB"`), boundaries, and invalid inputs. Closing this makes the rule credible and teaches value-object testing. | 1h | P1 |
| **Property-based test example** | one spec (e.g. Postcode normalisation idempotence, or the `RemoteData.map` functor-composition law); adds `fast-check` dev-dep | Every current test is example-based. One law-based test shows how to catch edge cases you didn't enumerate. **Flag:** introduces a new dev dependency — justified because property testing is an explicit teaching goal. | 1h | P2 |
| **`NonEmptyArray<T>` helper** | `src/app/shared/kernel/fp.ts`; use for `vraagIds` / required upload categories | Makes "at least one" a *type* rather than a runtime check — a crisp "make illegal states unrepresentable" lesson applied to collections. | 1h | P3 |
| **Effect/command testability (note)** | `src/app/registratie/application/{draft-sync,submit-*}.ts` | Direction only, not built here: inject the HTTP effect so commands are unit-testable without a full component. Documents how to close the one untested layer. | — | P3 |
---
## Track C — Enforcement depth
ESLint checks imports; several documented rules are otherwise only hoped-for. Turning
them into machine-checked guarantees is itself a teachable "fitness function" pattern.
| Item | Where | Why (teaching value / cognitive load) | Effort | Prio |
|------|-------|----------------------------------------|--------|------|
| **Architecture-fitness test** | `src/architecture.spec.ts` + `npm run check:architecture`, wired into `.github/workflows/ci.yml` | A vitest that scans `domain/` for Angular/HTTP/RxJS imports and asserts cross-context direction. Belt-and-suspenders over ESLint, and a worked example of an executable architecture rule. | 2h | P1 |
| **a11y as a CI gate** | Storybook test-runner + axe (or vitest + axe on rendered atoms), added to `ci.yml` | The a11y addon's checks are visible in the panel but not enforced. Gating them turns "we care about a11y" into a guarantee — high value for a design-system showcase. | 23h | P1 |
| **Interaction tests in CI** | run Track-A `play` tests via the Storybook test-runner in `ci.yml` | Makes behavioural stories part of the pipeline, not just docs. | 1h | P2 |
| **Domain coverage gate** | vitest coverage threshold on `domain/**` | Guarantees the "domain must have a spec" rule holds as the code grows. | 45m | P3 |
| **Dependency-graph visual** | `madge` script producing an SVG/JSON of the layer graph | A generated picture makes the architecture graspable at a glance and catches accidental edges. | 45m | P3 |
---
## Suggested sequencing
Do P1 across tracks, interleaved so each shows value early:
1. **[B]** `Result` combinators + value-object specs — small, self-contained, immediate.
2. **[A]** the three MDX pages — the visible "showcase" upgrade.
3. **[C]** architecture-fitness test + a11y-in-CI — locks the guarantees in.
Then P2 (controls, anatomy/interaction stories, property test, interaction tests in CI).
P3 items are backlog. None of this changes runtime behaviour or the public component
API; it is additive teaching + enforcement.