Skip to content

Work on the documentation

This site is its own app, apps/elitea-docs, built with Astro Starlight. It has its own package.json and lockfile, so a change that touches only the docs starts only the CI — Docs workflow, plus the repository-wide guards that run on every pull request. It does not start the web, E2E or desktop pipelines.

Terminal window
cd apps/elitea-docs
npm ci
npm run dev # http://localhost:4321/docs/
npm run build # dist/, with the Pagefind search index
npm run preview # serve dist/ the way nginx will

The standalone and browser-test stacks build the web image’s spa target, which has only a placeholder at /docs/, so a docs-only change never rebuilds them. Use npm run dev here to read the docs locally.

DOCS_BASE sets the base path and defaults to /docs/, where the web image’s nginx serves the site. The GitHub Pages workflow builds with /elitea-platform/ instead. The search index is built from the rendered pages at build time (Pagefind), so nothing generated is committed.

  1. Write the page

    Add an .mdx file under src/content/docs/<section>/. Its front matter needs a title and a description; the title is the page heading, so the body starts without an # heading. File names are lowercase: the file name is the URL.

  2. Put it in the navigation

    Add the slug to the right group in src/nav/<tab>.ts. Each top-level tab becomes a sidebar topic. A page that is in no tab, or a tab entry with no page, fails npm run check.

  3. Link to it

    Link with root-relative paths such as /development/frontend. The build adds the base path, and npm run check:dist fails on any link or #anchor that does not resolve.

Every .mdx page can use these components without importing them: Note, Tip, Info, Warning, Check, Steps/Step, Tabs/Tab, Accordion/AccordionGroup, Card/CardGroup, Badge, Frame, Icon and Screenshot. The list lives in src/plugins/remark-docs-components.ts, and the content check fails a page that uses anything else. Icon and Card take Lucide icon names.

A ```mermaid fence renders as a diagram in the site’s colours, and redraws when the reader changes the theme.

A Screenshot with an id shows src/screenshots/<id>.webp. Each id must be in shots.manifest.ts, which tells the capture script which route and persona to shoot (see Documentation screenshots). Every image must be referenced by a page and be at most 250 KB.

CommandWhat it checks
npm run checkNavigation and files match, front matter, components, mermaid syntax, screenshot ids and sizes
npm run typecheckastro check: the components, plugins and config type-check
npm run buildThe site builds
npm run check:distEvery internal link and anchor in dist/ resolves, no page repeats an id, the web app’s hard-coded docs links name real pages, and every inline script’s hash is in the docs Content-Security-Policy

The docs CSP is apps/elitea-web/nginx/docs-security-headers.conf, which the web image installs beside its own. When a Starlight upgrade or a new component changes an inline script, run node scripts/check-dist.mjs --write-csp after a build to rewrite the hashes, and commit the result.