Investigate: Add Docusaurus to noclickops
IMPLEMENTATION RULES: Before implementing the plans that come out of this investigation, read and follow:
- WORKFLOW.md — the implementation process
- PLANS.md — plan structure and best practices
Status: Completed 2026-05-29
All three child PLANs shipped: PLAN-103 (foundation), PLAN-104 (deploy → https://noclickops.sovereignsky.no/), PLAN-105 (homepage + generator → v1.4.0). See each PLAN's completion notes in plans/completed/ for what landed and what didn't.
Goal: Decide what Docusaurus setup noclickops needs and how much of an existing sister project's Docusaurus setup to copy. Land a v1 that publishes the existing website/docs/ markdown to a browsable site AND renders a marketing homepage that shows what noclickops does — without dragging in template-catalogue machinery that has no equivalent here.
Last Updated: 2026-05-29
Locked-in decisions (2026-05-29)
User answered the decision-points; outcomes below feed directly into PLAN-A/B/C. The full reasoning behind each option lives in the [Q] sections further down.
| ID | Answer | Outcome |
|---|---|---|
| [Q1a] | yes | Brand color: terminal green (#00ff66-ish, neon-on-black accent). Set in website/src/css/custom.css. |
| [Q2a] | yes | Pure DCT homepage shape: Hero → HomepageFeatures → QuickInstall. Category browsing lives on /docs/commands (the generated reference page), NOT the homepage. |
| [Q3b] | defer | No blog in v1. Release notes stay in CHANGELOG.md / git tag messages. Easy to enable later. |
| [Q4a] | yes | Public URL: noclickops.sovereignsky.no. static/CNAME carries the domain; DNS work happens out-of-band. |
| [Q5a] | add | Mermaid enabled via @docusaurus/theme-mermaid + markdown.mermaid: true. |
| [Q6a] | yes | Local search via @easyops-cn/docusaurus-search-local. |
| [Q7c] | yes for now | Docs index = repo root README.md, copied into website/docs/index.md at build time by the same generator that produces commands.md. Path-rewriter is mandatory (see note below). |
| [Q8a] | yes | Add _category_.json to website/docs/ai-developer/, .../plans/, .../plans/{backlog,active,completed}/ for labeled sidebar entries. |
| [Q9b] | yes | Workflow rebuilds on every push to main (no path filter). Cheap CI minutes; simpler workflow. |
| [Q18a] | yes | Generator is Bash (scripts/generate-docs.sh). Sources lib/metadata.sh for parse_metadata(). |
| [Q19a] | yes | Single generated website/docs/commands.md (H2 per category, H3 per command, anchored). DCT pattern. |
Defaults adopted for unanswered Q's (user said "not sure" or didn't specify):
| ID | Default | Why |
|---|---|---|
| [Q10] | Mooted by Q7c. | If README is the docs index (Q7c), there's no second copy to drift. The "single source of truth" version of Q10 is the answer — Q10b/Q10c don't apply. |
| [Q11a] | Document cd website && npm install && npm start in project-noclickops.md. | DCT's own README does this verbatim. No wrapper script; no noclickops subcommand (would violate "wrap, never replicate"). |
| [Q18b'-a] | Generator runs as an explicit CI step before npm run build. | Matches DCT's workflow exactly. Local devs run bash scripts/generate-docs.sh manually before npm start (documented in project-noclickops.md alongside Q11a). |
Q7c implementation note (the risky bit, now scoped):
scripts/generate-docs.sh gets a third output: copy README.md → website/docs/index.md with these transformations (small sed pipeline, all build-time):
- Prepend Docusaurus frontmatter:
---\nslug: /\ntitle: noclickops\nsidebar_position: 1\n--- - Rewrite relative repo-root links so they resolve in the rendered site:
](CLAUDE.md)/](AGENTS.md)→ absolute GitHub URL (these are tooling files, not docs pages)](LICENSE)→ absolute GitHub URL](website/docs/ai-developer/...)→](/docs/ai-developer/...)](website/docs/ai-developer/plans/completed/)→](/docs/ai-developer/plans/completed/)
- Strip / rewrite the GitHub Actions badge — it points at an
actions/workflows/...URL; either leave it (renders fine in Docusaurus) or drop it (cleaner). Default: leave it. - Smoke check: after copy, grep the result for any remaining
](website/patterns and fail the build if any are found (catches new README links that need a rule).
website/docs/index.md becomes a generated file (gitignored or committed-but-don't-edit, like DCT's commands.md). The existing website/docs/ai-developer/README.md keeps its current role — sidebar entry for the AI-developer tree, not the site root.
Still open (non-blocking for PLAN drafting):
- [Q15] Separate
CONTRIBUTING.md— defer; revisit after site is live. - [Q16]
editUrlfor "Edit this page" links — recommend yes (DCT enables it; free). Will fold into PLAN-A. - [Q17] Analytics — defer until [Q4a] domain is live and there's an audience to measure.
- [Q21] Extended
SCRIPT_*metadata fields (SCRIPT_DETAILS/SCRIPT_FLAGS/SCRIPT_AUTH/ etc.) — separate backlog INVESTIGATE/PLAN, triggered after the v1 site exposes the gap.
Sources surveyed:
/Users/terje.christensen/learn/helpers/dev-templates/website/(TMP) — Docusaurus 3.10, deployed totmp.sovereignsky.novia GitHub Pages./Users/terje.christensen/learn/helpers/devcontainer-toolbox/website/(DCT) — Docusaurus 3.9.2, deployed todct.sovereignsky.no. The closer model (2026-05-29 user steer): sameSCRIPT_*metadata pattern noclickops already uses; generator is Bash, not TypeScript; outputs a singlecommands.mdreference page exactly equivalent to what noclickops's "v1.0.0 surface" table inREADME.mdis today.
Why now
The repo already keeps documentation under website/docs/ai-developer/ as if Docusaurus were going to render it — the folder layout, the relative [link](./WORKFLOW.md) style, even the _category_.json-shaped subfolders all point at that. But there's no Docusaurus app present. Two consequences:
- Anyone who lands at the GitHub repo reads the docs as raw markdown in the GitHub UI. Cross-references work, but there's no search, no sidebar, no rendered Mermaid, no shareable section URLs.
- The
noclickopsbrand promise (README.mdline 5: "no clickops") deserves a small, fast docs site that matches the product's vibe — terminal-y, low-friction. TMP already pays the tooling cost for the same Docusaurus stack we'd use; the marginal cost of adopting here is small.
Constraint: the file paths under website/docs/ai-developer/ are referenced from CLAUDE.md, AGENTS.md, and every plan file via relative links (e.g. website/docs/ai-developer/project-noclickops.md). Docusaurus must render those files without moving them. (Same constraint TMP lives with — confirmed by inspecting their layout.)
What DCT's Docusaurus setup actually is (the model we follow)
Anatomy of devcontainer-toolbox/website/ + the generator at .devcontainer/manage/dev-docs.sh:
| Piece | What it is | Relevant to noclickops? |
|---|---|---|
docusaurus.config.ts | site config: title, URL, navbar (with version badge), footer, mermaid theme, local search, image-zoom, editUrl | Yes — copy and adapt; drop image-zoom if [Q5] says so |
sidebars.ts | one autogenerated sidebar | Yes — copy verbatim |
package.json | Docusaurus 3.9.2 + classic preset + mermaid theme + local search + image-zoom | Yes — copy and trim per [Q5]/[Q6] |
tsconfig.json | extends @docusaurus/tsconfig | Yes — copy verbatim |
docs/ | markdown content; one commands.md is generated, the rest hand-written | Yes — point at existing website/docs/; add a generated commands.md |
blog/ | release notes / blog posts | Per [Q3] |
src/pages/index.tsx | hero (with logo + tagline) + <HomepageFeatures> (3-4 cards) + <QuickInstall> + <AiDemo> | Yes — copy the shape, swap copy and drop AiDemo |
src/components/CategoryCard, CategoryGrid | category-overview cards used on a docs page (not the homepage) | Yes — adapt for noclickops categories |
src/components/ToolCard, ToolGrid | per-item cards used inside category pages | Yes — adapt to "CommandCard" / "CommandGrid" |
src/components/HomepageFeatures, QuickInstall | static React for homepage marketing | Yes — adapt |
src/components/FloatingCubes, AiDemo | DCT-specific visual flourishes | No — drop |
src/components/RelatedTools | "see also" widget for per-item pages | Defer — needs SCRIPT_RELATED metadata extension first |
src/data/categories.json, tools.json | generated by dev-docs.sh, consumed by React components | Yes — same pattern; we generate commands.json + categories.json |
src/css/custom.css | brand colors, hero styling, card styling | Partial — adapt brand color per [Q1] |
static/img/ | logo, favicon, social card, per-category logos, per-tool logos | Yes — but we need our own (no noclickops logo yet) |
static/CNAME | dct.sovereignsky.no | Yes — needs noclickops's domain per [Q4] |
.github/workflows/deploy-docs.yml | builds + deploys; runs the generator (dev-docs.sh) before npm run build | Yes — copy; replace the dev-* generator calls with our generate-docs.sh |
.devcontainer/manage/dev-docs.sh | Bash generator (~1400 lines) — walks additions/install-*.sh, extracts SCRIPT_* metadata via grep + sed, emits per-tool MDX pages, commands.md, tools.json, categories.json, and updates README.md between HTML-comment markers (TOOLS_START / TOOLS_END) | Yes — this is the reference implementation for our scripts/generate-docs.sh (which will be much smaller — ~150 lines for 11 commands) |
The clean separation: everything in website/docs/, website/src/components/, and the generator pattern is directly applicable; DCT's marketing-specific bits (FloatingCubes, AiDemo) are drop-only; DCT's container-context (the generator lives in .devcontainer/manage/ because DCT itself ships a devcontainer) doesn't apply — our generator lives at scripts/generate-docs.sh at the repo root.
What TMP offered (and what we're explicitly not taking)
Surveyed first; superseded by DCT as the closer model. Kept for the record so future readers don't repeat the survey:
- TMP's
src/pages/index.tsxis too heavy for a CLI tool's homepage — it's<HeroAnimation>+<CategoryGrid>+<TemplateGrid>for ~50 templates. DCT's simpler hero + features + install pattern is the better fit. - TMP's
scripts/generate-registry.tsis TypeScript because TMP's source data istemplate-info.yamlfiles (Node has YAML libs; Bash needsyq). noclickops's source data isSCRIPT_*=shell assignments — Bash already parses them vialib/metadata.sh::parse_metadata(). DCT's Bash generator is the right shape. - TMP's
src/pages/templates.tsxcatalogue page has no analogue here (noclickops's "catalogue" is 11 commands; DCT'scommands.mdsingle-page pattern fits better than a dedicated/commandsroute). - TMP's mermaid theme, local search, image-zoom plugin, and
static/CNAMEdeploy pattern are all things DCT also has — so no loss in switching the primary reference to DCT.
Patterns to ADOPT (for v1)
A1 — Docusaurus 3.10 + classic preset + faster preset
Same versions TMP runs in production. Stable, well-supported by upstream. @docusaurus/faster cuts cold-start build time meaningfully (Rspack-based bundler). No reason to diverge.
Apply: copy package.json dependency block, drop @easyops-cn/docusaurus-search-local, docusaurus-plugin-image-zoom, js-yaml, @types/js-yaml (TMP-only) and consider mermaid + search ([Q5], [Q6]).
A2 — docs/ lives in place; sidebar autogenerated
TMP's sidebars.ts is a single line: docsSidebar: [{type: 'autogenerated', dirName: '.'}]. Docusaurus walks the tree and uses folder structure + _category_.json files to build the sidebar. Means we keep website/docs/ai-developer/ as is and just add the Docusaurus app around it. CLAUDE.md / AGENTS.md paths keep working.
Apply: copy sidebars.ts verbatim. Add _category_.json files where we want labeled folders (e.g. website/docs/ai-developer/, website/docs/ai-developer/plans/).
A3 — tsconfig.json extends @docusaurus/tsconfig
Two-line config, nothing to customize.
Apply: copy verbatim.
A4 — GitHub Pages deploy on push to main
TMP's workflow: install deps, build, upload artifact, deploy via actions/deploy-pages@v5. Path filter website/** means non-docs changes don't trigger a rebuild.
Apply: copy a slimmed version — drop the template-registry / metadata / generate-docs steps; keep only npm ci → npm run build → upload → deploy. Add .github/workflows/deploy-docs.yml. Path filter becomes website/** + .github/workflows/deploy-docs.yml.
A5 — .gitignore entries for build artifacts
TMP gitignores website/build/ and website/.docusaurus/. Standard hygiene.
Apply: add both lines (plus node_modules/) to root .gitignore.
A6 — Marketing homepage + category-grouped command reference (DCT pattern)
Decision (user, 2026-05-29): YES, we want this. The homepage is the marketing surface — first-time visitors should see what noclickops actually does, not a docs sidebar. DCT's pattern fits perfectly because noclickops already has the same shape: a small set of commands that naturally bucket into categories. The README's "v1.0.0 surface" table groups all 11 commands across 5 categories (Meta / Git / Deployment / Service lifecycle / Inspect & observe). That table becomes a docs page (/docs/commands), and the homepage links to it from a category grid.
The DCT→noclickops mapping is essentially identical (same metadata pattern, same Bash generator approach):
| DCT concept | noclickops equivalent |
|---|---|
Install script (e.g. .devcontainer/additions/install-dev-python.sh) | Command script (e.g. bin/create-pr.sh) |
SCRIPT_ID / SCRIPT_NAME / SCRIPT_DESCRIPTION / SCRIPT_CATEGORY (+ extended fields) | Same; noclickops already has SCRIPT_NAME / SCRIPT_DESCRIPTION / SCRIPT_USAGE / SCRIPT_EXAMPLE / SCRIPT_CATEGORY (see A7) |
LANGUAGE_DEV, AI_TOOLS, etc. (in lib/categories.sh) | meta, git, deploy, service-lifecycle, inspect (already in lib/metadata.sh as _NCO_VALID_CATEGORIES) |
.devcontainer/manage/dev-docs.sh (~1400 lines, Bash) | scripts/generate-docs.sh (~150 lines for 11 commands, Bash; reuses lib/metadata.sh::parse_metadata) |
website/docs/commands.md (generated, single page, anchored H3s per command) | website/docs/commands.md (generated, same shape) |
website/docs/tools/<category>/<tool>.mdx (per-tool pages) | Defer — wait for extended SCRIPT_* fields ([Q21]). v1 has only the single page. |
website/src/data/tools.json + categories.json (generated, consumed by <ToolGrid> etc.) | website/src/data/commands.json + categories.json (generated, consumed by <CommandGrid> etc.) |
<CategoryGrid> + <CategoryCard> (rendered on /docs/tools index page) | <CommandCategoryGrid> + <CommandCategoryCard> (rendered on homepage and/or /docs/commands per [Q2]) |
<ToolGrid> + <ToolCard> (rendered on per-category pages) | <CommandGrid> + <CommandCard> (rendered on homepage per [Q2]) |
<HomepageFeatures> (3-4 marketing cards on index.tsx) | Same — adapt copy from README.md ("Installed once", "Works in any repo", "Wraps existing pipelines", "No clickops") |
<QuickInstall> (install one-liner card on index.tsx) | Same — adapt to noclickops's curl … install.sh line |
<FloatingCubes>, <AiDemo> | Drop — DCT-specific marketing flourishes |
<RelatedTools> | Defer — needs SCRIPT_RELATED from [Q21] |
Apply: copy the shape of DCT's src/components/CategoryGrid + CategoryCard + ToolGrid + ToolCard + HomepageFeatures + QuickInstall and rewrite them against the noclickops data model. Skip FloatingCubes / AiDemo / RelatedTools. The homepage hero + features + install pattern is direct; the category grid placement (homepage vs docs page) is [Q2].
This supersedes the original B1/B2 "defer" stance.
A7 — Drive the homepage and commands.md from existing SCRIPT_* metadata, generator in Bash
Decision (user, 2026-05-29): YES, and use Bash. noclickops already has the SCRIPT_* metadata; DCT proves the Bash-generator pattern in production. If a richer doc page needs fields that don't exist yet, capture those as a separate metadata-extension PLAN — don't block v1 on them.
The metadata is already in place across all 12 scripts. From lib/metadata.sh (line 4–9) and confirmed by inspecting bin/create-pr.sh, bin/deploy.sh, bin/add-service.sh, bin/noclickops.sh:
# --- noclickops metadata ---
SCRIPT_NAME="create-pr"
SCRIPT_DESCRIPTION="Open an Azure DevOps PR from the current branch to main."
SCRIPT_USAGE='noclickops create-pr "<title>" ["<description>"]'
SCRIPT_EXAMPLE='noclickops create-pr "feat: add login flow"'
SCRIPT_CATEGORY="git"
# --- end metadata ---
That's enough for both surfaces:
- Homepage card uses:
SCRIPT_NAME(card title),SCRIPT_DESCRIPTION(card body),SCRIPT_CATEGORY(which bucket it sits in). commands.mdH3 section uses all five:SCRIPT_NAME(H3 anchor + title),SCRIPT_DESCRIPTION(tagline),SCRIPT_USAGE(synopsis code block),SCRIPT_EXAMPLE(cookbook code block),SCRIPT_CATEGORY(which H2 group it goes under), plus--helpbody in a collapsible (per DCT'scommands.mdpattern, lines 1064–1226 ofdev-docs.sh).
Bash generator pattern is already proven by DCT. lib/metadata.sh::parse_metadata() already does the extraction; the new generator at scripts/generate-docs.sh would source lib/metadata.sh, walk bin/*.sh, and emit:
website/docs/commands.md— single page, H2 per category, H3 per command with anchors. Direct port of DCT'sgenerate_commands_md()(dev-docs.shlines 1100–1229).website/src/data/commands.json— one row per command (name, description, usage, example, category). Consumed by<CommandGrid>/<CommandCard>React components.website/src/data/categories.json— one row per category (id, label, description). Consumed by<CommandCategoryGrid>/<CommandCategoryCard>. Source for category labels: the lister's display strings inbin/noclickops.shlines 90–94 ("Meta","Git / pull requests","Deployment","Service lifecycle","Inspect / observe").- Optional v1.x: update
README.md's "v1.0.0 surface" table between HTML-comment markers (COMMANDS_START/COMMANDS_END), so the README never drifts frombin/. Direct port of DCT'supdate_readme()(dev-docs.shlines 617–660).
Generator size estimate: ~150 lines of Bash for noclickops's 11 commands and 5 categories (DCT's 1400 lines handle 50+ tools with package arrays, logos, extensions, multi-output orchestration — most of that is not relevant here).
Apply: PLAN-C adds scripts/generate-docs.sh. Generator runs per [Q18b'] (recommended: explicit step in CI workflow, same as DCT). See [Q19] for the question of additional per-command pages beyond the single commands.md.
What's missing for richer pages (recorded as [Q21] follow-up, not blocking v1):
DCT extends SCRIPT_* with: SCRIPT_ID, SCRIPT_VER, SCRIPT_TAGS, SCRIPT_ABSTRACT, SCRIPT_LOGO, SCRIPT_WEBSITE, SCRIPT_SUMMARY, SCRIPT_RELATED (see dev-docs.sh line 141). That extended set is what enables DCT's rich per-tool MDX pages. For noclickops the analogous extensions would be:
SCRIPT_DETAILS— multi-line "what this actually does" paragraph (beyond the one-lineSCRIPT_DESCRIPTION). Some scripts already have this as a comment header (bin/add-service.shlines 1–18 explain the pipeline contract); not structured yet. DCT'sSCRIPT_SUMMARYis the precedent.SCRIPT_FLAGS— structured flag reference. Today flag handling lives in each script'scase "$a" in …block; nothing parses it.SCRIPT_AUTH— auth prerequisites per command (the README has this at category level:create-pr/merge-pr/deploy/add-service/statusneedaz login;info/logs/shelladditionally need Reader on a subscription). Per-command would be cleaner.SCRIPT_EXIT_CODES— documented non-zero exit conditions. Several scriptsdie "..."in distinct failure modes; not currently classified.SCRIPT_SEE_ALSO— related commands. Obvious pairs:create-pr↔merge-pr,add-service↔status,info↔logs↔shell. DCT'sSCRIPT_RELATEDis the precedent.SCRIPT_DEPENDS_ON— required tools (az,gh,jq,rsyncfor sync-lovable). Therequire_*helpers inlib/know this implicitly; surfacing per-command would help.
These are decisions for [Q21]'s follow-up PLAN, not this investigation. v1's commands.md renders only the existing five fields plus the --help body in a collapsible (the DCT pattern).
Patterns to DEFER
B1 — mermaid-zoom.ts client module
Nice quality-of-life for big diagrams. Mermaid itself is the prerequisite ([Q5]). Defer the zoom — easy to add later, not worth the surface area for v1.
Verdict: defer. Revisit if Mermaid lands and the rendered diagrams are too small to read.
B2 — Image-zoom plugin (docusaurus-plugin-image-zoom)
Same reasoning as B1 but for .markdown img. We have no screenshots in the current docs.
Verdict: defer.
Patterns to DIVERGE on
C1 — Brand color
TMP's --ifm-color-primary: #2d6a4f (forest green) ties to the dev-templates / SovereignSky family. noclickops needs its own. Suggested palette options in [Q1].
C2 — Domain
TMP uses tmp.sovereignsky.no on a SovereignSky-controlled DNS. noclickops's hosting decision is a separate question ([Q4]). Reasonable choices: SovereignSky subdomain, plain GitHub Pages URL, custom domain — picks below.
C3 — Homepage content (not structure)
We're keeping TMP's homepage structure (hero + category grid + item grid — see A6) but every word of copy is noclickops-specific: tagline reflects "no clickops" not "instant-start templates", the hero CTAs go to install + first commands not "Browse Templates", category labels match the README table (Meta / Git / Deployment / Service lifecycle / Inspect & observe). See [Q2] for hero-copy options.
C4 — Footer / navbar links
TMP's navbar includes "Templates" and footer links to DevContainer Toolbox + Infrastructure Stack (the sister projects in the SovereignSky family). For noclickops: probably just "Docs" + "Blog" (if [Q3] = yes) + "GitHub". Footer can be minimal.
Decision-points for the maintainer
These are the calls that need to be made before drafting child PLANs. Use the [Q<N>] IDs to give feedback.
Branding & hosting
-
[Q1] Brand color. Options:
- [Q1a] Terminal green (
#00ff66-ish, dark accent in light mode, neon on black). Matches the "no clickops" CLI vibe. - [Q1b] Slate / charcoal (
#374151primary with a single accent color). Neutral, ages well, less theme-y. - [Q1c] Reuse TMP's forest green for visual kinship with the sister project.
- [Q1d] Some other color you have in mind — name it.
- [Q1a] Terminal green (
-
[Q2] Homepage structure (the layout, not the copy — copy is locked to noclickops). DCT's reference layout is Hero → HomepageFeatures (3-4 cards) → QuickInstall → AiDemo; category browsing lives on a separate
/docs/toolspage, not the homepage. Pick what shape noclickops's homepage should have:- [Q2a] Pure DCT shape: Hero → HomepageFeatures → QuickInstall. The category grid lives on
/docs/commands(the generated reference page). Homepage is purely marketing; visitors click "Get Started" or "Browse Commands" to drill in. Recommended — matches the production sister project; lightest React surface. - [Q2b] DCT shape + category teaser on home: Hero → HomepageFeatures → QuickInstall → CommandCategoryGrid (5 cards). Each category card links to its anchor on
/docs/commands. Adds discoverability above the fold without flattening the whole 11-command grid. - [Q2c] Category-first home: Hero → CommandCategoryGrid → CommandGrid (flat, alphabetical) → QuickInstall. Heaviest above the fold but no hidden surface — first-time visitors see every command without scrolling past marketing copy.
- [Q2d] Grouped grid home: Hero → QuickInstall → CommandGrid grouped by category (5 H2 sections, commands as cards within each). One screen-scroll covers everything; no category-card layer at all. Closest to "the README, but pretty".
- [Q2a] Pure DCT shape: Hero → HomepageFeatures → QuickInstall. The category grid lives on
-
[Q3] Blog / changelog. Options:
- [Q3a] Enable the Docusaurus blog and use it for release notes (one post per
vX.Y.Ztag). Gives RSS, dated archive, "Recent posts" sidebar. - [Q3b] No blog; keep release notes in
CHANGELOG.md(or in git tag messages) and don't carry the extra Docusaurus surface.
- [Q3a] Enable the Docusaurus blog and use it for release notes (one post per
-
[Q4] Public URL. Options:
- [Q4a]
noclickops.sovereignsky.no(matches TMP's family; needs DNS work on your end). - [Q4b]
terchris.github.io/noclickops(zero DNS; Docusaurus needsbaseUrl: '/noclickops/'). - [Q4c] Different custom domain you'd want — name it.
- [Q4a]
Plugins
-
[Q5] Mermaid. Options:
- [Q5a] Yes — add
@docusaurus/theme-mermaid, enablemarkdown.mermaid: true. Useful for architecture / flow diagrams in plans andWORKFLOW.md. - [Q5b] No — defer until we have diagrams to render.
- [Q5a] Yes — add
-
[Q6] Search. Options:
- [Q6a] Local search (
@easyops-cn/docusaurus-search-local, same as TMP). Free, no Algolia signup, builds at deploy time. - [Q6b] No search in v1 — small docset, sidebar + browser find is enough. Add later if the docset grows.
- [Q6a] Local search (
Existing-docs handling
-
[Q7] Docs entry point. The
website/docs/folder currently contains onlyai-developer/— there's no top-levelindex.md. Options:- [Q7a] Add
website/docs/index.mdwith the README intro + a one-paragraph "where to look" pointing intoai-developer/and the plans tree. Becomes the URL slug/docs/. - [Q7b] Promote
website/docs/ai-developer/README.mdto the docs root by settingslug: /in its frontmatter. Avoids a new file; reuses the existing entry point. - [Q7c] Use the repo root
README.mdas the docs index via a symlink or a build-time copy step. Risky (Docusaurus + symlinks across repo boundaries get fiddly); probably skip.
- [Q7a] Add
-
[Q8]
_category_.jsonfiles. Should we add them now to label the sidebar nicely, or let the autogenerated sidebar use raw folder names?- [Q8a] Add
_category_.jsontowebsite/docs/ai-developer/,.../plans/,.../plans/backlog/,.../plans/active/,.../plans/completed/— pretty labels, controlled ordering. - [Q8b] Skip for v1; sidebar shows folder names verbatim ("ai-developer", "plans", etc.). Add later if the auto-labels look ugly.
- [Q8a] Add
CI & deploy
-
[Q9] When does the docs site rebuild?
- [Q9a] Only on changes under
website/**and the workflow file itself (TMP's pattern, minus their template-metadata paths). - [Q9b] On every push to
main(simpler workflow file; trivially more CI minutes).
- [Q9a] Only on changes under
-
[Q10] README + docs index drift. The current
README.mddescribes install + first commands; if [Q7a] is picked, the same content lives inwebsite/docs/index.md. Risk: drift.- [Q10a] Accept the drift — README is for GitHub readers, docs index is for site readers; they overlap and that's fine.
- [Q10b] Add a contributor note in
PLANS.md/project-noclickops.mdsaying "when you change install instructions, change both." - [Q10c] Build-time copy of
README.mdintowebsite/docs/index.md(CI step). Cleaner but adds a moving part.
Local dev
- [Q11] Local dev workflow. TMP runs
cd website && npm install && npm start. Options:- [Q11a] Same — document
cd website && npm install && npm startinCONTRIBUTING.md(orproject-noclickops.md); no wrapper. - [Q11b] Add a
noclickopssubcommand likedocsthat runs the dev server. Tempting but breaks the "wrap existing automation, never replicate it" rule — npm already wraps it. - [Q11c] Add a
scripts/docs-dev.shthin wrapper in this repo (sister of TMP'sscripts/). Mild ergonomics for "I forgot the npm command."
- [Q11a] Same — document
Command-grouping data model (opened by A6 + A7)
The big decisions are resolved by A7 (data source = bin/*.sh SCRIPT_*; generator = Bash, like DCT's dev-docs.sh). These sub-questions remain.
- [Q18] Generator language. (DCT uses Bash; TMP uses TypeScript. Pick one.)
- [Q18a] Bash (
scripts/generate-docs.sh). Sourceslib/metadata.shand reusesparse_metadata()— single source of truth for parsing, no duplicated regex. Output JSON viajq(already a noclickops runtime dep). Matches DCT verbatim; matches the repo's "Bash + PowerShell siblings" idiom; matches the existinglib/library style. Recommended. - [Q18b] TypeScript (
scripts/generate-docs.ts, run vianpx tsx). Matches TMP. Re-implements the same five-field regex in TS — small (~30 lines for the parser). Downside: parsing logic now lives in two places (lib/metadata.sh+ the TS generator); they can drift. Upside: stays inside the Node/Docusaurus toolchain, no shell-out from CI. - [Q18c] Docusaurus plugin (
website/plugins/load-commands/index.ts). The plugin'sloadContentlifecycle runs the same scanning logic and exposes the result as a Docusaurus "global data" blob the components consume directly. No on-disk JSON file. Most idiomatic for Docusaurus; downside: harder to inspect (no committed JSON to diff in PRs); doesn't writecommands.md.
- [Q18a] Bash (
18b. [Q18b'] When does the generator run? (Independent of [Q18] language choice.)
- [Q18b'-a] Explicit CI step before
npm run buildindeploy-docs.yml— DCT's pattern (lines 56–60 of their workflow:- name: Generate documentation data→run: bash .devcontainer/manage/dev-docs.sh). Visible in CI logs; local devs run it manually before previewing. Recommended (matches DCT). - [Q18b'-b]
prebuild/prestartnpm hook inwebsite/package.json— runs automatically on every localnpm startand every CInpm run build. Zero new CI steps. Better local DX; slightly less visible in CI. - [Q18b'-c] Commit-time pre-commit hook that regenerates and adds the JSON +
commands.mdto the commit. Keeps the generated files always in sync on disk; adds setup burden.
- [Q19] Per-command page granularity. Each card on the homepage needs a destination URL — pick the shape.
- [Q19a] Single generated page
website/docs/commands.mdlisting every command grouped by category (H2 per category, H3 per command, anchored). DCT's pattern (theirdev-docs.sh::generate_commands_md(), ~130 lines, produces a page like DCT's live commands.md). One file, deep links (#create-pr). Cheapest to generate; renders the existing fiveSCRIPT_*fields + a collapsible--helpblock per command. Recommended for v1; matches what the README's "v1.0.0 surface" table already implies. Per-command sub-pages can be added later when extended metadata lands ([Q21]). - [Q19b] One generated page per command at
website/docs/commands/<name>.md. Cleanest URLs, sidebar entry per command. DCT does this for tools (docs/tools/<category>/<tool>.mdx) but only because their extended metadata (logos, package arrays, related-tools) justifies the per-page real estate. With only five fields per command, 11 separate pages mostly duplicate the H3-anchor layout of Q19a — overkill for v1. Revisit after [Q21] lands extended fields. - [Q19c] Dynamic route (
<CommandPage>mounted on a catch-all/commands/[name]via a custom Docusaurus theme component). No generated.mdfiles. Most TS-heavy, hardest for a doc contributor to extend, but no codegen-output committed. Not worth the complexity for v1.
- [Q19a] Single generated page
Note: all three options use the same metadata. The choice is about file layout and where rendering happens. Q19a is the strong recommendation because it matches DCT, fits 11 commands cleanly on one page, and leaves room to add Q19b-style per-command pages as a follow-up if extended metadata makes them worth the surface area.
Out of scope (state explicitly so we don't drift later)
- Metadata-driven docs generation pipeline (deferred per B1 — revisit when the SCRIPT_CATEGORY metadata from
INVESTIGATE-uis-lessons.mdA3 lands). - Image-zoom and Mermaid-zoom (defer; reopen if/when diagrams land).
- Multi-language i18n (single locale
enis fine; matches TMP). - Versioned docs (Docusaurus supports
npx docusaurus docs:version; we don't yet have multiple shipping versions of the docs surface — release notes via [Q3] cover the "what changed" need).
Risks / things that could bite us
-
Existing relative links assume raw markdown viewing. Most
[link](../WORKFLOW.md)references work in Docusaurus too (it strips.mdautomatically), but some files link to plans files using paths likeplans/backlog/INVESTIGATE-noclickops.mdfromproject-noclickops.md. After Docusaurus renders, those resolve to/ai-developer/plans/backlog/INVESTIGATE-noclickops— fine, but worth a smoke test in the foundation PLAN. -
CLAUDE.mddeep-links from the repo root (e.g.website/docs/ai-developer/project-noclickops.md) keep working on the GitHub web UI because they're real file paths. They do not become hyperlinks in the rendered Docusaurus site (sinceCLAUDE.mdisn't a docs file). Acceptable —CLAUDE.mdis for tooling, not site visitors. -
onBrokenLinks: 'throw'(TMP's setting) will fail the build if any relative link insidedocs/resolves to nothing. The first Docusaurus build is going to find broken links — that's actually a feature for cleaning up the existing docset, but allocate time in the foundation PLAN to fix them rather than weakening to'warn'. -
README.mdat repo root vsdocs/index.md. See [Q10]. Whichever option wins needs to be written down somewhere; otherwise next quarter we have two stale README-like documents. -
GitHub Pages settings need a manual one-time toggle. Source = "GitHub Actions" rather than "Deploy from a branch." Easy to miss; the foundation PLAN should call it out explicitly.
-
No
noclickopslogo or social card exists yet. TMP shipslogo.svg,logo-dark.svg,social-card.jpg,favicon.ico. v1 can use Docusaurus defaults + a 5-minute text-only SVG; better assets are a follow-up.
Recommendation — phased PLAN proposal
Three child PLANs, sequenced. Each delivers something useful on its own; each commits at the end (per project-noclickops.md "commit per plan; PR per investigation").
[Q12] PLAN-A — website/ foundation (Docusaurus boots, existing docs render)
- Add
website/package.json,website/docusaurus.config.ts,website/sidebars.ts,website/tsconfig.json(TMP-shape, slimmed per [Q5]/[Q6]). - Add
website/src/css/custom.csswith the brand color block only (per [Q1]). - Resolve docs entry point per [Q7] (
website/docs/index.mdor repurposeai-developer/README.md). - Add
_category_.jsonfiles per [Q8]. - Add
node_modules/,website/build/,website/.docusaurus/to.gitignore. - Fix any broken intra-docs links surfaced by the first
npm run build(theonBrokenLinks: 'throw'will flush them out). - Validation:
cd website && npm install && npm run build && npm run startshows the site locally with the fullai-developer/tree in the sidebar. User confirms.
[Q13] PLAN-B — Public deploy (GitHub Pages + domain + CI)
- Add
.github/workflows/deploy-docs.yml(slimmed-down TMP shape per A4). - Add
website/static/CNAMEif [Q4a]/[Q4c] picked. - Set
url/baseUrl/organizationName/projectNameindocusaurus.config.tsto match [Q4]. - Document the one-time GitHub Pages → "GitHub Actions" toggle in the PLAN's smoke-test instructions.
- Validation: push to a
docs-deploybranch, run workflow viaworkflow_dispatch, confirm the site is reachable. Merge tomain, confirm path-filtered rebuild fires only onwebsite/**changes.
[Q14] PLAN-C — Marketing homepage + generated commands.md (always runs)
This is the work A6 + A7 / [Q2] / [Q18] / [Q19] commit us to. Sequencing: after PLAN-A (so the site builds), parallel with or after PLAN-B (deploy). Reference implementation: DCT's dev-docs.sh + src/components/{CategoryCard,CategoryGrid,ToolCard,ToolGrid,HomepageFeatures,QuickInstall} + src/pages/index.tsx.
- Add
scripts/generate-docs.shper [Q18] (Bash recommended). The generator sourceslib/metadata.sh, walksbin/*.sh, and emits:website/docs/commands.md— single page per [Q19a]: H2 per category, H3 per command (anchored), synopsis fromSCRIPT_USAGE, example fromSCRIPT_EXAMPLE, collapsible--helpblock. Direct port of DCT'sgenerate_commands_md()(dev-docs.shlines 1100–1229), scoped down.website/src/data/commands.json— one row per command (name, description, usage, example, category).website/src/data/categories.json— one row per category (id, label, description) derived from_NCO_VALID_CATEGORIES+ the lister display strings inbin/noclickops.shlines 90–94.
- Wire the generator to run per [Q18b'] (CI step recommended, matching DCT).
- Build React components (
website/src/components/), copying the shape of DCT's equivalents:CommandCategoryCard/+CommandCategoryGrid/(rename of DCT'sCategoryCard/CategoryGrid).CommandCard/+CommandGrid/(rename of DCT'sToolCard/ToolGrid).HomepageFeatures/(3-4 marketing cards: "One command per task", "Works in any repo", "Wraps existing pipelines", "No clickops") — copy adapted fromREADME.mdline 5.QuickInstall/(thecurl … install.shone-liner in a copy-able block).
- Build
website/src/pages/index.tsxper [Q2] layout choice. Hero copy mirrorsREADME.mdlines 5–7. If [Q2a] picked, onlyHomepageFeatures+QuickInstallappear on the homepage (lightest path). - Skip these DCT pieces:
FloatingCubes,AiDemo,RelatedTools(RelatedTools needsSCRIPT_RELATEDfrom [Q21]). - Provide a minimal placeholder logo + favicon if branding isn't ready yet (text-only SVG is fine; DCT's
cube-code-green.svgis 5kb). - Add a smoke check at the end of
generate-docs.sh: count of rows incommands.json== count ofbin/*.shfiles (catches drift if a script slips through without metadata). Matches DCT'scount_total_scripts()pattern (dev-docs.shline 477). - Add
scripts/to the gitignore-untouched paths in the deploy workflow's path filter, so changes to the generator trigger a docs rebuild. - Validation: run
bash scripts/generate-docs.shlocally →commands.md+ JSON files appear →cd website && npm start→ confirm hero / features / install render, confirm/docs/commandslists all 11 commands grouped by category with anchors working. Touch a script'sSCRIPT_DESCRIPTION, re-run the generator, confirm the change shows up.npm run buildsucceeds withonBrokenLinks: 'throw'.
[Q20] PLAN-D — Optional polish (only if [Q3a] / [Q5a] / [Q6a] selected)
- Enable Mermaid theme +
markdown.mermaid: trueper [Q5]. - Enable local search theme per [Q6].
- Enable blog with one starter post per [Q3].
- Validation: each enabled feature works against the live site.
If [Q3b] + [Q5b] + [Q6b] are all picked (the maximally-minimal path), PLAN-D is dropped entirely and the investigation completes after PLAN-C.
Open questions (track separately from the [Q] decision-points above)
-
[Q15] Does
noclickopsneed a separateCONTRIBUTING.mdonce docs are on the website? Right now contributor info is spread acrossREADME.md,CLAUDE.md,AGENTS.md, and theai-developer/tree. Probably out of scope for this investigation; flag for a follow-up if site structure makes the gap obvious. -
[Q16] Should the docs site link back to each plan file's source on GitHub (an "Edit this page" link)? Docusaurus supports
editUrlin the docs preset — basically free if we want it. -
[Q17] Does
noclickopswant analytics on the docs site (e.g. Plausible, Umami, Google Analytics)? Easy to add later, but worth deciding before [Q4] domain is announced. -
[Q21] Filed by A7: a follow-up INVESTIGATE or PLAN to extend
SCRIPT_*metadata with the six fields listed under A7's "What's missing" —SCRIPT_DETAILS,SCRIPT_FLAGS,SCRIPT_AUTH,SCRIPT_EXIT_CODES,SCRIPT_SEE_ALSO,SCRIPT_DEPENDS_ON. Out of scope here; tracked so it doesn't get lost. Trigger: once the v1 docs site is live, the gap between what the per-command pages render and what they should render will be obvious.
Next steps
- User reviews this investigation and marks up
[Q1]–[Q20](one-line answers per ID). After the 2026-05-29 DCT pivot, the recommended-path answers (matching DCT) are: [Q2a] (DCT homepage shape) · [Q18a] (Bash generator) · [Q18b'-a] (CI step) · [Q19a] (singlecommands.md). The other [Q]s (Q1 brand color, Q3 blog, Q4 domain, Q5 mermaid, Q6 search, Q7 docs entry, Q8 category.json, Q9 path filter, Q10 README drift, Q11 local-dev wrapper) are still open. - Open questions resolved, child PLANs drafted in
plans/backlog/PLAN-A-…,PLAN-B-…,PLAN-C-…, optionallyPLAN-D-…. The metadata-extension work from A7 / [Q21] is filed as a separate backlog INVESTIGATE/PLAN, not a child of this one. - PR opens when the last child PLAN of this investigation merges (per the "PR per investigation" rule in
project-noclickops.md).