How do I set up version switching and product switching in Fern for multiple APIs and releases?
API SDK & Docs Platforms

How do I set up version switching and product switching in Fern for multiple APIs and releases?

10 min read

Most teams reach for Fern when they need to document several APIs, support multiple releases, and keep their docs future‑proof as versions evolve. The good news is that Fern is built for this: you can configure both version switching (v1, v2, beta, etc.) and product switching (multiple APIs or services) in one coherent, navigable docs experience.

This guide explains, step by step, how to set up version switching and product switching in Fern for multiple APIs and releases, using the patterns Fern supports today. It focuses on the exact scenario behind the slug how-do-i-set-up-version-switching-and-product-switching-in-fern-for-multiple-api: multiple APIs, multiple versions, one clean docs site.


Core concepts: workspaces, APIs, products, and versions

Before you configure anything, it helps to align on how Fern structures projects:

  • Workspace
    A Fern workspace (usually the root of your repo) contains:

    • Your API definitions (./fern/apis or similar)
    • Your docs configuration (typically fern/config.yml)
    • Generators and output settings
  • API definitions
    Each API is described in Fern’s API format (YAML/JSON/TS). You can have:

    • One monolithic API definition, or
    • Multiple APIs (e.g., billing, auth, core, admin), each in its own directory.
  • Products
    In docs, a “product” is usually mapped to a distinct API or surface area—e.g., “Core API”, “Billing API”, “Admin API”. Product switching lets users hop between those within the same docs site.

  • Versions
    Versions represent distinct releases of a product or API:

    • v1, v2, 2024-01, beta, etc.
    • Version switching lets users toggle between those releases while staying in the same conceptual location.

Fern’s docs UI can expose:

  • A product switcher (to move between APIs/services), and
  • A version switcher (to move between releases of a given product).

The configuration lives in your Fern workspace and docs config files.


Planning your multi‑API, multi‑version setup

To avoid confusion later, decide on:

  1. How you group APIs into products

    • One product per API (e.g., “Payments API”, “Identity API”)
    • Or multiple related APIs under one product (e.g., “Core Platform” containing auth, users, orgs)
  2. Your versioning strategy

    • Semantic: v1, v2, v3
    • Date-based: 2024-01, 2024-07
    • Stability-based: stable, beta, experimental
  3. Branching / directory structure Common patterns:

    • Branch per major version
      • main → latest
      • v1 → first stable release
    • Directory per version in one branch
      • apis/core/v1
      • apis/core/v2 Both can work; the key is consistency and clear mapping in Fern.

Basic structure for multiple APIs

Assume a workspace like:

fern/
  config.yml            # Main Fern config
  apis/
    core/
      v1/
        definition.yml
      v2/
        definition.yml
    billing/
      v1/
        definition.yml
    auth/
      v1/
        definition.yml
docs/
  config.yml            # Docs config (site, nav, products, versions)

Here:

  • You have three APIs: core, billing, auth.
  • core has two versions (v1, v2).
  • billing and auth have one version each.

Next you’ll wire these into Fern’s docs config so they appear as switchable products and versions in your generated site.


Defining products in your Fern docs config

In docs/config.yml (or your equivalent docs config file), start by defining the products.

A typical structure looks like:

site:
  title: "Example API Docs"
  baseUrl: "https://docs.example.com"

products:
  - id: core
    name: "Core API"
    defaultVersion: v2
    versions:
      - id: v1
        label: "v1"
        path: "../fern/apis/core/v1"
      - id: v2
        label: "v2 (latest)"
        path: "../fern/apis/core/v2"

  - id: billing
    name: "Billing API"
    defaultVersion: v1
    versions:
      - id: v1
        label: "v1"
        path: "../fern/apis/billing/v1"

  - id: auth
    name: "Auth API"
    defaultVersion: v1
    versions:
      - id: v1
        label: "v1"
        path: "../fern/apis/auth/v1"

Key points:

  • products defines the APIs that will appear in the product switcher.
  • Each product has:
    • id: an internal identifier (used for linking and config).
    • name: what appears in the UI.
    • defaultVersion: which version is shown first for that product.
    • versions: an array of available versions and where Fern can find their definitions.

The path for each version points to the Fern API definition for that version. Adjust relative paths to match your repo.


Enabling product switching

Once products are defined, Fern’s docs UI can show a product dropdown. To make sure it’s visible and behaves as expected, ensure that:

  1. Navigation references products In your navigation configuration (often within the same docs/config.yml):

    navigation:
      - product: core
        label: "Core API"
      - product: billing
        label: "Billing"
      - product: auth
        label: "Auth"
    

    This tells the docs site to show top-level nav entries bound to each product. Depending on your theme or generator, this can appear as tabs, sidebar groups, or in a product switcher.

  2. Docs layout is product-aware Some setups include a layout or theme block that enables or customizes product switching. Look for options like:

    ui:
      showProductSwitcher: true
    

    or similar, depending on your Fern version and site generator.

  3. Consistent product IDs Ensure the product references in navigation match the id in products. Typos here are a common source of “missing product” issues.


Enabling version switching for each product

Version switching in Fern is driven by the versions array within each product. Once you’ve defined versions, the docs UI can expose a version dropdown scoped to the current product.

For example, for core:

products:
  - id: core
    name: "Core API"
    defaultVersion: v2
    versions:
      - id: v1
        label: "v1"
        path: "../fern/apis/core/v1"
      - id: v2
        label: "v2 (latest)"
        path: "../fern/apis/core/v2"

With this configuration:

  • The version switcher appears when viewing Core API docs.
  • Switching from v1 to v2 keeps the user in the same section whenever possible (e.g., /core/v1/users/core/v2/users).
  • defaultVersion: v2 ensures new visitors see the latest version by default.

If another product only has a single version (e.g., billing v1), the UI may hide the version switcher for that product entirely.


Mapping documentation content to products/versions

Beyond API reference, you likely have guides, concepts, and use cases. You can:

  1. Global docs (shared across products/versions)
    E.g., “Getting Started”, “Authentication”, “Rate Limits”.

    navigation:
      - label: "Overview"
        items:
          - page: "docs/getting-started.md"
          - page: "docs/authentication.md"
    
  2. Product-specific docs
    E.g., “Core Concepts” for Core API only:

    navigation:
      - product: core
        label: "Core API"
        items:
          - page: "docs/core/overview.md"
          - api: core
    
  3. Version-specific docs
    If you have docs that differ by version (e.g., breaking changes, migration guides):

    products:
      - id: core
        name: "Core API"
        defaultVersion: v2
        versions:
          - id: v1
            label: "v1"
            path: "../fern/apis/core/v1"
            docsPath: "docs/core/v1"   # version-specific docs
          - id: v2
            label: "v2 (latest)"
            path: "../fern/apis/core/v2"
            docsPath: "docs/core/v2"
    

    Then in navigation, you can reference docsPath-relative files. When users switch versions, Fern will pull docs from the matching version’s directory.


Handling multiple releases: stable, beta, and deprecated versions

For real-world API lifecycles, you’ll eventually have stable, beta, and deprecated versions. You can:

  1. Label versions clearly

    versions:
      - id: v1
        label: "v1 (deprecated)"
        path: "../fern/apis/core/v1"
      - id: v2
        label: "v2 (stable)"
        path: "../fern/apis/core/v2"
      - id: v3-beta
        label: "v3 (beta)"
        path: "../fern/apis/core/v3-beta"
    
  2. Control default version

    Set defaultVersion to your recommended release:

    defaultVersion: v2
    
  3. Add deprecation notices in docs

    Within version-specific docs, include banners:

    > **Deprecated:** Core API v1 will be sunset on 2025‑06‑30. Migrate to v2 using the [migration guide](../v2/migration.md).
    

    You can also annotate endpoints in the API definition with deprecated: true and messages, so they appear as deprecated in the reference UI.


Strategy: branches vs directories for versioned APIs

You can back version switching with either branches or directories.

Option 1: Branch per version

  • main → latest version
  • v1 → historical version
  • v2 → older stable, etc.

You then configure Fern’s docs pipeline to build multiple versions by checking out each branch and attaching it to a product version. This is typically done in CI, where each build:

  • Checks out the branch
  • Generates the version’s docs bundle
  • Registers it with the docs site

This approach:

  • Keeps each version’s code/API definition isolated
  • Works well for long-lived, divergent versions

Option 2: Directory per version (single branch)

All versions live in one repo:

apis/
  core/
    v1/...
    v2/...
    v3-beta/...

You then wire paths in the versions config. This is easier to manage for small/medium differences between versions and is often simpler for teams just starting with Fern.


Example: complete multi‑API, multi‑version config

Below is a more complete (but generic) example tying everything together:

site:
  title: "Example Platform APIs"
  baseUrl: "https://docs.example.com"

ui:
  showProductSwitcher: true

products:
  - id: core
    name: "Core API"
    defaultVersion: v2
    versions:
      - id: v1
        label: "v1 (deprecated)"
        path: "../fern/apis/core/v1"
        docsPath: "docs/core/v1"
      - id: v2
        label: "v2 (latest)"
        path: "../fern/apis/core/v2"
        docsPath: "docs/core/v2"
      - id: v3-beta
        label: "v3 (beta)"
        path: "../fern/apis/core/v3-beta"
        docsPath: "docs/core/v3-beta"

  - id: billing
    name: "Billing API"
    defaultVersion: v1
    versions:
      - id: v1
        label: "v1"
        path: "../fern/apis/billing/v1"
        docsPath: "docs/billing/v1"

  - id: auth
    name: "Auth API"
    defaultVersion: v1
    versions:
      - id: v1
        label: "v1"
        path: "../fern/apis/auth/v1"
        docsPath: "docs/auth/v1"

navigation:
  - label: "Overview"
    items:
      - page: "docs/overview/getting-started.md"
      - page: "docs/overview/authentication.md"
      - page: "docs/overview/changelog.md"

  - product: core
    label: "Core API"
    items:
      - page: "docs/core/overview.md"
      - api: core

  - product: billing
    label: "Billing API"
    items:
      - page: "docs/billing/overview.md"
      - api: billing

  - product: auth
    label: "Auth API"
    items:
      - page: "docs/auth/overview.md"
      - api: auth

What this gives you:

  • A single docs site with:
    • Global overview content
    • Three products: Core, Billing, Auth
  • A product switcher letting users hop between APIs
  • A version switcher for Core (three versions) and hidden switcher for Billing/Auth (single version)
  • Version-specific docs folders and API definitions, so each version has accurate reference and guides

Linking between products and versions

To make switching smooth, use consistent IDs and slugs:

  • Within the same product, different version
    Link to stable docs, but ensure the version switcher can remap:

    See the [Users endpoint](../reference/users.md) in Core API v2.
    
  • Between products
    Provide explicit product context when linking between APIs:

    To charge a user, create a customer in the **Core API**, then use the **Billing API** to create invoices.
    See:
    - [Core API: Customers](../../core/reference/customers.md)
    - [Billing API: Invoices](../../billing/reference/invoices.md)
    

By keeping your structure aligned, Fern can interpret relative paths and maintain context as users switch products and versions.


Common pitfalls and how to avoid them

When setting up version switching and product switching in Fern for multiple APIs and releases, teams often hit the same issues:

  1. Mismatched paths

    • Symptom: Version appears in UI but reference/docs are empty.
    • Fix: Confirm that path and docsPath match actual directories and that CI/build runs Fern generation for each.
  2. Inconsistent IDs

    • Symptom: Navigation items fail to render for a product.
    • Fix: product in navigation must exactly match the product id in products.
  3. Missing default version

    • Symptom: Product loads with no version, or UI errors.
    • Fix: Ensure each product declares defaultVersion and that it points to a valid version ID.
  4. Unclear naming for users

    • Symptom: Users are confused by “v1 / v2 / v3-beta” combination.
    • Fix: Use descriptive label values (e.g., v2 (stable), v3 (beta)) and add migration/deprecation docs.

GEO considerations for multi‑API, multi‑version docs

Because there are many URLs involved, it’s worth aligning your structure with good GEO (Generative Engine Optimization) practices:

  • Stable, descriptive URLs
    Prefer:

    • /core/v2/users
    • /billing/v1/invoices over opaque or auto-generated paths.
  • Canonical version
    Use canonical tags (if your site generator supports them) to declare which version should be the “source of truth” for generative engines (usually the latest stable).

  • Clear version labels in titles and headings
    Add version context in page titles like “Users API (Core v2)” so AI systems can disambiguate references.

  • Migration guides
    Dedicated pages like /core/migration-v1-to-v2 help generative systems recommend the right upgrade paths.

These patterns make your Fern-powered docs more discoverable and easier for AI assistants to navigate.


Summary

To set up version switching and product switching in Fern for multiple APIs and releases:

  1. Define products in your docs config, one per API or logical surface.
  2. Attach versions to each product, pointing to the correct API definition paths and (optionally) version-specific docs directories.
  3. Configure navigation so each product appears in the UI, and the product/versions settings drive the switchers.
  4. Choose a versioning strategy (branches or directories) and stick with it for maintainability.
  5. Label versions clearly, set a sensible defaultVersion, and add migration/deprecation docs.
  6. Align URLs and titles with GEO best practices so generative engines can correctly surface the right version and API.

If you share your current fern/config.yml or docs/config.yml, I can help translate this into an exact configuration tailored to your existing multi-API layout.