Shoalrun documentation frameworkMenu
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.
Reference

Publications and routing settings

Configure versions, languages, navigation, and redirects.

Updated
Read as Markdown

Configure versions, languages, navigation, and redirects. These keys belong in docs.config.yaml or an included configuration file. For file composition and validation commands, see Configure your project. Use the configuration index to find another setting.

publications

Required. Declares which channel, version, and language combinations to build. See how Shoalrun works for the concepts.

These settings select page variants within a build. For separate branches and domains, see use Git branches for separate docs sites.

Key Meaning
enabled At least one { channel, version, language } entry. language is optional and defaults to the default language.
channels.<name>.pathPrefix Route prefix for a channel. Every channel used in enabled must be declared, even with pathPrefix: "".
versions.<name>.pathPrefix Route prefix for a version. Same rule as channels.
defaults.channel, defaults.version The publication that uses each API's top-level source, and the defaults for scaffold and api select. Required when the project has apis.
defaults.language The default language, which gets no route prefix. Global frontmatter can override it. Falls back to en.
externalSites Optional links in the Version menu. Each entry needs a label and HTTP(S) baseUrl, which links to that site's root. Add a local manifest file containing its built documents.json to link only matching document IDs at their published paths.

For a page in several enabled combinations, set its frontmatter publications to a list of { channel, version } pairs. This is separate from apis.<name>.publications, which binds API source files. A page without a list uses its resolved single channel and version. A list may include a declared but disabled combination; that copy is omitted from the build. See share pages across documentation versions for an example with version-specific sections.

A single publication with no prefixes. Pages set channel: production and version: current:

docs.config.yaml
publications:
  defaults: { channel: production, version: current, language: en }
  channels:
    production: { pathPrefix: "" }
  versions:
    current: { pathPrefix: "" }
  enabled:
    - { channel: production, version: current }

Two API versions side by side. A v1 page at /guides/start is published at /v1/guides/start:

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

A sandbox channel, with a version that is declared but not yet built. Leave a combination out of enabled to stop publishing it without deleting its pages:

docs.config.yaml
publications:
  defaults: { channel: production, version: v1 }
  channels:
    production: { pathPrefix: "" }
    sandbox: { pathPrefix: /sandbox }
  versions:
    v1: { pathPrefix: "" }
    v2: { pathPrefix: /v2 }
  enabled:
    - { channel: production, version: v1 }
    - { channel: sandbox, version: v1 }

English at the root and German under /de. Pages without a language are English:

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

A list of sidebar nodes. Each node has a unique id and exactly one of doc, operation, generated, or items. Unknown node keys fail. See navigation.

Key Meaning
id Unique node ID. Required.
doc A page ID.
operation A stable operation ID; shows that operation's reference page.
items Child nodes, optionally loaded from another YAML list with $include; makes the node a group. Groups need a label.
label Menu text. Defaults to the page title for doc and operation nodes.
search Extra words for the sidebar navigation filter, separate from site-wide search. Allowed on page and operation nodes, not groups or generators.
api Limits a group or generator to one API. Children inherit it.
tab Set true on a top-level group to give it a navigation tab and sidebar. Requires landing; nested tabs are rejected.
landing Stable ID of a page inside the tab's items. The tab links to that page in each publication.
tag An OpenAPI tag for a group that uses generated: remaining.
generated tags or remaining. Adds generated reference pages.

Pages and groups:

config/nav.yaml
- id: start
  doc: guide.overview
- id: guides
  label: Guides
  items:
    - id: first-payment
      doc: guide.create-payment
      label: Your first payment
      search: checkout charge
    - id: errors
      doc: guide.handle-errors

Mix authored pages, a pinned API operation, and generated reference pages grouped by OpenAPI tag:

config/nav.yaml
- id: payments
  label: Payments API
  api: payments
  items:
    - id: payment-guide
      doc: guide.create-payment
    - id: create-payment
      operation: payments.create
    - id: other-payment-pages
      generated: tags

Fill one hand-made group with the remaining operations for a tag:

config/nav.yaml
- id: reports
  label: Reports
  api: payments
  tag: Reports
  items:
    - id: report-guide
      doc: guide.reports
    - id: report-operations
      generated: remaining

redirects

A list of old URLs to send to a current page. Shoalrun's own docs use redirects to preserve links when changelog entries are combined.

Add a redirect when a URL that readers, bookmarks, or other sites already use would stop working:

  • You change a page's slug. The slug sets the URL, so the old path no longer has a page.
  • You change site.basePath, a channel or version pathPrefix, or a language prefix. Every route under it moves.
  • You delete a page, merge two pages, or replace a page with one in another version.

You don't need a redirect when a page keeps its slug. Moving or renaming the source file doesn't change a URL, and neither does changing navigation. The URL comes from the slug, not the file.

List the redirects under redirects in docs.config.yaml, or keep them in a file and include it:

docs.config.yaml
redirects: { $include: ./config/redirects.yaml }

The versioned API documentation example shows a complete config with a redirect. Each entry looks like this:

config/redirects.yaml
- from: /guides/old-payment
  to: { doc: guide.create-payment, channel: production, version: current, language: en }

Use a different status, such as 301 for clients that don't support 308:

config/redirects.yaml
- from: /getting-started
  to: { doc: guide.overview, channel: production, version: current, language: en }
  status: 301

Send an old URL to a page in another publication, such as a retired v1 page to its v2 version:

config/redirects.yaml
- from: /v1/guides/webhooks
  to: { doc: guide.webhooks, channel: production, version: v2, language: en }

Because the target is a page ID, the redirect follows the page when its slug changes. Nothing else needs updating.

Key Meaning
from Old path, starting with /. Compared without regard to case; a duplicate or a path that belongs to a current page fails.
to Target page ID and its full publication: doc, channel, version, and language are all required.
status HTTP status: 301, 302, 303, 307, or 308. Defaults to 308.

The build resolves each target to its current route and writes redirects.json. shoalrun serve and the Vercel build apply the redirects, with or without a trailing slash. The old page's .md URL redirects to the target's Markdown twin with the same status.

Read first

Reference while working