Two backlog trees are complete: `docs/project/backlog/` (75 files, every WP done) and `docs/project/refactor-backlog-setup/` (the arc before it). Move both under `docs/project/archive/` with `git mv`, so history stays intact through `git log --follow`. `SHOWCASE-ROADMAP.md` moves with them, because it points at the now-archived backlog README. Add `docs/project/archive/README.md`. It states that these trees are historical and names the two directories that are still live. Repoint every inbound reference named in RD-30's Files table: CLAUDE.md, the root README, both backend READMEs, `LetterHtml.cs`, `a11y.mdx`, the `document-feature` and `new-ssp` skills, and the readable-codebase PLAN, README, and RD-19 ticket. Fix two upward-relative links inside the moved WP files (WP-68, WP-69) that gained a directory level and would otherwise break. Repoint `.prettierignore`'s two agent-prompt exclusions to their new path, so prettier keeps leaving those files' exact wording alone. Mark RD-30 done and check off its acceptance criteria; flip its README row to done. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
6.9 KiB
name, description
| name | description |
|---|---|
| new-ssp | Bootstrap a new self-service portal from this repo as a template — what to keep, strip, rename, and re-seed. Use when starting a new SSP for a different domain/register. |
New SSP from this template
The template's value is the enforced architecture (layer fences, token gate, a11y gate, API-drift gate) and the shared building blocks — not the BIG-register business content. Keep the machinery, replace the domain.
Run the script
Clone this repo, npm ci, then mechanise the mechanical parts (WP-45):
node scripts/create-frontend.mjs --name Kvk --context inschrijving
--name (PascalCase) replaces BigRegister.* everywhere; --context (lowercase Dutch
ubiquitous term) is passed straight to gen:context (plop context, WP-44) to seed the new
portal's first real context. Add --dry-run to preview file operations first, --keep <context> to leave one business context in place temporarily as a worked example, and
--skip-backend if no .NET SDK is available yet (skips gen:api).
It strips the four business contexts and their wiring, renames the backend, re-runs
gen:api, and seeds the first context — then prints a checklist for what it deliberately
doesn't script: backend business rules and real branding can't be generated from nothing.
Work through that checklist, keeping the GREEN gate below passing at every step.
Keep as-is
src/app/shared/— kernel (fp.ts), application (remote-data,store,submit), ui atoms/molecules, layout templates, upload subtree — exceptshared/ui/debug-state/, which the script deletes (see below).- Tooling:
eslint.config.mjs,.dependency-cruiser.js(edited by the script, not hand-stripped — see below),scripts/check-tokens.sh,.github/workflows/ci.yml,nswag.json,.storybook/,proxy.conf.json,.npmrc(legacy-peer-deps— and nevernpm audit fix --force, it downgrades Angular). src/app/auth/(fake auth shell) andsrc/app/shared/infrastructure/scenario.interceptor.ts(dev-only).docs/reference/architecture/ADRs 0001–0003 — the decisions still apply; amend, don't delete.CLAUDE.md,docs/reference/architecture/ARCHITECTURE.md,docs/reference/fp-tea-atomic-design.md— update names/examples as contexts change..claude/skills/— these recipes are the point of the template.src/app/beheer/— its frontend is genuinely generic (data-driven off aStamdataTable/AuditEntryshape, nothing BIG-specific). Its backend Stamdata catalog is not — see below.
Strip / replace — what the script does
- Business contexts
registratie/,herregistratie/,brief/,showcase/: deleted (or one kept temporarily via--keepas the worked example while building the first real context — new-context + new-feature skills; if kept, update the worked-example paths in those skills to the new flagship context once you drop it for real). app.routes.tsroute blocks andtsconfig.jsonaliases for removed contexts, and theirCONTEXT_ALLOWEDentry in.dependency-cruiser.js— boundary rules moved there in WP-38 and are no longer ineslint.config.mjs(which only keepsno-explicit-any+ a11y template rules). Route stripping matches on the import alias a route uses, not its own path segment —beheer/zakenimports@registratie/ui/admin-cases.pageand gets dropped along withregistratieeven though its own path doesn't say so.src/app/shared/ui/debug-state/(the dev⚙ statepanel): imports@registratie/application/big-profile.storedirectly and is the one path.dependency-cruiser.js'sshared-no-featuresrule exempts — there's no generic way to re-target it at an arbitrary new context, so it's deleted alongsideregistratie, along with its three wiring lines inshell.component.ts(import,imports:entry, template tag).- The
dashboardroute is not deleted even though it currently imports@registratie/ui/dashboard.page— too much else hardcodes/dashboard(login's post-auth redirect,authGuard's fallback, header nav/logo, breadcrumb trail, several stories/specs). The script rewrites itsloadComponentto point at the freshly scaffolded--contextpage instead (aTODO(create-frontend)stopgap landing page, not a real overview). scripts/gen-snippets.mjs(showcase-only) + itspackage.jsonscript entry + its CI/ci-local.sh"showcase snippets drift" steps: deleted alongsideshowcase/— they run unconditionally, so leaving them breaksnpm run ciimmediately onceshowcase/is gone.- Backend: keep the skeleton (
Program.csminimal-API style, ProblemDetails 422,X-Correlation-Idaudit line,/api/v1versioning,Contracts//Domain//Data/split, test project, and the genericStamdata/StamdataFile.cs+StamdataTable.csreflection-driven/stamdataendpoint machinery, ADR-0004) — replaceData/SeedData.cs,Domain/*rules,Contracts/*DTOs, and the three concrete Stamdata catalog entries (Beroep/Opleiding/Specialisme/ProfessionMapping+ their JSON) with the new register's. The script renames the solution/projects fromBigRegister.*(and updatespackage.json'sgen:api,ci.yml's paths,docker-compose.yml) — it does not rewrite business content; that's the printed checklist. - Regenerate the seam:
npm run gen:api(commitsbackend/swagger.json+src/app/shared/infrastructure/api-client.ts) — only reflects a new shape once the backend content above is actually rewritten. - Branding: the script swaps
src/index.html's stylesheet<link>+<title>to a placeholder path and creates an emptypublic/<name>-huisstijl/— it cannot generate a real house style. Vendor your CSS there, then re-point the--rhc-*bridge insrc/styles.scss(ADR-0003 pattern: bridge, don't rewrite tokens), thennpm run check:tokens. docs/project/archive/backlog/WPs, PRDs, and memory-specific docs — new portal, new backlog (keepdocs/project/archive/backlog/README.md's WP process/template if you like the workflow).docs/reference/scaffolding.mdalso namesBigRegister.Apiin prose — update by hand.e2e/*.spec.ts(smoke.spec.ts,brief-v2.spec.ts,error-state.spec.ts): full BIG-register user-flow tests (BSN login → registration wizard → submission assertions). Not touched by the script (they don't blocknpm run ci— thee2ejob runs separately) but are 100% stale business content; rewrite once you have real flows to test.
Verify — the GREEN gate must pass at every step
npm run lint && npm run check:tokens && npm test && npm run build
npm run build-storybook && npm run test-storybook:ci
cd backend && dotnet test && cd ..
npm run gen:api && git diff --exit-code backend/swagger.json src/app/shared/infrastructure/api-client.ts
Or just npm run ci for the non-storybook subset. Strip incrementally and keep this green
— the fences are only worth having if they never go red.