Shoalrun documentation framework
For agents
Start with https://www.shoalrun.com/llms.txt for the documentation index, then read the Markdown pages it links. Skip to article. Documentation index. Read this page as Markdown.
How to

Share pages across documentation versions

Versioning one docs site without copying every page: share unchanged pages, vary sections, and publish changed pages separately.

Updated
Read as Markdown

Say you support v1 and v2. Your setup instructions are mostly the same, but v2 has a new credential and one extra guide. You can keep the common instructions in one source file, show the right credential in each version, and publish the extra guide only in v2.

Shoalrun calls each channel, version, and language combination a publication. You choose which publications a build makes. A Git branch or tag chooses which revision of the repository to build; it does not automatically create a docs version. For separate sites such as stable and next, see publish separate docs sites from Git.

Choose which versions exist

This config publishes two versions at /v1 and /v2:

docs.config.yaml (fragment)
publications:
  defaults: { channel: production, version: v1, language: en }
  channels:
    production: { pathPrefix: "" }
  versions:
    v1: { pathPrefix: /v1 }
    v2: { pathPrefix: /v2 }
  enabled:
    - { channel: production, version: v1, language: en }
    - { channel: production, version: v2, language: en }

enabled sets the combinations the build may publish. It does not create pages or fill gaps in them. The paths come from the prefixes above plus each page's slug.

Keep an unchanged page in one file

List the versions that should receive the page in its frontmatter. This one file creates /v1/start and /v2/start:

content/start.mdx
---
id: guide.start
title: Get started
summary: Set up your first request.
type: guide
slug: /start
publications:
  - { channel: production, version: v1 }
  - { channel: production, version: v2 }
language: en
access: { policy: public }
---

Install the client and create a project.

The publications list is explicit: add a version when the page should appear there, and omit it when the page should not. Only enabled combinations are built. Keep the same id and slug in every publication so links and the Version menu can find the corresponding page. A shared file cannot also set page-level channel or version.

Change just one part of a shared page

Put version-specific content inside <ForPublication>. The rest of the page stays shared:

Create a project, then choose a credential.

<ForPublication version="v1">

Use a legacy key.

</ForPublication>

<ForPublication version="v2">

Use a scoped key. [Set permissions](doc:guide.permissions)

</ForPublication>

You can select a channel, version, language, or a combination, such as <ForPublication channel="sandbox" version="v2">. Omitted attributes match any value. The block needs at least one attribute and ordinary block content. A doc: link inside a block resolves in that publication, so a v2-only target can live in a v2-only block.

If a whole page changes substantially, write separate source files with the same id and slug, each with its own channel and version. If a page exists only in v2, write only its v2 file. You do not need a blank v1 copy. The Version menu shows a matching page only where one was published.

Source choice Result
One file listing v1 and v2 The same page appears at both paths.
One file listing v1 and v2, with <ForPublication> blocks Shared text appears in both; each version gets its own selected blocks.
Two files with the same ID, one for each version Each version gets different page content.
One file assigned only to v2 The page appears only in v2.

Run shoalrun build docs.config.yaml dist and inspect dist/documents.json for the actual pages and routes. Links, navigation, search, and the Version menu use those published variants. A link to a page missing from the current publication fails the build instead of sending readers to another version.

Give each API version its own contract

When API behavior differs by version, bind an OpenAPI file to each publication in apis.<name>.publications. The top-level API source belongs to publications.defaults. A shared guide can refer to the same stable operation ID in both versions; each version resolves that operation against its own API source. The build fails if a page needs an API operation but that publication has no source. See API references for the config and example configs for full projects.

What agents receive

Each published page has a Markdown copy at its route plus .md, such as /v1/start.md and /v2/start.md. These are separate artifacts built from the same source file. Each copy includes only its own <ForPublication> sections, so an agent reading v1 instructions does not see v2-only text. documents.json, search-index.json, and the site's agent discovery files list the published variants and their Markdown URLs. A missing version of a page has no Markdown copy or search result. Published outputs lists those files.

For channel and prefix rules, see the publication configuration reference.

Add a language

To add a language such as Japanese, add its combination to enabled, then write a translated file for each page with that language. The translated file reuses the page's id and slug, so it is another language of the same page:

docs.config.yaml
publications:
  defaults: { channel: production, version: current, language: en }
  channels:
    production: { pathPrefix: "" }
  versions:
    current: { pathPrefix: "" }
  enabled:
    - { channel: production, version: current }
    - { channel: production, version: current, language: ja }
content/install.ja.mdx
---
id: guide.install
title: インストール
summary: Acme のコマンドラインツールをインストールします。
slug: /install
language: ja
---

The Japanese page publishes at /ja/install with lang="ja", and its Markdown copy is /ja/install.md. The default language keeps the ordinary route. Pages without a language are in the default language.

Shoalrun does not translate text. Your translation pipeline writes the files, one for each page and language. A page with no Japanese file has no Japanese version, and it gets no Markdown copy or search result there. To keep a language out of a build, leave it out of enabled.

Reference while working