Investigate: Documentation site structure and Docusaurus configuration health
Whether the current Docusaurus setup and docs organization actually serve their intended audiences well, what's fragile, and what's missing — triggered by retiring a stale docs-split plan and a real anchor-link bug found earlier this session.
IMPLEMENTATION RULES: Before implementing this plan, read and follow:
- WORKFLOW.md - The implementation process
- PLANS.md - Plan structure and best practices
Status: Backlog — Option A (onBrokenAnchors) shipped 2026-07-14
Goal: A grounded, evidence-based picture of the documentation site's real structural health — not a redesign for its own sake — so any follow-up work targets genuine gaps rather than guessed ones.
Last Updated: 2026-07-14 — folded in INVESTIGATE-developer-first-onboarding.md's one remaining open item (Option E1), since it's the same underlying "developer-facing docs/verification experience" question this investigation already covers. That investigation is now fully retired to completed/ — see its own banner for what shipped.
Trigger: retiring PLAN-onboarding-docs-split.md (superseded, never built as designed) surfaced a real, still-unmet gap — no generic developer-quickstart template exists, only ollacrm's own specific page. Separately, this session found a real, live bug class: a heading-derived hash anchor (#upgrade-2026-07-14--sovdev-logger102--self-verification-setup) that would have silently broken the moment its heading's wording changed, with no build failure to catch it. Both prompted a broader look rather than two narrow fixes.
Option A done: onBrokenAnchors: 'throw' added to docusaurus.config.ts, verified with a real deliberately-broken anchor causing a real build failure, then reverted the test. See git history (e494bc7) for the exact change.
Current State — checked directly, not assumed
1. onBrokenLinks: 'throw' is real and working
Confirmed by direct test, not just reading the config: moving PLAN-onboarding-docs-split.md to completed/ during this same session broke a relative link inside it (INVESTIGATE-developer-first-onboarding.md no longer resolved from the new location) — npm run build failed immediately with an exact, actionable error pointing at the broken link. This is a real, already-working safety net, not a theoretical one.
2. onBrokenAnchors is not configured — a real, confirmed gap
docusaurus.config.ts only sets onBrokenLinks: 'throw'. There's no onBrokenAnchors setting at all, and Docusaurus's own default for it is 'warn', not 'throw' — meaning a broken #heading-anchor fragment (a link resolving to the right page but the wrong section, or no section at all) would not fail the build, only print a warning easy to miss in CI output. This is exactly the class of bug found earlier this session: a link to using/onboarding/ollacrm#upgrade-2026-07-14--sovdev-logger102--self-verification-setup would have silently stopped working the moment that heading's text changed (which happened repeatedly during this same session's editing), with nothing forcing a fix.
3. Sidebar is fully autogenerated, no manual curation yet
sidebars.ts is a single {type: 'autogenerated', dirName: '.'} entry, with its own comment: "Reach for a manually curated array... once the docs tree grows complex enough to need custom ordering or grouping." Worth checking directly whether that threshold has already been passed — see finding 4.
4. Content is heavily skewed toward internal planning history, not published documentation
Direct file count under website/docs/:
| Directory | File count | Audience |
|---|---|---|
ai-developer/ | 59 | Internal — investigation/plan history (PLANS.md, WORKFLOW.md, every INVESTIGATE-*/PLAN-*) |
contributor/ | 20 | Contributors to sovdev-logger's own codebase |
using/ | 10 | Consumers integrating sovdev-logger into their own systems |
general/ | 4 | Cross-cutting philosophy/architecture |
ai-developer/ alone is larger than the other three directories combined, and it's all published to the same public site (sovdev-logger.sovereignsky.no) via the same autogenerated sidebar. This raises a real, unasked question: should the planning/investigation history be part of the public-facing docs site at all, or does it belong somewhere else (e.g. plain repo files, not built into the Docusaurus site)? Not answered by this investigation — flagged as [Q1] below.
5. Known, carried-over gap: no generic developer-quickstart template
From the retired PLAN-onboarding-docs-split.md: using/onboarding/ollacrm/index.md is the only developer-facing onboarding page that exists, and it's ollacrm-specific (package name references, services/api paths, etc.) — not a reusable template. The next customer after ollacrm has nothing generic to start from.
6. Search works — confirmed, not assumed
@easyops-cn/docusaurus-search-local is configured; npm run build genuinely produces build/search-index.json and a build/search/ route. Not a gap.
7. Folded in from INVESTIGATE-developer-first-onboarding.md: the public dashboard verification link (Option E1) still isn't built
That investigation's every other option shipped (docs rewrite, onboard-system.sh automation, the self-test CLI) — only Option E1 remains: Grafana Cloud's built-in "Share externally" feature, set up on the shared dashboard, pre-filtered to a developer's own service_name via URL query param. Already decided, not just proposed — confirmed as the only verification path that doesn't assume Grafana Cloud portal access a developer (confirmed, for ollacrm) doesn't have. No code changes, no library work — a Grafana Cloud portal setting plus confirming the resulting URL pattern (?var-service_name=<name>) actually works. Full research (Sentry/Datadog/Azure/GCP comparison) preserved in the retired investigation's own file, not repeated here.
Options
Option A: Fix onBrokenAnchors immediately, treat everything else as separate follow-up work — done
Set onBrokenAnchors: 'throw' in docusaurus.config.ts — a one-line config change, directly closes the exact fragility class already found once. Leave the content-organization questions (Tier/audience split, ai-developer/ publication question) for a later, separate decision.
Pros: cheap, immediate, directly addresses a confirmed real bug class with no design work needed. Cons: doesn't touch the larger structural questions (content skew, missing developer template) — but those are genuinely separate, bigger decisions, not blocked by this fix.
Option B: Full site reorganization now — decide ai-developer/'s public status, build the generic developer template, restructure the sidebar
Pros: addresses everything in one pass.
Cons: bundles a small, safe config fix with much bigger, judgment-call decisions (should 59 files of internal history be public? what does a generic template even look like before a second real customer exists to design it against?) — repeats the exact mistake INVESTIGATE-hold-dependency-upgrade-sweep.md already learned from (don't bundle a critical fix with open-ended design work).
Option C: Do nothing, revisit only if another anchor-link bug actually recurs
Pros: zero effort now.
Cons: the onBrokenAnchors gap is cheap to close and already proven to bite once — no real reason to wait for a second occurrence.
Recommendation
Option A now, everything else deferred pending real answers to the open questions below. The onBrokenAnchors fix is a one-line, zero-risk config change that closes an already-proven bug class — do it immediately, doesn't need its own PLAN-*.md. The larger structural questions (is ai-developer/ appropriately public? is a generic developer-quickstart template worth building speculatively, or only once a second customer actually onboards?) are genuine judgment calls, not technical fixes, and shouldn't be bundled with the cheap safety fix.
Open Questions
- [Q1] Should
website/docs/ai-developer/*(59 files of internal investigation/plan history) be excluded from the public Docusaurus build entirely, kept as-is (public but not prominently linked), or something in between (e.g. anoindexmeta tag so it doesn't show up in search engines, while staying reachable by direct link)? This project's own AI-collaboration workflow depends on these docs being somewhere readable/linkable (cross-references between investigations are everywhere) — the question is whether "somewhere" needs to be the same public site as customer-facing docs. - [Q2] Is a generic
developer-quickstart.mdtemplate worth building now, speculatively, or only once a second real customer (after ollacrm) actually onboards — matching this project's own repeated preference for building from evidence, not anticipation (seeINVESTIGATE-developer-first-onboarding.md's Option D deferral for the same reasoning)? - [Q3] Now that
ai-developer/alone is 59 files, hassidebars.ts's own stated threshold ("once the docs tree grows complex enough") been reached? If [Q1] answers "keepai-developer/public," does it need its own manually-curated sidebar grouping (e.g. collapsingcompleted/by default, since it's historical record rather than active reference)? - [Q4] Any other Docusaurus config worth auditing while in here — e.g. is
onBrokenMarkdownLinks(a related, distinct setting for raw markdown-style links vs. resolved anchor links) also at a safe default? Not checked yet, worth a direct look before closing this investigation. - [Q5] (Folded in from
INVESTIGATE-developer-first-onboarding.md) Set up Grafana Cloud's "Share externally" on the shared dashboard, confirm the pre-filtered?var-service_name=<name>URL pattern actually works (Option E1) — already decided, just not executed yet. Small enough to do directly, noPLAN-*.mdneeded.
Next Steps
- Implement Option A: set
onBrokenAnchors: 'throw'indocusaurus.config.ts, verified with a real build that it actually catches a deliberately-broken anchor — done 2026-07-14 - Set up Option E1 ([Q5]) — the single highest-value, lowest-cost remaining action across both this investigation and the one it absorbed
- Maintainer answers [Q1]–[Q3] — these are genuine judgment calls this investigation can't resolve on its own
- Check [Q4] directly before considering this investigation closed
Files to Modify (Option A only, for now)
website/docusaurus.config.ts— addonBrokenAnchors: 'throw'