Skip to content

Docs site

Source: apps/docs/ · Spec: §2.2, §14 (M4)

Astro Starlight static site (astro 7.1.3 + @astrojs/starlight 0.41.4), a workspace package named beetl-docs under apps/*.

Two kinds of pages:

  • Hand-authored (committed in apps/docs/src/content/docs/): the landing page (index.mdx, Starlight hero), getting-started.md, cli-reference.md (command map linking into the subsystem pages), configuration.md (the full project/user config reference), and an intentional 404.md splash page.
  • Synced from the canonical docs/features/*.md pages by apps/docs/scripts/sync-content.mjs (plain Node, no deps) into apps/docs/src/content/docs/features/. The script injects frontmatter — title taken from the first # heading, which is then dropped since Starlight renders the title — and keeps existing frontmatter untouched if a source page ever gains any. The synced directory is gitignored; never edit it, edit docs/features/ instead. Sync runs automatically via predev/prebuild.

Sidebar: Getting Started, CLI reference, Configuration, then an autogenerated “Subsystems” group over the synced features/ directory.

Terminal window
pnpm --filter beetl-docs dev # sync + astro dev
pnpm --filter beetl-docs build # sync + astro build → apps/docs/dist
pnpm --filter beetl-docs preview # serve the built site locally
pnpm --filter beetl-docs sync # sync only

Deploy target is Cloudflare Workers static assets: apps/docs/wrangler.jsonc (worker name beetl-docs, assets.directory: ./dist). Wrangler is pinned as a devDependency of apps/docs; pnpm --filter beetl-docs deploy:dry validates the config without deploying and runs in CI. Deploying (pnpm --filter beetl-docs run deploy) is user-gated — never deploy from an agent session. The run is required: deploy is a built-in pnpm command, so omitting it invokes pnpm’s own deploy and fails with ERR_PNPM_INVALID_DEPLOY_TARGET.

The site is published at https://beetl.weberx.dev. That hostname appears in two places, and both must agree:

  • site in apps/docs/astro.config.mjs — the canonical URL Starlight uses for the sitemap and for absolute canonical/OG links.
  • the routes entry in apps/docs/wrangler.jsonc (custom_domain: true) — declared in the repo rather than only in the dashboard, so the hostname is version-controlled. Wrangler manages the DNS record in the weberx.dev zone on deploy.

apps/docs is intentionally outside the root pnpm check pipeline: it is not a tsconfig.json project reference (Astro types don’t fit the tsgo build), and vitest’s include only covers packages/*. oxlint/oxfmt do cover the committed files under apps/docs; the synced content and dist/ are gitignored and excluded. CI covers the site through a dedicated docs job (Node 22) that builds the site and runs the wrangler dry-run, keeping pnpm check fast.