Implementation of ADR-0022.
* `vitepress`, `vitepress-plugin-mermaid` and `mermaid` added to
workspace devDependencies. Build settled at ~9 s for the full
site, sub-second incremental in dev.
* `docs/.vitepress/config.mts`:
* `srcExclude` drops `docs/README.md` (git/IDE-only index) and
`docs/decisions/template.md` (authoring scaffold).
* `rewrites` maps `decisions/README.md` → `decisions/index.md`
so `/decisions/` resolves to the curated landing while the
source stays git-friendly.
* `ignoreDeadLinks` skips cross-repo refs (`../CLAUDE`,
`../../apps/**`, `../../notes/**`), `localhost:*` dev URLs,
and the deliberately-excluded `README`/`template` references —
the source stays usable from a git/IDE reader without
breaking the site build.
* Auto-generated sub-sidebar for `/decisions` walks
`00NN-*.md` so adding an ADR is one file.
* Mermaid via `withMermaid` with `securityLevel: 'strict'`.
* `docs/index.md` — VitePress Hero landing with four feature
cards (Architecture, Decisions, Development, Onboarding).
* `package.json` exposes `docs:dev`, `docs:build`, `docs:preview`.
* `docs/development.md` (line ~5): `[setup/](setup/)` → first
page, since folder-style links don't resolve cleanly under
`cleanUrls`. Line 330: wrap `${{ github.* }}` in
`<code v-pre>…</code>` so VitePress's Vue template parser
doesn't trip on the curly-brace interpolation.
* `.gitea/workflows/docs-site.yml` — builds on every PR (gate
on parse errors + genuine dead links), uploads the dist as an
artifact on push to main. The Mermaid plugin regression fence
greps for `class="mermaid"` / `<svg>` in ADR-0009's rendered
HTML.
* `.gitignore` excludes `docs/.vitepress/{cache,dist}/`.
Deployment target stays provisional per ADR-0022; the workflow
publishes a `docs-site` artifact for now. The rsync step lands
once the future infrastructure ADR locks the host.
Nx 22 generators inject AI agent tooling into the repo via marked
sections and side files. Rather than re-deleting them after every
generator run, track the workspace-level ones and document why.
- CLAUDE.md gains a 'General Guidelines for working with Nx' section
between Nx-managed markers; future Nx versions will update this
section automatically without touching our project rules above.
Pre-existing prettier-formatted blank lines added before code blocks
are kept.
- .claude/settings.json (228 bytes) enables the nx-claude-plugins
marketplace from nrwl/nx-ai-agents-config; tracked for contributor
consistency. The personal .claude/settings.local.json stays
gitignored.
- .github/ is the Nx AI skills/prompts/agents catalog. Kept despite
being GitHub-named; it does not conflict with our Gitea workflows
which will live under .gitea/workflows/ (per ADR-0015).
- .gitignore picks up Nx-managed transient dirs (.nx/polygraph,
.claude/worktrees) and a trailing newline fix.
AGENTS.md is removed: it duplicated only the Nx auto-injected guidance
that CLAUDE.md already carries (CLAUDE.md is the strictly broader file
- project rules + Nx section). One source of truth for AI-agent
guidance.
Generate the four phase-4 libraries:
- libs/shared/tokens (project name shared-tokens) - plain TS lib via
@nx/js:library; will host the a11y design tokens (palette,
contrast tiers, spacing, motion) once Tailwind lands in phase 5;
consumable by both apps; tagged scope:shared, type:shared.
- libs/shared/util (shared-util) - plain TS lib for cross-cutting
utility code; tagged scope:shared, type:shared.
- libs/shared/ui (shared-ui) - Angular standalone library that will
host the spartan-ng components copy-pasted in phase 5; Angular-only
so tagged scope:portal-shell, type:shared. unitTestRunner=
vitest-analog because vitest-angular requires a buildable lib.
- libs/feature/auth (feature-auth) - placeholder Angular standalone
feature lib to demonstrate the type:feature pattern; tagged
scope:portal-shell, type:feature.
@nx/enforce-module-boundaries depConstraints replaced (root
eslint.config.mjs) with the rules from ADR-0003:
scope:portal-shell -> scope:portal-shell, scope:shared
scope:portal-bff -> scope:portal-bff, scope:shared
scope:shared -> scope:shared
type:app -> type:feature, type:shared
type:feature -> type:feature, type:shared
type:shared -> type:shared
This forbids portal-shell from importing portal-bff code (and vice
versa) and prevents shared libs from depending on feature libs.
Project names follow the convention of ADR-0003 (feature-<name> /
shared-<scope>) by passing --name explicitly to the generator; the Nx
22 default takes only the last directory segment.
Sanity check: pnpm nx run-many -t lint and -t test pass for the 8
projects (4 apps/e2e + 4 libs).
Side effects from the generators: tsconfig.base.json paths populated
with the lib import aliases; nx.json gains vite/playwright plugin
entries; .gitignore picks up vitest.config.*.timestamp* (Vitest temp
files); package.json gains @analogjs/vitest-angular and related
devDeps; pnpm-lock.yaml regenerated. Two eslint-disable comments in
portal-bff-e2e support files were trimmed by lint --fix - those files
already lint clean without the directive.
Add the @nx/angular, @nx/nest, @nx/vite, @nx/eslint plugins, then
generate the two apps. Adjust the empty-template tsconfig.base.json
to be Angular-compatible (drop project references and customConditions
that the empty-template defaults to but Angular doesn't support; keep
the strict-TS extensions from ADR-0004).
apps/portal-shell (Angular 21):
- standalone APIs, routing, SCSS, esbuild
- vitest-angular as unitTestRunner, playwright for e2e
- strict mode
- tags scope:portal-shell, type:app
- app.config.ts wired with provideZonelessChangeDetection() per
ADR-0004 (Angular 21 + Nx 22 generates without zone.js by default)
apps/portal-bff (NestJS 11):
- Express adapter (default per ADR-0005)
- Jest as unitTestRunner
- tags scope:portal-bff, type:app
- main.ts wired with a global ValidationPipe configured
whitelist + forbidNonWhitelisted + transform per ADR-0005
- Phase-2 security additions (helmet, CORS, sessions, CSRF, rate
limit, auth guards, error filter) deferred to their respective
ADRs - placeholder comment in main.ts
Workspace dependencies: class-validator + class-transformer added
(required by NestJS ValidationPipe at runtime). Nx-generated
.gitignore additions (.angular, __screenshots__) merged into ours.
.vscode/extensions.json and launch.json added by Nx are kept (do not
override our existing settings.json).
Set up the foundation for the adastra-portal project:
- CLAUDE.md captures durable project rules (quality bar, security/perf/a11y
as first-class, language, commit conventions, ADR proactivity).
- docs/ and decisions/ scaffolding with maintained indexes (docs/README.md
and decisions/README.md), MADR 4.0.0 template, and tag vocabulary.
- Phase-1 ADRs (0001-0006) lock structural choices: ADR usage, Nx monorepo
with the apps preset, naming convention (adastra-portal / portal-shell /
portal-bff), Angular CSR/zoneless/Signals/Vitest, NestJS over Express,
PostgreSQL with Prisma.
- docs/setup/ guides translated to English.
- .gitignore covers Node/Nx artifacts and the personal notes/ scratchpad.
The Nx workspace itself is not yet bootstrapped; that step is gated on a
revised setup guide aligned with the ADRs.