Contributing to these docs
This site is an Astro Starlight project in docs/site/ of the
Legion repository. Every push to main publishes it to GitHub
Pages, and every pull request that touches it builds it, so a broken page or link fails the pull
request before it can merge.
Building it locally
Section titled “Building it locally”From the repository root, with Bun, Go and Node.js 22.12 or newer installed:
bun install --cwd docs/sitebun run docs:dev # generate the reference pages, then serve the site with live reloadbun run docs:build # generate the reference pages, then build the site into docs/site/dist/Page layout
Section titled “Page layout”Pages live in docs/site/src/content/docs/, one Markdown (.md) or MDX (.mdx) file per page.
The file’s path is its URL: dispatch/inbox.md is published at /legion/dispatch/inbox/.
| Path | What it holds |
|---|---|
index.mdx, how-it-fits.md |
The Overview: the landing page and how the components fit together. |
legion/ |
Legion, the coordinator and its agents. |
dispatch/ |
Dispatch, issues and the decisions people make there. |
broker/ |
The Secrets Broker. |
<section>/reference/ |
Generated reference pages. Never edit or commit these; see below. |
Every page starts with frontmatter:
---title: The Inbox # the page heading and its sidebar labeldescription: One sentence saying what the page covers. # used for search results and link previewssidebar: order: 2 # optional: lower numbers sort first within the section label: Inbox # optional: a shorter sidebar label than the title---Write the body as if the title were already its first heading: start with ## headings. A diagram
is a fenced code block whose language is mermaid; it renders in the page and follows the light or
dark theme.
Adding a page to a section
Section titled “Adding a page to a section”Create the file in the section’s directory. Each section’s sidebar is built from its directory, so
the page appears there without any configuration; set sidebar.order to place it. A section’s
index.md is its introduction and sorts first (order: 0). A subdirectory becomes a collapsible
group in the sidebar.
Linking between pages
Section titled “Linking between pages”Every link to another page on this site is root-absolute and starts with the site’s /legion base,
because the site is served under /legion/ and nothing adds the base for you:
- a page linking a sibling in its section:
[Documents](/legion/dispatch/documents/); - a page linking its section’s generated reference:
[Tools](/legion/dispatch/reference/tools/); - a section page linking the overview:
[How it fits together](/legion/how-it-fits/).
The build checks every internal link and fails on one that leads nowhere, and on a link to a heading
that does not exist (/legion/how-it-fits/#no-such-heading). It also fails on a relative link such
as ../documents/: the link validator either refuses relative links (its default,
errorOnRelativeLinks) or, with that turned off, never checks them, so a broken one would ship.
Generated reference pages
Section titled “Generated reference pages”Reference pages that describe code, such as an HTTP API, a CLI or a tool list, are generated from
that code on every build and never committed, so they cannot drift from it. They come from
generators, and bun run generate (part of dev and build) runs them under this contract:
- Name and place. A generator is an executable file directly in
docs/site/generators/named<section>-<name>.tsor<section>-<name>.sh, where<section>is one of the content directories above (legion,dispatch,broker). Subdirectories ofgenerators/hold shared helpers and are never run. A file directly ingenerators/that breaks these rules fails the build. - Invocation. It runs from the repository root as
<generator> <absolute content dir>, where the content directory isdocs/site/src/content/docs. A.tsgenerator runs through Bun. - Binaries. Before any generator runs,
docs/site/scripts/build-binaries.shbuilds the Go binaries from the same commit and puts them first on the generator’sPATH:legion,envoy-dispatch,envoy-broker,agent-secretsandagent-secrets-helper. - Output. It writes its pages, with frontmatter like any other page, under
<content dir>/<section>/reference/. That directory is emptied before the generators run and is ignored by git. The sidebar shows it as the section’s Reference group. - Failure. A generator that exits non-zero, or exits zero without writing a page, fails the build.
generators/legion-skills.ts is a small example: it lists every skill in skills/ by the name and
description in its SKILL.md, as Skills.
The scripts that make screenshots and narrated walkthroughs live in docs/site/media/, and its
README says how to run and extend them. Screenshots are taken in CI before every site build and
are not committed; videos are committed with their sources. Only their output goes in
docs/site/public/media/, which the site publishes as it is. A file at public/media/<path> is
published at /legion/media/<path>, so a page embeds a screenshot as
.
Media shows example data only: this repository is public, so no real hostname, account, token or
private URL appears in a page, image or video.
The secrets broker’s media is made differently. It needs a rig of its own (a broker, its client
and an example agent machine) that the shared harness does not boot and CI does not run, so its
screenshots are committed too, and its walkthrough has a build of its own:
docs/site/media/broker/walkthrough/build.py makes it from the cut in edl.py, not
walkthrough.ts. Its terminal casts are recorded live against the rig between its browser
sections, since each section acts on what the one before it left. Its browser sections are
Playwright’s recordVideo at 1280x720, which build.py renders at 30 fps. The shared pipeline
avoids that recorder for its blur; this walkthrough keeps it because the committed footage and the
marks the cut is placed at come from it, and changing it needs a new take. It publishes the video,
its captions and its poster to public/media/broker/.
docs/site/media/broker/walkthrough/README.md says how to record and build it.