Mechanises the new-ssp skill's manual fork-and-strip recipe into a runnable script: strips the four business contexts and every wiring point that references them (routes, tsconfig aliases, dependency-cruiser boundaries, nav links, capability union, the debug-state panel, showcase snippet tooling), renames BigRegister.* throughout including the backend solution/projects, re-runs gen:api, and reuses gen:context (WP-44) to seed the new portal's first context. Backend business rules and real branding can't be generated from nothing, so those print an explicit checklist instead of pretending to be automated. Verified end-to-end against an isolated clone (not this working tree): lint, dep:check, check:tokens, all frontend tests, ng build, dotnet build/test on the renamed backend, and gen:api against it all pass clean with zero remaining references to the stripped contexts. Co-Authored-By: Claude Sonnet 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-ssp.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-ssp)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/backlog/WPs, PRDs, and memory-specific docs — new portal, new backlog (keepdocs/project/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.