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

8.2 KiB
Raw Blame History

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.