PLAN-103: Docusaurus foundation — site boots, existing docs render
IMPLEMENTATION RULES: Before implementing this plan, read and follow:
Status: Completed 2026-05-29
Goal: Stand up a Docusaurus app under website/ so the existing website/docs/ai-developer/ markdown renders as a navigable site locally (npm start) and builds clean (npm run build). No deploy, no homepage, no command generator yet — those land in PLAN-104 and PLAN-105.
Last Updated: 2026-05-29
Investigation: INVESTIGATE-docusaurus.md (DCT pivot at 2026-05-29; this PLAN realises rows A1–A5, A6 partial, A7 deferred to PLAN-105)
Prerequisites: none — website/docs/ai-developer/ already contains the source markdown this PLAN renders.
Blocks: PLAN-104 (deploy needs a buildable site), PLAN-105 (homepage + generator need the foundation)
Priority: Medium — enables the rest of the Docusaurus trilogy.
Branch: feat/v1.4.0-docusaurus — same branch shared by PLAN-103/104/105 (per "PR per investigation" rule in project-noclickops.md). PR opens after PLAN-105 ships.
Problem
website/docs/ai-developer/ already exists and reads like a Docusaurus docs tree (folder-as-category, [link](../FILE.md) relative refs, _category_.json-shaped subfolders) — but there's no Docusaurus app to render it. GitHub's raw-markdown view works, but visitors get no sidebar, no search, no rendered Mermaid, no shareable section URLs. The repo's branding (README.md line 5: "no clickops") deserves a real site.
DCT (/Users/terje.christensen/learn/helpers/devcontainer-toolbox/website/) is the reference: same Docusaurus 3.9.2 stack, same metadata-driven approach noclickops already uses, identical local-search + Mermaid choices. Locked-in answers (see INVESTIGATE-docusaurus.md "Locked-in decisions" table):
- [Q1a] Brand colour: terminal green.
- [Q4a] Public URL:
https://noclickops.sovereignsky.no(DNS work + deploy in PLAN-104). - [Q5a] Mermaid enabled.
- [Q6a] Local search enabled.
- [Q7c] README is the docs index — but the generator that copies it (with link rewrites) lives in PLAN-105. PLAN-103 ships a placeholder
index.mdthat PLAN-105 will overwrite. - [Q8a]
_category_.jsonfiles for friendly sidebar labels. - [Q11a] Local dev workflow documented in
project-noclickops.md:cd website && npm install && npm start. - [Q16]
editUrlenabled (free; matches DCT).
What it delivers
website/ Docusaurus app skeleton
Copy DCT's shape with these tightening / re-targeting changes:
| File | DCT source | noclickops delta |
|---|---|---|
website/package.json | DCT line-for-line | Drop docusaurus-plugin-image-zoom (no images in v1 docs); keep @docusaurus/theme-mermaid, @easyops-cn/docusaurus-search-local, classic preset. Same Docusaurus 3.9.2 floor. |
website/tsconfig.json | DCT verbatim | No changes. |
website/sidebars.ts | DCT verbatim | One autogenerated sidebar (docsSidebar). |
website/docusaurus.config.ts | DCT shape | Title noclickops; tagline from README.md line 5; URL https://noclickops.sovereignsky.no; organizationName: 'terchris', projectName: 'noclickops' (env-var fallback like DCT, so forks work); mermaid + search themes; editUrl to https://github.com/${ORG}/${REPO}/tree/main/website/; navbar items: Docs + GitHub (no Blog, no Templates); drop announcementBar and zoom; drop image-zoom plugin. |
website/src/css/custom.css | DCT brand palette | Terminal-green primary (#00ff66 family) per [Q1a]. Keep DCT's hero / button / colorMode blocks; drop the per-template card / dropdown / mermaid-zoom CSS (no analogue in noclickops v1). |
Bare minimum for the docs tree to render
-
website/docs/index.md— stub (PLAN-105 replaces with generated README copy). One paragraph + a link into/docs/ai-developer/. Frontmatterslug: /docs/(Docusaurus default fordocs/index.md; explicit for clarity). -
website/src/pages/index.tsx— stub placeholder (PLAN-105 replaces with hero + features + install). Bare<Layout>with "Site under construction — docs at /docs/". Without this, Docusaurus falls back to its own template homepage at/, which looks worse than a one-line placeholder. -
Five
_category_.jsonfiles for nice sidebar labels per [Q8a]:Path Label Position website/docs/ai-developer/_category_.json"AI Developer Workflow" 2 website/docs/ai-developer/plans/_category_.json"Plans" 99 website/docs/ai-developer/plans/backlog/_category_.json"Backlog" 1 website/docs/ai-developer/plans/active/_category_.json"Active" 2 website/docs/ai-developer/plans/completed/_category_.json"Completed" 3
.gitignore additions
# Docusaurus
node_modules/
website/build/
website/.docusaurus/
project-noclickops.md — new "Working on the docs site" section
Adds after the "Devcontainer" heading (which currently says "No devcontainer"):
## Working on the docs site
The site under `website/` is a Docusaurus app. Local dev:
```bash
cd website
npm install # first time only
npm start # http://localhost:3000 with hot reload
npm run build # production build (catches broken links)
```
Requires Node 20+. The build runs with `onBrokenLinks: 'throw'`, so any
broken intra-docs link fails CI. Mermaid + local search are enabled.
The marketing homepage at `/` and the generated `/docs/commands` page are
delivered by PLAN-105; the GitHub Pages deploy is delivered by PLAN-104.
What this PLAN does NOT do
- No deploy. No
.github/workflows/deploy-docs.yml, nostatic/CNAME. PLAN-104. - No homepage.
src/pages/index.tsxis a one-line placeholder. No hero, no<HomepageFeatures>, no<QuickInstall>. PLAN-105. - No
commands.mdgenerator. Noscripts/generate-docs.sh, nowebsite/src/data/commands.json. PLAN-105. - No README →
docs/index.mdcopy step. Stubindex.mdonly. PLAN-105. - No logo / favicon / social card. Docusaurus defaults are fine for v1; replace when assets exist (out of scope for this trilogy).
- No version bump.
version.txtstays at the current value; PLAN-105 bumps tov1.4.0once the site is feature-complete and shippable. - No tests added to
tests/. Docusaurus'sonBrokenLinks: 'throw'+typecheckare the validation surface. A futuretests/test-website-builds.shcould wrapnpm run buildbut isn't worth the Node-dep weight at v1. - No expansion of
tests/test-portability.sh. The portability scan coversbin/lib/templates/shell/only —website/andscripts/are noclickops's own internals (docs about ourselves and tooling for ourselves), not target-repo-facing scripts. They're allowed to mention "noclickops" by name.
Phases
Phase 1: Scaffold the Docusaurus app
Tasks
- 1.1 Create
website/package.json(DCT-line-for-line minus image-zoom; Docusaurus 3.9.2;"engines": {"node": ">=20.0"}). - 1.2 Create
website/tsconfig.json(DCT verbatim). - 1.3 Create
website/sidebars.ts(DCT verbatim — single autogenerated sidebar). - 1.4 Create
website/docusaurus.config.tsper the "delta" row of the table above. Seturl: 'https://noclickops.sovereignsky.no'andbaseUrl: '/'; resolveorganizationName/projectNamefromGITHUB_ORG/GITHUB_REPOenv vars with defaultsterchris/noclickops(matches DCT's fork-friendly pattern). - 1.5 Create
website/src/css/custom.csswith the terminal-green palette per [Q1a]. Suggested base:--ifm-color-primary: #00b347(a readable terminal green that works in light mode; DCT's#25c2a0mint is the comparison). Dark-mode palette uses a brighter#00ff66-family accent. - 1.6 Append the three
.gitignorelines (node_modules, build, .docusaurus). - 1.7 Run
cd website && npm installonce to generatepackage-lock.json. Commit the lock file.
Validation
cd website
npm install # exits 0
npm run typecheck # exits 0 (tsc on docusaurus.config.ts + sidebars.ts)
User confirms package-lock.json lands and node_modules/ doesn't get committed.
Phase 2: Make the existing docs render
Tasks
- 2.1 Create stub
website/docs/index.md(1–2 paragraphs +slug: /docs/frontmatter + link to/docs/ai-developer/). - 2.2 Create stub
website/src/pages/index.tsx(10-line<Layout>placeholder, links to/docs/). - 2.3 Create the five
_category_.jsonfiles per the table above. - 2.4 Run
npm startand verify the site loads athttp://localhost:3000. Click into/docs/ai-developer/and confirm the sidebar shows the friendly labels from_category_.json.
Validation
cd website
npm start # http://localhost:3000 renders
User confirms (visually):
/shows the placeholder page./docs/shows the stub index./docs/ai-developer/shows the README content with the full sidebar tree visible.- Sidebar labels read "AI Developer Workflow", "Plans", "Backlog", "Active", "Completed" — not raw folder names.
- Mermaid blocks (if any in current docs) render as diagrams.
- The search box appears in the navbar (search index is built on
npm run build, so dev mode shows a warning; that's expected).
Phase 3: Fix broken intra-docs links
onBrokenLinks: 'throw' will fail the first npm run build on any link in website/docs/ that resolves to nothing. This is a feature — it's catching real drift in the existing markdown. Don't weaken to 'warn'.
Tasks
- 3.1 Run
cd website && npm run buildand capture the broken-link list. - 3.2 For each broken link, fix it at the source (correct path, or remove if the target is gone). Common shapes to expect:
- Plan-files referencing other plans by
[link](PLAN-xxx.md)when the target moved betweenbacklog/andcompleted/. [link](../../foo.md)overshooting the docs root (will hitonBrokenLinksif the resolved path falls outsidewebsite/docs/).- Pointers to repo-root files like
../../../README.md— these can't resolve in Docusaurus; rewrite to absolute GitHub URLs (https://github.com/terchris/noclickops/blob/main/README.md).
- Plan-files referencing other plans by
- 3.3 Re-run
npm run builduntil it exits 0.
Validation
cd website
npm run build # exits 0
Output reports a built site under website/build/. No "Broken link found" errors. The build's "Loaded X documents" line should be ~30 (every .md in website/docs/).
Phase 4: Document local dev
Per [Q11a] + the "Keeping contributor docs in sync" rule in PLANS.md: docs updates are part of the same PLAN that changes behaviour. This PLAN introduces the docs site, so it documents how to work on it.
Tasks
- 4.1 Add the "Working on the docs site" section to
website/docs/ai-developer/project-noclickops.mdper the "Delivers" section above. Position: after the "Devcontainer" heading. - 4.2 Add a one-liner to the repo-root
README.md"Development" section pointing at the new contributor section.
Validation
User reads the new section and confirms the steps are unambiguous and complete for a fresh-clone contributor.
Phase 5: Commit (don't PR yet)
Per "commit per plan; PR per investigation" (project-noclickops.md "Commit per plan; PR per investigation"): commit at the end of PLAN-103 on feat/v1.4.0-docusaurus, then PLAN-104 commits to the same branch, then PLAN-105 commits and opens the PR.
Tasks
- 5.1 Run
bash tests/run-all.shto confirm no regressions in the existing Bash test suite. Should be a no-op for this PLAN (nobin//lib/changes). - 5.2 Stage everything except
node_modules/. Confirmgit statusshows the expected new files and zero unexpected ones. - 5.3 Commit on
feat/v1.4.0-docusaurus. Suggested message:feat(PLAN-103): Docusaurus foundation — site builds, ai-developer docs render. - 5.4 Move
PLAN-103-website-foundation.mdfromplans/backlog/toplans/completed/and update Status toCompleted YYYY-MM-DD. Do not moveINVESTIGATE-docusaurus.mdyet — per the PLANS.md rule, the INVESTIGATE stays inbacklog/until all children ship (PLAN-105 will move it).
Validation
git log --oneline -1 # shows the PLAN-103 commit
git branch --show-current # feat/v1.4.0-docusaurus
gh pr list --head feat/v1.4.0-docusaurus # empty (no PR yet — waiting for PLAN-105)
Acceptance criteria
-
cd website && npm install && npm run buildexits 0 on a fresh clone. -
cd website && npm startrenders the site athttp://localhost:3000. -
/docs/ai-developer/shows the full markdown tree with friendly sidebar labels from_category_.jsonfiles. -
onBrokenLinks: 'throw'is set indocusaurus.config.tsand the build passes — no broken-links suppression. - Mermaid theme loaded and renders any existing mermaid blocks in the docs (smoke check: add a
mermaidblock somewhere temporarily, build, remove). - Local search appears in the navbar (functional only after
npm run build+npm run serve). -
package-lock.jsoncommitted;node_modules/ignored. -
project-noclickops.mdhas the "Working on the docs site" section. -
tests/run-all.shstill passes (no regression). - No
bin/,lib/,templates/,shell/files modified — this PLAN is docs-infra only. -
version.txtunchanged (PLAN-105 bumps). - Commit lands on
feat/v1.4.0-docusaurus; no PR opened.
Implementation notes for whoever picks this up
- DCT is the line-by-line reference: for every config or component you're unsure about, open
/Users/terje.christensen/learn/helpers/devcontainer-toolbox/website/<same-path>and start from there. Diverge only where the "delta" column of the table calls it out. - Don't try to use
routeBasePath: '/'(which would make docs the site root). It tempts because Q7c says "README is the docs index" — but it creates churn with PLAN-105's marketing homepage and breaks the standard/vs/docs/separation. Keep the default layout. organizationName+projectNameshould be env-overridable (DCT pattern,docusaurus.config.tslines 9–14 of DCT's file). This is what lets a forker deploy to their own GitHub Pages with zero code changes. Important for the fork-friendliness story inREADME.md.- The terminal-green palette ([Q1a]) needs to pass WCAG AA contrast for light + dark mode. Suggested base
#00b347(light primary) /#00ff66(dark accent). Tweak after seeing it rendered — Docusaurus's swatch generator (https://docusaurus.io/docs/styling-layout#styling-your-site-with-infima) is the easiest source for the matching--ifm-color-primary-{dark,darker,darkest,light,lighter,lightest}values. - For the broken-links Phase 3: it's faster to run
npm run buildonce, capture the full list of broken links from stdout, then fix in one batch than to iterate one-at-a-time. - Mermaid in dark mode: DCT's setup works out of the box. If a diagram renders badly in dark mode, it's a per-diagram issue, not a config issue.
@easyops-cn/docusaurus-search-local's dev-mode warning ("⚠ Local search will not work in dev mode") is normal and not a bug. The search index is built atnpm run buildtime. Document this in the "Working on the docs site" section so the next contributor doesn't think they broke something.- Don't commit
node_modules/— the.gitignoreaddition handles it, but double-checkgit statusbefore the Phase 5 commit. A straygit add -Aafternpm installwould balloon the commit.
Files to modify / create
Create:
website/package.jsonwebsite/package-lock.json(auto-generated bynpm install; committed)website/tsconfig.jsonwebsite/sidebars.tswebsite/docusaurus.config.tswebsite/src/css/custom.csswebsite/src/pages/index.tsx(10-line placeholder)website/docs/index.md(stub; PLAN-105 overwrites)website/docs/ai-developer/_category_.jsonwebsite/docs/ai-developer/plans/_category_.jsonwebsite/docs/ai-developer/plans/backlog/_category_.jsonwebsite/docs/ai-developer/plans/active/_category_.jsonwebsite/docs/ai-developer/plans/completed/_category_.json
Modify:
.gitignore— add three Docusaurus lines.website/docs/ai-developer/project-noclickops.md— add "Working on the docs site" section.README.md— one-liner pointing at the new contributor section.- Any
website/docs/ai-developer/**.mdfiles surfaced by Phase 3's broken-link audit.
Move (Phase 5):
website/docs/ai-developer/plans/backlog/PLAN-103-website-foundation.md→plans/completed/PLAN-103-website-foundation.md.