## Summary Records the decision to render `docs/**/*.md` as a separately-deployed static site using **VitePress + `vitepress-plugin-mermaid`**. This is **ADR-only** — the implementation (install + `.vitepress/config.ts` + `docs/index.md` + Gitea Actions workflow) lands as the next chantier. Splitting them keeps the decision review focused on the *why* before the *how*. ## What lands ### [`docs/decisions/0022-docs-site-vitepress.md`](docs/decisions/0022-docs-site-vitepress.md) Full MADR 4.0.0 ADR. Decision drivers, 4 considered options (VitePress, MkDocs Material, Docusaurus 3, Astro Starlight), site-structure mapping, Mermaid integration, deployment + CI plan, consequences, revisit triggers. Tags: `process`, `infrastructure`. **Key choices captured:** - VitePress wins on toolchain alignment (Vite already in the workspace via `@nx/vite`, `vite-plugin-angular`, Vitest). MkDocs Material was the strong runner-up; the Python runtime tax in Gitea Actions tipped the balance. - `vitepress-plugin-mermaid` for ```` ```mermaid ```` blocks ([ADR-0009](docs/decisions/0009-auth-flow-oidc-pkce-msal-node.md) sequence + [architecture.md](docs/architecture.md) C4 are hard requirements). - Site sources entirely from `docs/`. Mapping: - `docs/index.md` (new, Hero layout) → `/` - `docs/development.md` → `/development` - `docs/architecture.md` → `/architecture` - `docs/decisions/README.md` → `/decisions/` (curated index, kept as section landing) - `docs/decisions/00NN-….md` → auto-listed in the sidebar by numeric prefix - `docs/setup/0N-….md` → `/setup/0N-…` - **Excluded** via `srcExclude`: `docs/README.md` (stays as the git-side / IDE-preview index — option A from the prior discussion) and `docs/decisions/template.md` (authoring scaffold). - Empty placeholder sections in `docs/README.md` (Operations runbooks, Security/perf/a11y rationales) are NOT pre-created as empty pages — they appear in the sidebar when real content lands. - Deployment: dedicated hostname (provisional `docs.portal.apf.fr`) behind the same Caddy reverse-proxy as the apps, fed by a new `.gitea/workflows/docs-site.yml` triggered on `docs/**` push. Exact hostname follows the future infrastructure ADR; not locked here. ### [`docs/decisions/README.md`](docs/decisions/README.md) ADR-0022 added to the index table. ### [`CLAUDE.md`](CLAUDE.md) Bumps the ADR range from `0001 → 0021` to `0001 → 0022`. New bullet in the "Architecture (recorded in ADRs)" section describing the docs-site choice in one paragraph. Implementation tracked in "Still on the roadmap" until the next PR lands it. ## Notes for the reviewer - **Why ADR before implementation?** The choice between VitePress / MkDocs Material / Docusaurus / Astro Starlight is exactly the "stable + recognized + innovative" trade-off [CLAUDE.md](CLAUDE.md) asks to document. Reviewing the rationale on its own (without dragging through the install diff) keeps the discussion focused. - **Why not surface ADRs inside `portal-admin`?** Audience mismatch — [ADR-0020](docs/decisions/0020-portal-admin-app.md) §"Audience is disjoint" frames `portal-admin` around APF internal operators (CMS, audit, user directory), not architects. The full reasoning is in ADR-0022 §"Context and Problem Statement". - **Why two index artefacts (`docs/README.md` + future `docs/index.md`)?** Option A from the structure discussion. Each serves a distinct audience: `README.md` is the flat link list that renders well in IDEs / Gitea source view; `index.md` will be the VitePress Hero landing for the web audience. Light duplication, no maintenance pressure (the IDE one only needs updating when sections appear/disappear). - **Why `vitepress-plugin-mermaid` rather than Docusaurus's built-in Mermaid?** The community plugin is a sub-1.0 dependency on the wrapper (Mermaid itself is mature), but Mermaid is so mainstream that switching it out is a half-day rewrite if the plugin stalls. Trading that risk against Docusaurus's MDX-by-default footprint + React runtime is a net win. - **Why `process` + `infrastructure` tags?** Mirrors [ADR-0015](docs/decisions/0015-cicd-gitea-actions.md) (also a CI / deploy decision with content authoring implications) and is consistent with the [tag vocabulary](docs/decisions/README.md#tag-vocabulary). No new tag invented. ## Test plan - [x] `docs/decisions/0022-docs-site-vitepress.md` validates as MADR 4.0.0 (frontmatter, section order). Index in [`docs/decisions/README.md`](docs/decisions/README.md) updated in the same PR per [ADR conventions](docs/decisions/README.md#conventions). - [x] No code touched — `lint / test / build` matrix unaffected. - [ ] Review for trade-off accuracy: did I get MkDocs Material's strengths right? Is Astro Starlight's maturity argument fair? - [ ] Implementation chantier (next PR): `pnpm add -D vitepress vitepress-plugin-mermaid mermaid`, `docs/.vitepress/config.ts`, `docs/index.md`, `.gitea/workflows/docs-site.yml`, `package.json` scripts. Will land within the same week assuming this ADR holds. ## What's next If accepted as-is, the immediate follow-up is: 1. Install VitePress + the Mermaid plugin. 2. Author `docs/.vitepress/config.ts` with the sidebar shape spelled out in this ADR (auto-generated sub-sidebar for `/decisions`, hand-curated top-level). 3. Author `docs/index.md` (Hero layout). 4. Add the `docs-site` Gitea Actions workflow. 5. Wire the dev script (`pnpm docs:dev`) into `package.json` so contributors can preview locally. If reviewers want to push back on the toolchain choice (MkDocs Material in particular has a strong case for the theme polish), this is the right PR to surface that — implementation hasn't started. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #153
9.5 KiB
Architectural Decision Records
This project records architecturally-significant decisions as ADRs in the MADR 4.0.0 format. References: adr.github.io.
Why ADRs
ADRs capture the why behind a decision — context, drivers, options considered, trade-offs accepted — at the moment the decision is made. They make architecture reviewable, onboarding faster, and prevent the same debate from being re-litigated later.
Conventions
- Format: MADR 4.0.0. Start from template.md.
- Filename:
NNNN-kebab-case-title.md, e.g.0007-adopt-tailwind-for-design-tokens.md. - Numbering: globally sequential 4-digit prefix. Numbers never reset, never get reused — even when an ADR is superseded or deprecated.
- Layout: flat folder. ADRs are not nested into category subfolders; topical organization happens via tags.
- Tags: every ADR carries a
tags:array in the MADR frontmatter, drawn from the tag vocabulary below. An ADR may carry several tags. Propose new tags (or renames) in the same PR that needs them; never invent ad-hoc tags inline. - Status lifecycle:
proposed→accepted→ optionallydeprecatedorsuperseded by [ADR-NNNN](NNNN-other.md). Update the YAML frontmatter; never delete an ADR. - Index maintenance: every ADR addition or status change must update the Index below in the same commit.
When to write an ADR
Write one whenever a development decision is non-trivial: tool or library choice, framework pattern, security control, perf budget, a11y target, naming convention, deprecation, breaking change, or any choice that future contributors would benefit from understanding the why of.
Tag vocabulary
The vocabulary below is the source of truth. It is intentionally coarse — propose extensions only when an existing tag genuinely doesn't fit, and avoid overly narrow tags.
| Tag | Scope |
|---|---|
frontend |
UI, Angular, components, design system, client-side state |
backend |
API, BFF, server-side services |
security |
AuthN, AuthZ, sessions, CSP, dependency scanning, secret management |
performance |
Perf budgets, caching, bundle size, Lighthouse |
accessibility |
WCAG, a11y testing, keyboard, ARIA, contrast |
infrastructure |
CI/CD, hosting, deployment, runtime |
observability |
Logs, metrics, traces, correlation IDs, monitoring |
data |
Persistence, schemas, migrations, data flow |
process |
Team conventions, workflows, repo policy |
Status: starter vocabulary, to be refined as ADRs accumulate. Update this table whenever a tag is added, renamed, or retired.
Index
ADRs are listed in numerical order. To slice by topic, filter on the Tags column.
| # | Title | Status | Tags | Date |
|---|---|---|---|---|
| 0001 | Use ADRs to record architectural decisions | accepted | process |
2026-04-29 |
| 0002 | Adopt Nx monorepo with the apps preset |
accepted | infrastructure, frontend, backend |
2026-04-29 |
| 0003 | Workspace and app naming convention | accepted | process |
2026-04-29 |
| 0004 | Frontend stack — Angular (latest LTS), standalone, zoneless, Signals, CSR-only, Vitest | accepted | frontend |
2026-04-29 |
| 0005 | Backend stack — NestJS over Express, Fastify, Hono | accepted | backend |
2026-04-29 |
| 0006 | Persistence — PostgreSQL with Prisma | accepted | data, backend |
2026-04-29 |
| 0007 | Pre-commit hooks and Conventional Commits | accepted | process |
2026-04-29 |
| 0008 | Identity model — multi-tenant Entra ID for workforce, dual-audience design for future External ID | accepted | security, data |
2026-04-29 |
| 0009 | Authentication flow — OIDC Authorization Code + PKCE via MSAL Node, BFF session pattern | accepted | security, backend |
2026-04-29 |
| 0010 | Session management — opaque session IDs in cookies, payload in self-hosted Redis with AES-GCM at rest | accepted | security, backend, infrastructure |
2026-04-29 |
| 0011 | MFA enforcement — Entra ID Conditional Access baseline, BFF claim sanity-check, step-up hooks designed-in | accepted | security |
2026-04-29 |
| 0012 | Observability — Pino structured logs + OpenTelemetry tracing, W3C Trace Context propagation, stdout + collector | accepted | observability, backend, frontend |
2026-04-29 |
| 0013 | Audit trail — separated append-only Postgres schema, decoupled from app logs | accepted | security, observability, data |
2026-04-29 |
| 0014 | Downstream API access — On-Behalf-Of pattern, unified DownstreamApiClient, audience-aware authorization |
accepted | security, backend |
2026-04-29 |
| 0015 | CI/CD pipeline — Gitea Actions, trunk-based + squash-merge, thin YAML over portable scripts | accepted | infrastructure, process |
2026-04-30 |
| 0016 | Accessibility baseline — WCAG 2.2 AA + targeted AAA, Angular CDK + spartan-ng + Tailwind, APF panel testing | accepted | accessibility, frontend, process |
2026-04-30 |
| 0017 | Performance budgets — Core Web Vitals + Lighthouse CI gates, bundle budgets, BFF p95/p99 SLOs | accepted | performance, frontend, backend, process |
2026-04-30 |
| 0018 | Environment configuration — Angular environment.ts, BFF env vars, audit pool split |
accepted | frontend, backend, infrastructure, process |
2026-05-10 |
| 0019 | Internationalisation — @angular/localize, build-time per-locale bundles, /fr + /en path-based routing |
accepted | frontend, accessibility, performance, process |
2026-05-11 |
| 0020 | portal-admin — dedicated SPA for portal administration, sharing the existing BFF |
accepted | frontend, backend, security, infrastructure, process |
2026-05-11 |
| 0021 | Phase-2 security baseline — helmet, CORS allowlist, double-submit CSRF, rate limiting, structured error envelope | accepted | security, backend |
2026-05-13 |
| 0022 | Documentation site — VitePress + Mermaid plugin, separate static deployment | accepted | process, infrastructure |
2026-05-15 |