Appearance
Building & publishing the docs site
This documentation site is built from ./docs (plus README.md) with VitePress, driven by the BoB docs-site skill. The engine workspace lives under .docs-site/ and is generated (gitignored) — you never edit it by hand. Everything you commit stays in docs/ and docs-site.json.
Prerequisites
- Node 20+ (VitePress builds fine on Node 22).
- No Cloudflare account or external hostname is needed for local build/preview.
Preview locally (hot reload)
sh
/docs-site devOr, from a plain terminal:
sh
~/.claude/scripts/docs-site/dev.shThis starts the VitePress dev server with hot reload on the project's docs port (http://localhost:6653 — the app's dev port +3). Edits under docs/ refresh live. Add --print-port to see the resolved port without starting the server.
Build the static site
sh
/docs-site buildOr:
sh
~/.claude/scripts/docs-site/build.shThis syncs docs/ into the engine workspace and emits flat static HTML to .docs-site/public/. A successful run ends with build complete -> …/.docs-site/public.
Clean
sh
/docs-site clean # drop build output, keep installed deps
/docs-site clean --hard # drop the whole .docs-site/ workspaceAuthoring gotcha: angle brackets in prose
VitePress passes non-fenced Markdown to the Vue compiler, so a bare <Something> in prose (e.g. a placeholder like <Entity>) is read as an unclosed HTML/component tag and fails the build. Wrap such placeholders in inline code — `<Entity>` — or escape them (<Entity>). Inside fenced code blocks they are safe.
Refreshing walkthrough screenshots
The getting-started walkthrough embeds screenshots of the admin. They're generated by a committed script, so they can be refreshed when the UI changes:
sh
dev-up # local app running + seeded
pnpm docs:screenshots # re-capture into docs/getting-started/images/first-track/The script (scripts/docs-screenshots/capture-first-track.mjs) drives each screen with Playwright and writes one PNG per step. Set DOCS_BASE_URL if your dev server isn't on http://localhost:6650.
Publishing
The public host is docs.nanaselect.iwpi.com — POC-only (like the app's nanaselect.iwpi.com, see POC access), gated by the same Cloudflare Access application/policy that covers the app, so one allowlist admits reviewers to both. Until published, the hostname serves the local VitePress dev server over the cloudflared tunnel (already Access-gated) — publishing replaces that laptop dependency with Cloudflare Pages.
Precondition — gate
pages.devbefore the FIRST deploy. Any deploy (manual/docs-site deployincluded) self-provisions the Pages project and makes the docs publicly reachable atpaulirv-nanaselect-docs.pages.dev, which the hostname's Access app does not cover. Enable Access on the Pages project'spages.devdomain immediately at creation (step 3 below) — never leave a deploy standing ungated. (Learned 2026-07-15: an ungated first deploy had to be rolled back; the full cutover is tracked in #1436.)
The repeatable publish path is CI: .github/workflows/docs-deploy.yml builds, gate-checks, and deploys to the Cloudflare Pages project paulirv-nanaselect-docs on every push to main that touches docs/, README.md, CLAUDE.md, or docs-site.json (PRs get preview deploys with a sticky comment). Deploy config lives in docs-site.json. A one-off manual publish is also available: /docs-site deploy.
CI deploying is off until three human-owned repo settings exist (build and doc-drift gate run regardless, so breakage is still caught):
- Repo secret
CLOUDFLARE_API_TOKEN— a token with Pages:Edit on the paul@iwpi.com account. - Repo secret
CLOUDFLARE_ACCOUNT_ID— the account UUID (inwrangler.jsonccomments). - Repo variable
DOCS_SITE_DEPLOY_ENABLED=true.
Then, to move the hostname from the tunnel to Pages (order matters, mirroring the app-host flip in POC access):
- Delete the
docs.nanaselect.iwpi.comCNAME to the tunnel (iwpi.com zone). - In the Pages project, add docs.nanaselect.iwpi.com as a custom domain (Cloudflare creates the proxied record in the zone; the existing Access app keeps gating the hostname).
- Gate the
pages.devURL too:paulirv-nanaselect-docs.pages.devserves the same content and is NOT covered by the hostname's Access app — in Zero Trust, enable Access on the Pages project'spages.devdomain (Cloudflare offers this as a one-click option on the Pages project) or add it to the Access application. Without this the "gated" docs are public at the pages.dev URL. - Verify: anonymous
curl -sI https://docs.nanaselect.iwpi.com→ 302 toiwpi.cloudflareaccess.com; OTP login → docs render; the pages.dev URL also 302s.