---
title: Versioning
description: "Publish multiple versions of your documentation with a version switcher, versioned URLs, and deprecation banners."
---

# Versioning

Ship documentation for multiple product versions side by side. Readers pick a version from a dropdown in the doc-site header; each version gets its own URL space, its own search scope, and — for retired versions — a deprecation banner.

## Configure versions

Declare your versions in `syntext.json` under `versioning.versions`:

```json title="syntext.json"
{
  "name": "Acme Docs",
  "versioning": {
    "versions": [
      { "label": "v2", "branch": "main", "default": true },
      {
        "label": "v1",
        "branch": "v1",
        "deprecated": true,
        "deprecationMessage": "v1 is deprecated and will sunset on March 1, 2027. Migrate to v2."
      }
    ]
  }
}
```

Versioning can also be configured in the dashboard under project settings — when both exist, `syntext.json` wins.

### Version fields

| Field | Type | Description |
|---|---|---|
| `label` | `string` | **Required.** The version name shown in the switcher and used as the URL prefix (e.g. `v1`). |
| `branch` | `string` | Git branch to build this version from. |
| `tag` | `string` | Git tag to build this version from. Takes precedence over `branch`. |
| `default` | `boolean` | Marks the version served at the site root. Defaults to the first version in the list. |
| `deprecated` | `boolean` | Shows a **deprecated** badge in the switcher and a warning banner when readers view this version. |
| `deprecationMessage` | `string` | Custom banner text for a deprecated version. |
| `autoRedirectToLatest` | `boolean` | Redirects (`302`) any request for this version to the same path on the default version — for versions you've fully retired. |

Each version resolves to a git ref with this precedence: `tag` > `branch` > `label` (the label is used as a branch name when neither is set).

## Creating a version

The recommended workflow when shipping a new major version:

1. **Freeze the old docs** — create a branch (or tag) from your default branch at the point you want to preserve: `git branch v1 main && git push origin v1`
2. **Keep writing on `main`** — it remains the default (latest) version and is still served at the site root
3. **Declare both versions** in `syntext.json` on `main`:

```json
{
  "versioning": {
    "versions": [
      { "label": "v2", "default": true },
      { "label": "v1", "branch": "v1", "deprecated": true }
    ]
  }
}
```

4. **Push to your default branch.** After the production build deploys, Syntext automatically builds every non-default version from its own branch or tag and deploys it under `/{label}/` — no extra builds to trigger.

Versioned builds always use the `versioning` config from your default branch, so old branches don't need their `syntext.json` updated. Fan-out requires a git-connected project; CLI-upload projects (`stx deploy`) can't build historical refs and only serve the uploaded version.

## URLs

The default version is served at the site root — its URLs never change when you adopt versioning. Every other version lives under its label as a path prefix:

```
https://acme-docs.syntext.dev/getting-started      ← v2 (default)
https://acme-docs.syntext.dev/v1/getting-started   ← v1
```

## The version switcher

When two or more versions are configured, a version dropdown appears in the header next to your brand on every guide and API-reference page:

- The default version is badged **latest**; deprecated versions are badged **deprecated**
- Switching versions preserves your current page path — `/v1/guides/webhooks` switches to `/guides/webhooks`, not to the homepage
- Viewing a deprecated version shows a banner below the header with your `deprecationMessage` (or a sensible default pointing readers at the latest version)

With a single version (or no `versioning` block) no switcher is rendered.

## Versioned search

Search results are scoped to the version being browsed. The search API accepts a `version` parameter that filters hits to that version's URL prefix, so readers on `/v1/...` never see `v2` pages in their results.

## Comparing versions

The API can diff two versions' page inventories — useful for "what changed in v2" pages:

```
GET /v1/projects/{projectId}/versions/diff?from=v1&to=v2
```

> **Note:** After adding or changing `versioning`, push to your default branch (or trigger a deploy) — the version manifest, switcher, and all versioned builds are rebuilt automatically.
