Skip to main content

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)

  1. Tooling, as in the runbook. Docusaurus v3 in a new website/ folder; docusaurus-plugin-typedoc (+ typedoc-plugin-markdown) for code; docusaurus-plugin-openapi-docs

    • docusaurus-theme-openapi-docs for REST. Both regenerate on build.
  2. Scope TypeDoc to the logic/data layers, not the UI. entryPoints: ['../src/lib', '../src/server', '../src/db', '../src/types'] with entryPointStrategy: 'expand', and exclude the generated src/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.

  3. 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. No supabase/functions/ exists, so the runbook's "Edge Functions aren't in the spec" caveat is moot.

  4. 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.

  5. website/ is an isolated npm project. It keeps its own package.json/lockfile (Docusaurus scaffolds with npm); the app stays on pnpm. The docs build never touches the app's deps.

  6. 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 keeps tsc green.

Execution checklist (after approval)

  1. npx create-docusaurus@latest website classic; set title/url; commit the scaffold.
  2. Add dev deps: typedoc typedoc-plugin-markdown docusaurus-plugin-typedoc docusaurus-plugin-openapi-docs docusaurus-theme-openapi-docs.
  3. Merge the consolidated docusaurus.config.js (runbook §3): TypeDoc block with the scoped entryPoints + exclude: ['../src/db/types.ts']; OpenAPI block; docItemComponent: '@theme/ApiItem'; register docusaurus-theme-openapi-docs.
  4. website/sidebars.js: intro + "Code reference" (autogenerated code/) + "REST API" (./docs/rest/sidebar.js).
  5. Pull the spec: SUPABASE_URL/SUPABASE_ANON_KEY from env (values via Supabase MCP) → specs/supabase.json; add spec:pull / gen:rest / clean:rest scripts (runbook §4).
  6. npx docusaurus gen-api-docs supabase then npm run build; fix any TypeDoc scope/excludes.
  7. Add .github/workflows/docs.yml (runbook §5, node 24; SUPABASE_URL/SUPABASE_ANON_KEY as repo secrets) — build only at first; add the deploy step once the target is chosen (see Open decisions).
  8. .gitignore the generated website/docs/code/ and website/docs/rest/ (rebuilt each run); keep specs/supabase.json committed.

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.com setup (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/@returns tags. Backfilling tags across src/ 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).