Skip to main content

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.md that PLAN-105 will overwrite.
  • [Q8a] _category_.json files for friendly sidebar labels.
  • [Q11a] Local dev workflow documented in project-noclickops.md: cd website && npm install && npm start.
  • [Q16] editUrl enabled (free; matches DCT).

What it delivers

website/ Docusaurus app skeleton

Copy DCT's shape with these tightening / re-targeting changes:

FileDCT sourcenoclickops delta
website/package.jsonDCT line-for-lineDrop 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.jsonDCT verbatimNo changes.
website/sidebars.tsDCT verbatimOne autogenerated sidebar (docsSidebar).
website/docusaurus.config.tsDCT shapeTitle 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.cssDCT brand paletteTerminal-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.mdstub (PLAN-105 replaces with generated README copy). One paragraph + a link into /docs/ai-developer/. Frontmatter slug: /docs/ (Docusaurus default for docs/index.md; explicit for clarity).

  • website/src/pages/index.tsxstub 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_.json files for nice sidebar labels per [Q8a]:

    PathLabelPosition
    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, no static/CNAME. PLAN-104.
  • No homepage. src/pages/index.tsx is a one-line placeholder. No hero, no <HomepageFeatures>, no <QuickInstall>. PLAN-105.
  • No commands.md generator. No scripts/generate-docs.sh, no website/src/data/commands.json. PLAN-105.
  • No README → docs/index.md copy step. Stub index.md only. 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.txt stays at the current value; PLAN-105 bumps to v1.4.0 once the site is feature-complete and shippable.
  • No tests added to tests/. Docusaurus's onBrokenLinks: 'throw' + typecheck are the validation surface. A future tests/test-website-builds.sh could wrap npm run build but isn't worth the Node-dep weight at v1.
  • No expansion of tests/test-portability.sh. The portability scan covers bin/ lib/ templates/ shell/ only — website/ and scripts/ 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.ts per the "delta" row of the table above. Set url: 'https://noclickops.sovereignsky.no' and baseUrl: '/'; resolve organizationName / projectName from GITHUB_ORG / GITHUB_REPO env vars with defaults terchris / noclickops (matches DCT's fork-friendly pattern).
  • 1.5 Create website/src/css/custom.css with the terminal-green palette per [Q1a]. Suggested base: --ifm-color-primary: #00b347 (a readable terminal green that works in light mode; DCT's #25c2a0 mint is the comparison). Dark-mode palette uses a brighter #00ff66-family accent.
  • 1.6 Append the three .gitignore lines (node_modules, build, .docusaurus).
  • 1.7 Run cd website && npm install once to generate package-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_.json files per the table above.
  • 2.4 Run npm start and verify the site loads at http://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).

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 build and 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 between backlog/ and completed/.
    • [link](../../foo.md) overshooting the docs root (will hit onBrokenLinks if the resolved path falls outside website/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).
  • 3.3 Re-run npm run build until 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.md per 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.sh to confirm no regressions in the existing Bash test suite. Should be a no-op for this PLAN (no bin//lib/ changes).
  • 5.2 Stage everything except node_modules/. Confirm git status shows 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.md from plans/backlog/ to plans/completed/ and update Status to Completed YYYY-MM-DD. Do not move INVESTIGATE-docusaurus.md yet — per the PLANS.md rule, the INVESTIGATE stays in backlog/ 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 build exits 0 on a fresh clone.
  • cd website && npm start renders the site at http://localhost:3000.
  • /docs/ai-developer/ shows the full markdown tree with friendly sidebar labels from _category_.json files.
  • onBrokenLinks: 'throw' is set in docusaurus.config.ts and the build passes — no broken-links suppression.
  • Mermaid theme loaded and renders any existing mermaid blocks in the docs (smoke check: add a mermaid block somewhere temporarily, build, remove).
  • Local search appears in the navbar (functional only after npm run build + npm run serve).
  • package-lock.json committed; node_modules/ ignored.
  • project-noclickops.md has the "Working on the docs site" section.
  • tests/run-all.sh still passes (no regression).
  • No bin/, lib/, templates/, shell/ files modified — this PLAN is docs-infra only.
  • version.txt unchanged (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 + projectName should be env-overridable (DCT pattern, docusaurus.config.ts lines 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 in README.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 build once, 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 at npm run build time. 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 .gitignore addition handles it, but double-check git status before the Phase 5 commit. A stray git add -A after npm install would balloon the commit.

Files to modify / create

Create:

  • website/package.json
  • website/package-lock.json (auto-generated by npm install; committed)
  • website/tsconfig.json
  • website/sidebars.ts
  • website/docusaurus.config.ts
  • website/src/css/custom.css
  • website/src/pages/index.tsx (10-line placeholder)
  • website/docs/index.md (stub; PLAN-105 overwrites)
  • website/docs/ai-developer/_category_.json
  • website/docs/ai-developer/plans/_category_.json
  • website/docs/ai-developer/plans/backlog/_category_.json
  • website/docs/ai-developer/plans/active/_category_.json
  • website/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/**.md files surfaced by Phase 3's broken-link audit.

Move (Phase 5):

  • website/docs/ai-developer/plans/backlog/PLAN-103-website-foundation.mdplans/completed/PLAN-103-website-foundation.md.