docs: rewrite the README as the entry point to all documentation
The repo had good docs that nobody could find. The root README linked to exactly two documents, while learning-path.mdx — a 375-line paced three-day onboarding curriculum — had zero inbound links and was reachable only by running Storybook and spotting it in the sidebar. docs/README.md indexes ~20 documents and nothing at the root pointed at it either. The README was also describing the pre-monorepo repo. Its centrepiece atomic-design table was fictional: it claimed the folder structure IS the hierarchy, with atoms/molecules/organisms/templates/pages directories that exist nowhere. The truth is a better story and now replaces it — two orthogonal axes, DDD on disk (context, then layer) and the atomic ladder in the Storybook sidebar, which comes from story titles. Every other path was stale too (src/app/, src/styles.scss, src/locale/, proxy.conf.json), the second app was entirely absent, and 6 of 36 npm scripts were documented, omitting `npm run ci` — the pre-push gate. Adds a signpost table organised by what you are trying to do, a repo map, the commands that matter, and keeps one corrected showcase section so the repo still makes its case. Also fixes the index it now points at: docs/README.md cited Foundations pages at src/docs/*.mdx, claimed the backlog ran to WP-48 (it is at 75 — the range is dropped so it cannot go stale again), and was missing ADR-0006 and the OpenZaak harness. Verified rather than assumed: all 12 README links and every docs/README.md link resolve, every named npm script exists, no stale path survives, and the quick start was executed — backend serves swagger and the API on :5000, behandelportal serves on :4201. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,205 +1,173 @@
|
||||
# BIG-register Self-Service Portal — Atomic Design POC
|
||||
# BIG-register Portals — Atomic Design POC
|
||||
|
||||
A small Angular app that shows how **atomic design** makes a frontend cheap to build,
|
||||
reuse and extend. The domain is the **BIG-register** self-service portal (the Dutch
|
||||
register of healthcare professionals, run by CIBG). It is styled with the **CIBG
|
||||
Huisstijl** design system (a customized Bootstrap 5.2 build, vendored — see ADR-0003),
|
||||
and demonstrates a robust **async-state pattern** where the UI can never reach an
|
||||
inconsistent state.
|
||||
A two-app Angular monorepo showing how **atomic design** plus **domain-driven boundaries** make
|
||||
a frontend cheap to build, reuse and extend. The domain is the **BIG-register** (the Dutch
|
||||
register of healthcare professionals, run by CIBG): a citizen self-service portal and a
|
||||
case-handler backoffice, sharing one design system and one backend.
|
||||
|
||||
> Demo / POC — **no real login** (DigiD is faked) and synthetic seed data. The
|
||||
> business rules and data _are_ served by a real **ASP.NET Core backend**
|
||||
> (`backend/`) consumed through a generated typed client, so the BFF + DDD design
|
||||
> is demonstrable, not hand-waved. A system-font stack stands in for the licensed
|
||||
> Rijksoverheid font and a text wordmark for the logo.
|
||||
It is styled with the **CIBG Huisstijl** (a customized Bootstrap 5.2 build, vendored — ADR-0003)
|
||||
and built around one idea: **make illegal states unrepresentable** — in the UI's async states, in
|
||||
the domain types, and in the tests.
|
||||
|
||||
> **Demo / POC** — **no real login** (DigiD is faked) and synthetic seed data. But the business
|
||||
> rules and data _are_ served by a real **ASP.NET Core backend** (`backend/`) through a generated
|
||||
> typed client, so the BFF + DDD design is demonstrable rather than hand-waved. A system-font
|
||||
> stack stands in for the licensed Rijksoverheid font, and a text wordmark for the logo.
|
||||
|
||||
> **New here?** Run `npm run storybook` and open **Foundations → Learning Path** — a paced,
|
||||
> hands-on three-day route through the codebase, written for a strong programmer who is new to
|
||||
> frontend functional programming. For everything else, **[`docs/README.md`](docs/README.md)** is
|
||||
> the documentation index.
|
||||
|
||||
---
|
||||
|
||||
## Run it
|
||||
## Quick start
|
||||
|
||||
Everything at once — API, both portals:
|
||||
|
||||
```bash
|
||||
docker compose up # frontend + backend together → app http://localhost:4200, Swagger http://localhost:5000/swagger
|
||||
docker compose up
|
||||
# self-service portal → http://localhost:4200
|
||||
# behandelportal → http://localhost:4201
|
||||
# API + Swagger → http://localhost:5000/swagger
|
||||
```
|
||||
|
||||
Or run the two halves separately:
|
||||
Or run the pieces yourself:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm start # app → http://localhost:4200 (proxies /api → backend, proxy.conf.json)
|
||||
# in another terminal:
|
||||
cd backend && dotnet run --project src/BigRegister.Api # API → http://localhost:5000/swagger
|
||||
npm start # self-service portal → :4200 (proxies /api → backend)
|
||||
npm run start:behandelportal # case-handler portal → :4201
|
||||
|
||||
npm run storybook # component library, organized by atomic layer
|
||||
npm run gen:api # regenerate the typed API client from the backend OpenAPI doc
|
||||
npm run e2e # Playwright smoke tests against the running app + backend (both must be up)
|
||||
# in another terminal:
|
||||
cd backend && dotnet run --project src/BigRegister.Api # API → :5000/swagger
|
||||
|
||||
npm run storybook # the design system + Foundations curriculum
|
||||
npm run e2e # Playwright — starts the backend and app itself
|
||||
```
|
||||
|
||||
Flow: **Login → Dashboard → Mijn gegevens (wijziging) → Herregistratie → Intake**.
|
||||
The backend hosts the business rules (profession derivation, policy questions,
|
||||
eligibility, thresholds); see **[backend/README.md](backend/README.md)**.
|
||||
**Self-service flow:** Login → Dashboard → Mijn gegevens → Registreren → Herregistratie → Intake
|
||||
→ Brief. **Behandelportal:** Login → Werkvoorraad → Beoordeling (approve / reject / ask for more).
|
||||
Admin pages (`/beheer/*`, `/brief/huisstijl`) need the `admin` role — see
|
||||
[roles and access](docs/reference/roles-and-access.md).
|
||||
|
||||
> **New here:** a **branching intake questionnaire** (`/intake`) where later questions
|
||||
> appear based on earlier answers and progress survives a page reload, plus a visual
|
||||
> walkthrough of the state-management ideas. See
|
||||
> **[docs/reference/architecture/ARCHITECTURE.md](docs/reference/architecture/ARCHITECTURE.md)** for diagrams (atomic-design pyramid,
|
||||
> the dispatch→reduce→view loop, RemoteData states, and "why not just signals") and a
|
||||
> section on **connecting to a .NET backend**.
|
||||
---
|
||||
|
||||
### See every data state (scenario toggle)
|
||||
## Where to find things
|
||||
|
||||
Append `?scenario=` to any data page (e.g. `/dashboard`) to force an async state:
|
||||
| I want to… | Go to |
|
||||
| --------------------------------- | -------------------------------------------------------------------------------------------------- |
|
||||
| learn the codebase from scratch | `npm run storybook` → **Foundations → Learning Path** |
|
||||
| find any document | **[docs/README.md](docs/README.md)** — the full index |
|
||||
| understand the architecture | [ARCHITECTURE.md](docs/reference/architecture/ARCHITECTURE.md) |
|
||||
| know _why_ a decision was made | [the ADRs](docs/reference/architecture/) — BFF-lite, contexts, huisstijl, stamdata, ZGW, test data |
|
||||
| work on the backend / BFF | [backend/README.md](backend/README.md) |
|
||||
| run OpenZaak locally | [backend/openzaak/README.md](backend/openzaak/README.md) |
|
||||
| see what shipped, or pick up work | [docs/project/backlog/README.md](docs/project/backlog/README.md) |
|
||||
| build a feature the house way | [`.claude/skills/`](.claude/skills/) — invocable recipes (`new-feature`, `form-machine`, …) |
|
||||
| know the import rules | [dependencies.md](docs/reference/architecture/dependencies.md) — enforced by `dep:check` |
|
||||
| work on this repo as an AI agent | [CLAUDE.md](CLAUDE.md) |
|
||||
|
||||
## Repo map
|
||||
|
||||
| Path | What lives there |
|
||||
| ---------------------- | ----------------------------------------------------------------------- |
|
||||
| `apps/ssp/` | Zorgverlener self-service portal (:4200) |
|
||||
| `apps/behandelportal/` | Behandelaar backoffice (:4201) |
|
||||
| `libs/shared/` | Design system, kernel, generated API client, Storybook Foundations docs |
|
||||
| `libs/beheer/` | Admin/stamdata context, used identically by both apps |
|
||||
| `backend/` | ASP.NET Core BFF (.NET 10, EF Core/SQLite), OpenZaak seam |
|
||||
| `e2e/` | Playwright specs |
|
||||
| `docs/` | `reference/` (how + why) and `project/` (backlog, PRDs) |
|
||||
| `public/` | Vendored CIBG Huisstijl + assets |
|
||||
| `scripts/` | CI gate, drift checks, generators |
|
||||
|
||||
---
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
npm run ci # ← run this before pushing: the whole gate, exactly what CI runs
|
||||
```
|
||||
|
||||
| Task | Command |
|
||||
| -------- | ------------------------------------------------------------------------------------------- |
|
||||
| Run | `npm start`, `npm run start:behandelportal`, `docker compose up` |
|
||||
| Test | `npm test`, `npm run e2e`, `npm run test-storybook` (axe on every story) |
|
||||
| Check | `npm run lint`, `typecheck`, `dep:check`, `check:tokens`, `check:seam` |
|
||||
| Build | `npm run build`, `npm run build-storybook` |
|
||||
| Generate | `npm run gen:api` (typed client), `npm run gen` (plop: value object, form machine, context) |
|
||||
| Docs | `npm run storybook`, `npm run dep:graph`, `npm run gen:behaviour-spec` |
|
||||
|
||||
`npm run ci` chains lint, typecheck, dependency boundaries, formatting, token and seam drift
|
||||
checks, all four test projects, both localized builds, the backend suite, and the generated-artifact
|
||||
drift gates. The full script list is in `package.json`; `CLAUDE.md` explains the traps.
|
||||
|
||||
---
|
||||
|
||||
## Where atomic design pays off
|
||||
|
||||
**Two orthogonal axes, and that is the point.** On disk, code is grouped by **ownership** —
|
||||
bounded context, then layer (`domain/` → `application/` → `infrastructure/` → `ui/`, dependencies
|
||||
pointing inward). In Storybook, the same components are grouped by **atomic level** — story titles
|
||||
put them under `Design System/Atoms|Molecules|Organisms|Templates`. So `libs/shared/src/ui/` is a
|
||||
flat folder of 26 components, and the atomic ladder lives in the sidebar where you actually browse
|
||||
it. See [Atomic design](libs/shared/docs/atomic-design.mdx) and
|
||||
[Domain-driven design](libs/shared/docs/layers.mdx) in Foundations.
|
||||
|
||||
**Reuse is the payoff.** `button`, `form-field`, `async`, `page-shell`, `site-header` appear on
|
||||
essentially every screen across _both_ apps. Change one, every screen follows.
|
||||
|
||||
**A new page is composition, not new components.** The branching intake wizard — the most complex
|
||||
flow in the app — needed exactly **one** new atom (`radio-group`) and one new organism
|
||||
(`intake-wizard`). Everything else was already there.
|
||||
|
||||
**Theming is one stylesheet and a token bridge.** `libs/shared/styles.scss` maps the app's
|
||||
semantic `--rhc-*` vocabulary onto CIBG/`--bs-*` values, so components reference tokens, never
|
||||
colours. Re-point the bridge to re-theme both apps with no component changes (ADR-0003).
|
||||
`npm run check:tokens` fails the build on a hardcoded colour.
|
||||
|
||||
---
|
||||
|
||||
## Try it: dev affordances
|
||||
|
||||
Append `?scenario=` to any data page to force an async state — the states are mutually exclusive
|
||||
by construction, via the `<app-async>` molecule:
|
||||
|
||||
| URL | What you see |
|
||||
| ----------------------------- | -------------------------------------------- |
|
||||
| `/dashboard` | real data (fast) |
|
||||
| `/dashboard` | real data |
|
||||
| `/dashboard?scenario=slow` | skeletons for ~2.5s, then data |
|
||||
| `/dashboard?scenario=loading` | the loading state, held open |
|
||||
| `/dashboard?scenario=empty` | "geen gegevens" empty state |
|
||||
| `/dashboard?scenario=error` | error message + **Opnieuw proberen** (retry) |
|
||||
|
||||
---
|
||||
|
||||
## How atomic design works here (folder = layer)
|
||||
|
||||
Atomic design organizes UI into five layers, each built from the one below. In this repo
|
||||
the folder structure _is_ the hierarchy (`src/app/`):
|
||||
|
||||
| Layer | What it is | Examples here |
|
||||
| -------------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
||||
| **atoms/** | smallest building blocks; wrap one design-system element | `button`, `text-input`, `heading`, `link`, `alert`, `status-badge`, `spinner`, `skeleton` |
|
||||
| **molecules/** | a few atoms combined into a unit | `form-field` (label + input + error), `data-row`, `async` (state wrapper) |
|
||||
| **organisms/** | larger, self-contained sections | `site-header`, `site-footer`, `login-form`, `registration-summary`, `registration-table`, `change-request-form` |
|
||||
| **templates/** | page skeletons that define layout; content is projected in | `page-layout` (header/content/footer chrome), `page-shell` (back-link + heading + intro + content) |
|
||||
| **pages/** | a template filled with real data | `login`, `dashboard`, `registration-detail`, `herregistratie` |
|
||||
|
||||
Each atom is a thin Angular standalone component that applies CIBG Huisstijl
|
||||
(Bootstrap 5.2) CSS classes (`btn`, `form-control`, `card`, …) — so the design system
|
||||
does the visual work and we only own a small, typed component API.
|
||||
Append `?role=drafter|approver|admin` to switch the dev role stand-in and unlock the admin pages.
|
||||
Both toggles are **dev-only** — neither interceptor is wired into production builds.
|
||||
|
||||
---
|
||||
|
||||
## Where you actually notice the benefit
|
||||
|
||||
**1. Reuse — the same blocks appear everywhere.**
|
||||
|
||||
| Component | Appears in |
|
||||
| ----------------------------- | ------------------------------------------------------------- |
|
||||
| `button` | login, change-request, herregistratie, async retry, Storybook |
|
||||
| `form-field` + `text-input` | login form _and_ change-request _and_ herregistratie |
|
||||
| `status-badge` | dashboard summary, detail summary |
|
||||
| `page-shell` / `page-layout` | all four pages |
|
||||
| `site-header` / `site-footer` | every page |
|
||||
| `async` + `skeleton` | dashboard, detail |
|
||||
|
||||
Change a component once and every screen that uses it updates.
|
||||
|
||||
**2. A whole new page = composition, no new components.**
|
||||
`pages/herregistratie/herregistratie.page.ts` is a complete new flow assembled entirely
|
||||
from existing atoms/molecules/templates — zero new building blocks. The branching
|
||||
**intake wizard** went further: it needed only **one new atom** (`radio-group`) and **one
|
||||
new organism** (`intake-wizard`); the form fields, buttons, alerts, spinner and page shell
|
||||
were all reused. That's the payoff: new screens cost almost nothing.
|
||||
|
||||
**3. Templates remove per-page boilerplate.**
|
||||
Every page used to repeat its own back-link + heading + intro markup. `page-shell`
|
||||
captures that once; pages now read like `<app-page-shell heading="…" backLink="…">…`.
|
||||
|
||||
**4. Theming is one stylesheet + a token bridge.**
|
||||
The look comes from **CIBG Huisstijl**, vendored under `public/cibg-huisstijl/` and
|
||||
loaded via a `<link>` in `index.html`; `body.brand--cibg` activates CIBG's
|
||||
robijn/lintblauw palette. `src/styles.scss` is a **token bridge** mapping the app's
|
||||
semantic `--rhc-*` token vocabulary onto CIBG/`--bs-*` values, so components keep
|
||||
referencing tokens — swap the vendored CSS and re-point the bridge to re-theme the
|
||||
whole app, no component changes (ADR-0003). `npm run check:tokens` fails the build
|
||||
on any hardcoded colour outside that bridge.
|
||||
|
||||
---
|
||||
|
||||
## State management (no impossible states)
|
||||
|
||||
Data fetching uses Angular's native, signal-based **`resource`** over the generated
|
||||
typed client (no NgRx, no extra dependency). Each context's `infrastructure/*.adapter.ts`
|
||||
exposes a resource that carries `status()`, `value()`, `error()` and `reload()` as
|
||||
signals, and a `parse*` function validates the response at the trust boundary
|
||||
(DTO → domain). The screen-shaped ("BFF-lite") endpoints return server-computed
|
||||
decisions the FE renders rather than recomputes (see ADR-0001).
|
||||
|
||||
The molecule **`<app-async>`** turns those signals into UI. It renders **exactly one** of
|
||||
four slots, chosen by a single `computed` — so loading, empty, error and loaded are
|
||||
mutually exclusive _by construction_. You cannot render data and an error at the same
|
||||
time, or show stale content during a hard failure: those states are unrepresentable.
|
||||
|
||||
```html
|
||||
<app-async [resource]="reg" [isEmpty]="regEmpty">
|
||||
<ng-template appAsyncLoaded let-r> <app-registration-summary [reg]="r" /> </ng-template>
|
||||
<ng-template appAsyncLoading> <app-skeleton [count]="6" /> </ng-template>
|
||||
<!-- appAsyncEmpty / appAsyncError are optional → sensible defaults -->
|
||||
</app-async>
|
||||
```
|
||||
|
||||
- **Loaded** — your content, with the value.
|
||||
- **Loading** — your skeleton, or a default **delayed spinner** (only appears after
|
||||
~250ms, so fast connections never flash a spinner; slow ones get feedback). Skeletons
|
||||
are also delay-gated. → _handles slow vs fast connections._
|
||||
- **Empty** — your message, or a default "Geen gegevens gevonden" (driven by an
|
||||
`isEmpty` predicate).
|
||||
- **Error** — your template, or a default alert + a **retry** button that calls
|
||||
`resource.reload()`.
|
||||
|
||||
Because each data-fetching page wraps its content in `<app-async>`, correct
|
||||
loading/empty/error handling is automatic and consistent across the app.
|
||||
|
||||
---
|
||||
|
||||
## Page transitions
|
||||
|
||||
The chrome (`templates/shell` — header + footer) is **persistent**: it mounts once and
|
||||
hosts the `<router-outlet>`, so navigating doesn't re-create it (no white flash). Only
|
||||
the routed content cross-fades, via Angular's native **`withViewTransitions()`** — the
|
||||
header/footer get a stable `view-transition-name` in `styles.scss` so they're excluded
|
||||
from the fade. `prefers-reduced-motion` disables the animation; non-Chromium browsers
|
||||
degrade to an instant navigation.
|
||||
|
||||
## Tech notes
|
||||
|
||||
- Angular 22 (standalone components, signals, `httpResource`, view transitions,
|
||||
control flow `@if/@for`).
|
||||
- Styling: **CIBG Huisstijl** (customized Bootstrap 5.2) vendored in
|
||||
`public/cibg-huisstijl/`, loaded via `<link>`; `src/styles.scss` holds the
|
||||
`--rhc-*` → CIBG/`--bs-*` token bridge (ADR-0003). No styling npm dependency.
|
||||
- Data: ASP.NET Core backend (`backend/`, EF Core/SQLite-persisted; BRP/DUO
|
||||
reference data stays in-memory-seeded) exposed via an OpenAPI contract; the FE
|
||||
consumes an **NSwag-generated** typed client (`npm run gen:api`).
|
||||
The `?scenario=` toggle (`shared/infrastructure/scenario.interceptor.ts`) is
|
||||
**dev-only** — it is not wired into production builds.
|
||||
- `.npmrc` sets `legacy-peer-deps=true` because `@storybook/angular`'s peer range lags
|
||||
Angular 22; the builder runs fine (build verified).
|
||||
- **i18n**: every user-facing string is `$localize`-wrapped with a stable `@@id`
|
||||
(source locale `nl`). `npx ng build --localize` (CI runs this) builds both `nl` and
|
||||
`en` — a genuine second-locale build, not just an unexercised claim — into
|
||||
`dist/atomic-design-poc/browser/{nl,en}/`; `ng serve --configuration=en` serves the
|
||||
English build locally. `src/locale/messages.en.xlf` is real (if demo-quality)
|
||||
English, not machine-untranslated placeholders; `angular.json`'s
|
||||
`i18nMissingTranslation: "error"` fails the build if a new `$localize` string ships
|
||||
without a translation. `npm run extract-i18n` regenerates the `nl` reference file.
|
||||
- **Angular 22** — standalone components, signals, `resource()`, native control flow, view
|
||||
transitions. No NgRx: shared state is a root singleton store with a pure reducer.
|
||||
- **Backend** — ASP.NET Core (.NET 10), EF Core/SQLite for applications, documents, the brief and
|
||||
the audit trail; BRP/DUO reference data stays in-memory seeded. Screen-shaped ("BFF-lite")
|
||||
endpoints return server-computed decisions the frontend renders rather than recomputes
|
||||
(ADR-0001). Cases can be sourced from **OpenZaak/ZGW** behind the same seam (ADR-0005).
|
||||
- **Typed client** — NSwag-generated from the backend's OpenAPI doc (`npm run gen:api`); CI fails
|
||||
on drift.
|
||||
- **Boundaries are enforced, not hoped for** — `dep:check` fails the build if `domain/` imports
|
||||
Angular, a context imports upward, or an app reaches into the other app.
|
||||
- **i18n** — every user-facing string is `$localize`-wrapped with a stable id (source locale `nl`).
|
||||
`ng build --localize` builds both `nl` and `en`, and `i18nMissingTranslation: "error"` fails the
|
||||
build if a string ships untranslated.
|
||||
- **Dependencies** — the shipped bundle audits clean (`npm audit --omit=dev`: 0 vulnerabilities).
|
||||
`.npmrc` sets `legacy-peer-deps=true` because Storybook's peer range lags Angular 22. Never run
|
||||
`npm audit fix --force` — it downgrades Angular 22 → 21.
|
||||
|
||||
### Dependency security
|
||||
### Deliberately out of scope
|
||||
|
||||
The **shipped app has 0 known vulnerabilities** (`npm audit --omit=dev`) — and, since the
|
||||
`@babel/core` pin below, the **full dev audit is 0 too**. All advisories live(d) in
|
||||
dev/build tooling (Storybook + the Angular build chain) and never reach the bundle.
|
||||
`package.json` `overrides` pin patched transitive versions; the last remaining cluster
|
||||
cascaded from `@babel/core`'s low-severity sourceMappingURL issue, closed by pinning
|
||||
`@babel/core` to a patched **7.x** (`^7.29.7`) — no jump to Babel 8, no breaking change.
|
||||
We do **not** run `npm audit fix --force`: its proposed fix downgrades Angular 22 → 21.
|
||||
|
||||
### Deliberately out of scope (POC)
|
||||
|
||||
Real auth/DigiD, real BRP/DUO upstreams, a production-grade database (Postgres/SQL
|
||||
Server — SQLite persists applications/documents/the brief + a real audit table,
|
||||
see `backend/README.md`, WP-22), NgRx, licensed RO/Rijks fonts + logo (system-font
|
||||
stack; text wordmark). (The backend itself _is_ implemented.) i18n's build seam is
|
||||
proven (see above) but
|
||||
production-quality translation, a runtime locale switcher, and RTL/pluralization
|
||||
edge cases are not — the `en` file is demo-quality, and locale is a build-time
|
||||
choice, not a switch in the running app.
|
||||
Real auth/DigiD, real BRP/DUO upstreams, a production-grade database, NgRx, licensed RO/Rijks
|
||||
fonts and logo. The i18n build seam is proven, but the `en` translation is demo-quality and locale
|
||||
is a build-time choice, not a runtime switch.
|
||||
|
||||
+10
-4
@@ -10,9 +10,13 @@ Docs are split by **kind**, and kept out of each other's way:
|
||||
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.
|
||||
here — see the **Foundations** section (`libs/shared/docs/*.mdx`, run `npm run storybook`).
|
||||
The `reference/` docs are the long-form source; the Foundations pages are the condensed,
|
||||
cross-linked curriculum.
|
||||
|
||||
**Starting out?** _Foundations → Learning Path_ (`libs/shared/docs/learning-path.mdx`) is a
|
||||
paced, hands-on three-day route through the codebase; _Foundations → Overview_
|
||||
(`overview.mdx`) is the map of every idea, cross-linked.
|
||||
|
||||
## `reference/` — information
|
||||
|
||||
@@ -24,7 +28,9 @@ condensed, cross-linked curriculum.
|
||||
| [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). |
|
||||
| [architecture/0005-openzaak-behind-bff.md](reference/architecture/0005-openzaak-behind-bff.md) | ADR — connect to OpenZaak (ZGW APIs) behind the BFF via a config-gated data-source seam; the FE never changes. |
|
||||
| [architecture/0006-test-data-builders.md](reference/architecture/0006-test-data-builders.md) | ADR — build test data through the production door: type-state builders, reducer replay, and which fixture idiom fits which test. |
|
||||
| [openzaak-integration.md](reference/openzaak-integration.md) | How the BFF sources cases from OpenZaak (the IZaakSource seam + ZGW client), and how to add the next slice. |
|
||||
| [../backend/openzaak/README.md](../backend/openzaak/README.md) | Docker harness for running OpenZaak locally: bring-up, integration test, notifications, teardown. |
|
||||
| [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. |
|
||||
@@ -40,7 +46,7 @@ condensed, cross-linked curriculum.
|
||||
|
||||
| Doc | What it is |
|
||||
| ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
|
||||
| [backlog/README.md](project/backlog/README.md) | The work-package backlog index (WP-01…WP-48) — the live tracker. |
|
||||
| [backlog/README.md](project/backlog/README.md) | The work-package backlog index — the live tracker, with the session protocol. |
|
||||
| [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. |
|
||||
| [prd/0003-brief-v2-demo-script.md](project/prd/0003-brief-v2-demo-script.md) | Demo script — Brief v2 scenarios mapped to a URL + click path (WP-28). |
|
||||
|
||||
Reference in New Issue
Block a user