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:
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:
---
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:
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 }
---
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.