Contributing docs

How to set up the docs site locally, write a new page, and avoid the patterns that make documentation feel AI-generated.

The docs site lives in a separate repository from the framework. Content is MDX under content collections, layout is plain Astro 6 with no Starlight, and search is Pagefind. Lychee checks every link in CI.

Contributions land in two flavors. Hand-authored pages — Build, Concepts, Operate, Agents, Resources — are MDX you edit directly. Generated pages — SDK reference, CLI reference, examples — are emitted by Python scripts under site/scripts/python/; you do not edit the MDX, you edit the source code in flux-src/ or the annotation files that augment the generator output.

Repo layout

flux-docs/
├── site/                          # the Astro app
│   ├── src/
│   │   ├── content/
│   │   │   ├── docs/              # all MDX content, one folder per top-level section
│   │   │   │   ├── get-started/
│   │   │   │   ├── build/
│   │   │   │   ├── agents/
│   │   │   │   ├── concepts/
│   │   │   │   ├── operate/
│   │   │   │   ├── reference/
│   │   │   │   ├── examples/
│   │   │   │   ├── deployment/
│   │   │   │   ├── integrations/
│   │   │   │   └── resources/
│   │   │   └── _annotations/      # editorial overlays for generated pages
│   │   ├── components/            # Astro components (Tabs, Admonition, Code)
│   │   ├── layouts/
│   │   └── styles/
│   ├── scripts/
│   │   └── python/                # generators for SDK / CLI / Examples
│   │       ├── generate_sdk_ref.py
│   │       ├── generate_cli_ref.py
│   │       ├── generate_examples.py
│   │       └── examples-order.yml # editorial ordering for example pages
│   └── package.json
├── flux-src/                      # the Flux framework, checked out as a sibling
├── docs/                          # the project's own design and roadmap docs
└── bin/                           # bash helpers (setup, regen-check)

flux-src/ is the framework checkout the generators read from. It is set up via bin/setup-flux-src.sh; treat it as read-only when editing docs.

Local development

# One-time: clone alongside flux-src
git clone git@github.com:<your-fork>/flux-docs.git
cd flux-docs
bash bin/setup-flux-src.sh    # clones flux into ../flux-src and creates a venv

# Daily workflow
cd site
npm install
npm run dev                   # local dev server on http://localhost:4321

Node 22.12 or newer is required (engines.node in site/package.json). The dev server has hot reload on MDX changes and shows broken links inline.

Regenerating from flux-src/:

npm run regen                 # regenerate SDK + CLI + examples in one shot
npm run regen:sdk             # SDK reference only
npm run regen:cli             # CLI reference only
npm run regen:examples        # examples only
npm run regen:check           # verify generators produce a clean diff

Run npm run regen after you pull a new flux-src/ or after the framework changes a signature you care about.

Frontmatter

Every page needs four frontmatter fields. The shape is:

---
title: Defining workflows
description: One sentence under 200 characters, used in search and meta tags.
sidebar:
  order: 1
diataxis: how-to
---

The section’s _meta.yml carries the section label and order:

label: Build
order: 2

Adding a new page

  1. Pick the section folder under site/src/content/docs/<section>/.
  2. Create <slug>.mdx or <subsection>/<slug>.mdx.
  3. Set the frontmatter (above).
  4. Write the page. Use components from src/components/ for code tabs, admonitions, and callouts.
  5. Cross-link to neighboring pages. Lychee in CI verifies every link.
  6. Run npm run dev and check the page renders cleanly.

For a new section, add a folder, an _meta.yml, and an index.mdx. Match the style of site/src/content/docs/resources/index.mdx — short prose introducing each subsection with inline links.

Style guide essentials

Voice: terse, technical, no marketing. The reader is an engineer with limited time who needs the answer or the example fast.

The patterns above come from review of phases 1 through 10 of this site. They are tells reviewers look for during PR review.

Code samples

Code samples render through Shiki with Python as the primary language. Use the Tabs component when an operation has both a Python SDK form and a CLI form:

import Tabs from '@components/Tabs.astro'
import TabItem from '@components/TabItem.astro'

<Tabs>
  <TabItem label="Python">
  ```python
  hello_world.run("World")
  ```
  </TabItem>
  <TabItem label="CLI">
  ```bash
  flux workflow run hello_world '"World"'
  ```
  </TabItem>
</Tabs>

Multi-language tabs (Python / TypeScript / Go) are scaffolded for the future; today only Python is populated. Do not write speculative TypeScript or Go samples — leave the tab off.

Generated content

Three sections are emitted by scripts:

To change generated content, you have two paths:

  1. Edit the source in flux-src/ — fix the docstring, rename the argument, rewrite the example. This is the right fix for most issues. After your framework PR merges, re-run npm run regen here.
  2. Add an annotation — drop a YAML or MDX file under site/src/content/_annotations/ mirroring the generated page’s path. The generator merges annotations on top of its output, so editorial framing (intro paragraphs, related-pages lists, “why this matters” sidebars) lives in annotations without modifying the source.

The annotation system was introduced in Phase 2 to keep editorial prose out of framework docstrings. See the existing files under _annotations/ for the shape.

Direct edits to generated MDX files will not survive the next npm run regen. CI runs npm run regen:check and fails the PR if the generator output diverges from what is committed.

Every link to another page goes through the rendered route, not the file path:

See [Defining workflows](/build/workflows/defining-workflows) for the full surface.

Lychee runs in CI on every PR and on cron against the deployed site. Broken internal links fail the build; broken external links open an issue. When a section is not yet shipped, add the link anyway with the future route — lychee has an exclude list for forward references (see lychee.toml). Phase shipping then removes the exclude.

Pull request workflow

1. Branch off main             git checkout -b docs/<short-name>
2. Make the change             one logical change per PR
3. Run regen if relevant       npm run regen
4. Verify with dev server      npm run dev, check the page renders
5. Run the link checker        npm run build (runs lychee offline)
6. Commit                      Co-Authored-By: lines are allowed here
7. Open the PR                 describe the why, scope, and any version-pin
8. Respond to review           commit, push, then reply

What reviewers look for:

Where to ask

Small fixes — typos, broken links, a clearer sentence — do not need an issue first. Open the PR.