Skip to main content

Docs Site — Operations

How to run, build, deploy, and version docs.nquiry.ai — the Docusaurus-rendered docs site that serves docs/guide/, docs/admin/, and docs/reference/ to the public.

Source layout

The docs site lives in docs-site/ inside this repo. It does not copy the markdown — it points plugin-content-docs at ../docs/guide/, ../docs/admin/, ../docs/reference/. Editing a .md file in docs/ and rebuilding the site picks up the change.

investigation-app/
├── docs/ ← markdown source (3 sections)
│ ├── guide/ ← end-user
│ ├── admin/ ← operator / licensee
│ └── reference/ ← technical
└── docs-site/ ← Docusaurus app
├── docusaurus.config.js ← maps the 3 sections to URL paths
├── sidebars/ ← autogenerated per-section sidebars
├── src/ ← landing page + theme overrides
└── static/ ← favicon, images

Run locally

cd docs-site
npm install # first time
npm run start # serves at http://localhost:3000 with hot reload

The dev server hot-reloads when you edit any .md under docs/. If you change docusaurus.config.js, restart the server.

Build

cd docs-site
npm run build # outputs to docs-site/build/
npm run serve # serve the built site locally on :3000 (sanity check)

Broken-link warnings appear during build. They are warnings, not errors — the build succeeds and produces the site. Fix them in the source markdown when you find them; the weekly freshness sweep (NQU-670) also flags them.

Deploy

Code-wired in PR 2, but not yet live. PR 2 lands the terraform module (infrastructure/terraform/modules/docs-site/) and the GitHub Actions workflow (.github/workflows/docs-site-deploy.yml). The resources don't exist in AWS until terraform apply runs against environments/dev. PR 3 runs the apply and wires DNS for docs.nquiry.ai. Until PR 3 applies, the workflow will fail at the aws s3 sync step (target bucket doesn't exist yet).

How a deploy happens (after PR 3 lands)

  1. Merge to main with changes in any of docs/guide/**, docs/admin/**, docs/reference/**, docs-site/**, or .github/workflows/docs-site-deploy.yml
  2. The Docs Site Deploy workflow fires (concurrency-grouped — newer commits cancel in-flight builds)
  3. Workflow: npm ci + npm run build inside docs-site/ (~3 min)
  4. aws s3 sync docs-site/build/ s3://<bucket>/ --delete --cache-control "public,max-age=3600"
  5. aws cloudfront create-invalidation --distribution-id <id> --paths "/*"
  6. CloudFront edge cache refreshed; https://docs.nquiry.ai/ reflects the new content within 1–2 minutes

Required GitHub Actions secrets

SecretValueSource
AWS_ROLE_ARNAlready existsOutput of cicd module — same role used by app CI
DOCS_SITE_BUCKETSet after PR 3 applyterraform output -raw docs_site_bucket_name
DOCS_SITE_DISTRIBUTION_IDSet after PR 3 applyterraform output -raw docs_site_distribution_id

Manual deploy (operator-driven)

# 1. Build locally
cd docs-site
npm install
npm run build

# 2. Sync
aws s3 sync build/ "s3://$(cd ../infrastructure/terraform/environments/dev && terraform output -raw docs_site_bucket_name)/" \
--delete --cache-control "public,max-age=3600"

# 3. Invalidate
aws cloudfront create-invalidation \
--distribution-id "$(cd ../infrastructure/terraform/environments/dev && terraform output -raw docs_site_distribution_id)" \
--paths "/*"

Version cuts

Docusaurus's versioned-docs feature is not enabled in v1. When the app gets its first SLA-bound version cut, run:

cd docs-site
npm run docusaurus docs:version 0.4 # snapshots current docs as v0.4

This copies docs/ into docs-site/versioned_docs/version-0.4/ and freezes it. New work continues in docs/ (which becomes "Next"). The CloudFront site serves both at /v0.4/ and /next/.

Versioning is intentionally deferred until needed — once enabled, every doc change carries the cognitive cost of "which version does this go into?" Holding off until the first real customer-version boundary requires it.

Search is wired via @easyops-cn/docusaurus-search-local — a FlexSearch-based plugin that builds the index at build time and ships it as a static search-index.json. Zero infrastructure; works offline.

If the corpus gets large enough that local search feels slow, the swap path is Algolia DocSearch (free for open-source/docs projects) or a Lambda + OpenSearch backend. Decision deferred per NQU-715 acceptance.

Common operations

TaskCommand (from docs-site/)
Add a new sectionAdd a plugin-content-docs instance in docusaurus.config.js, point at the new docs/<name>/ dir, add a sidebar file, add navbar entry
Change site title / taglineEdit title / tagline in docusaurus.config.js
Add a top-nav linkEdit themeConfig.navbar.items in docusaurus.config.js
Add a footer columnEdit themeConfig.footer.links in docusaurus.config.js
Customize landingEdit src/pages/index.js and src/pages/index.module.css
Brand colors / fontsEdit src/css/custom.css (Infima CSS variables)
Force-rebuild the search indexnpm run clear && npm run build

Troubleshooting

MDX compilation error on a doc. Docusaurus 3 parses .md as CommonMark by default in this repo (markdown.format: 'detect'). If the error mentions JSX or "unexpected character," the file is being parsed as MDX — confirm the extension is .md not .mdx, and that the file doesn't open with ---\n followed by JSX-looking content.

Broken-link build warning. The link target doesn't exist in any of the 3 indexed sections (docs/guide, docs/admin, docs/reference). Fix the link in source. Note: links to docs outside those three sections (e.g. docs/working/, docs/decisions/) won't resolve — those dirs aren't published to the site.

Plugin global data not found for "docusaurus-plugin-content-docs" plugin with id "default". The search plugin needs docsPluginIdForPreferredVersion set to one of our actual plugin IDs (currently 'guide'). Already configured.

  • NQU-715 — Docs site stand-up (this work)
  • NQU-714 — IA proposal that defined the 3-section taxonomy
  • NQU-670 — Weekly Documentation Freshness Report
  • docs/admin/docs-maintenance.md — manual freshness procedures