46. Documentation site (Docusaurus v3 — TypeDoc + Supabase OpenAPI)
Date: 2026-06-23
Status
Proposed — execution plan for the "Documentation Setup — NPM-Helper-App" runbook, tailored to this repo. Nothing is scaffolded until this is Accepted.
Context
We want auto-generated, always-current API references with minimal hand-maintenance:
- a code reference for the logic/data layers, from the TSDoc comments already in
src/, and - a REST reference for the Supabase/PostgREST surface — valuable here mainly for our 13 RPCs
(
send_invoices,void_invoice,backfill_invoice,weekly_billing_run,recompute_draft_invoice,create_facility_invoice, the payroll-batch RPCs,hire_candidate, …).
The source runbook assumes a "React/TS app" pointing TypeDoc at all of ../src. This is Next.js
(App Router): src/ also holds 'use client' components, 'use server' actions, and default-export
pages/layouts, which TypeDoc renders noisily. The plan below adapts the runbook to that reality.
Decision (proposed)
-
Tooling, as in the runbook. Docusaurus v3 in a new
website/folder;docusaurus-plugin-typedoc(+typedoc-plugin-markdown) for code;docusaurus-plugin-openapi-docsdocusaurus-theme-openapi-docsfor REST. Both regenerate on build.
-
Scope TypeDoc to the logic/data layers, not the UI.
entryPoints: ['../src/lib', '../src/server', '../src/db', '../src/types']withentryPointStrategy: 'expand', and exclude the generatedsrc/db/types.ts(≈5k lines of Supabase row types — pure noise). This is the runbook's "narrow entryPoints" escape hatch. Components/pages are excluded (default exports + JSX document poorly and aren't an API surface). Covers ~200 export-bearing files. -
REST reference kept, scoped to signal. Pull the PostgREST spec to
website/specs/supabase.json(committed);groupPathsBy: 'tag'. The raw table CRUD is low-value, but the RPCs make it worth it. Pull the URL + anon (publishable) key via the Supabase MCP / env — never commit the key. Nosupabase/functions/exists, so the runbook's "Edge Functions aren't in the spec" caveat is moot. -
Node 24 everywhere. Repo is pinned to Node 24.16.0 (
.nvmrc, ADR-0041); the §5 CI workflow uses node 24, not the runbook's 20. -
website/is an isolated npm project. It keeps its ownpackage.json/lockfile (Docusaurus scaffolds with npm); the app stays on pnpm. The docs build never touches the app's deps. -
Build coupling is acceptable. TypeDoc reruns inside the docs build, so a
src/type error fails the docs build — a feature (stale docs can't ship); the app's own CI already keepstscgreen.
Execution checklist (after approval)
npx create-docusaurus@latest website classic; set title/url; commit the scaffold.- Add dev deps:
typedoc typedoc-plugin-markdown docusaurus-plugin-typedocdocusaurus-plugin-openapi-docs docusaurus-theme-openapi-docs. - Merge the consolidated
docusaurus.config.js(runbook §3): TypeDoc block with the scopedentryPoints+exclude: ['../src/db/types.ts']; OpenAPI block;docItemComponent: '@theme/ApiItem'; registerdocusaurus-theme-openapi-docs. website/sidebars.js:intro+ "Code reference" (autogeneratedcode/) + "REST API" (./docs/rest/sidebar.js).- Pull the spec:
SUPABASE_URL/SUPABASE_ANON_KEYfrom env (values via Supabase MCP) →specs/supabase.json; addspec:pull/gen:rest/clean:restscripts (runbook §4). npx docusaurus gen-api-docs supabasethennpm run build; fix any TypeDoc scope/excludes.- Add
.github/workflows/docs.yml(runbook §5, node 24;SUPABASE_URL/SUPABASE_ANON_KEYas repo secrets) — build only at first; add the deploy step once the target is chosen (see Open decisions). .gitignorethe generatedwebsite/docs/code/andwebsite/docs/rest/(rebuilt each run); keepspecs/supabase.jsoncommitted.
Open decisions (need your call before/around execution)
- Deploy target. (a) separate Vercel project at
docs.nightingalepm.com— matches the app's Vercel/app.nightingalepm.comsetup (recommended); (b) GitHub Pages — free, zero new infra; (c) build-only in CI for now, no public site. Affects step 7's deploy step. - Surface the hand-written
docs/? We already have ADRs + runbooks (go-live,cron-setup,deploy-app-subdomain,ux-ui-guidelines). Option to include them as Docusaurus pages for a single home, or leave them as repo markdown and only publish the generated references. - TSDoc backfill is a separate task. The site renders whatever comments exist; our code already has
good prose
/** */headers but few@param/@returnstags. Backfilling tags acrosssrc/is its own follow-up (potentially a workflow), not part of standing up the site.
Consequences
- A new
website/workspace + a docs CI workflow; a small ongoing "pull spec after schema changes" step (scripted in §4). - The code reference is only as good as the comments — uncommented exports render as bare signatures.
- Excluding components means the UI layer isn't documented here; acceptable (it's not an API surface).