# Tabs, versions, languages and products

> For the complete documentation index, see [llms.txt](https://preview.writedocs.io/llms.txt).

More than one sidebar - tabs, versions, languages, products and dropdowns, and how they nest.

When one sidebar isn't enough, `navigation` is an object with one of five lists - `tabs`, `versions`, `languages`, `products` or `dropdowns`. Each item in the list has a sidebar of its own:

```json
{
  "navigation": {
    "tabs": [
      { "tab": "Guides", "icon": "book-open", "pages": ["index", "docs/quickstart"] },
      { "tab": "API reference", "icon": "code", "pages": ["api/overview"] },
      { "tab": "Blog", "href": "https://blog.example.com" }
    ]
  }
}
```

Each item has **one** of these, for what's inside it:

| Field | What the item holds |
| --- | --- |
| `pages` | A sidebar: pages, groups and links, as in [Navigation basics](https://preview.writedocs.io/docs/configuration/navigation-basics/). |
| `tabs`, `versions`, `languages`, `products`, `dropdowns` | Another level of navigation - see [Nesting](#nesting). |
| `href` | Nothing: the item is a link. A link to another site opens in a new tab. |

An item with two of them, like both `pages` and `versions`, is an error in `writedocs validate`.

Every item also accepts `page` - a page of its own, see [An item's own page](#an-items-own-page) - and `hidden` and `searchPublic` - see [Hidden sections](https://preview.writedocs.io/docs/configuration/hidden-sections/).

## Tabs

A row of tabs under the topbar - one per item.

**`tab`** `string` required

The tab's name.

**`icon`** `string`

Shown before the name. Any [icon](https://preview.writedocs.io/docs/content/components/icon/#icons).

When there are more tabs than fit the row, it scrolls sideways instead of wrapping: an arrow shows on each side that has more tabs, and the current tab is always in view. On a touch screen, swipe the row.

A tab with `dropdowns` instead of `pages` opens a menu of them:

```json
{
  "navigation": {
    "tabs": [
      { "tab": "Guides", "pages": ["index"] },
      {
        "tab": "SDKs",
        "icon": "package",
        "dropdowns": [
          { "dropdown": "JavaScript", "pages": ["sdks/js/install", "sdks/js/usage"] },
          { "dropdown": "Python", "pages": ["sdks/python/install", "sdks/python/usage"] }
        ]
      }
    ]
  }
}
```

### A second level in the menu

A dropdown in a tab's menu can hold `dropdowns` of its own. They open in a flyout beside its entry, with the entry's name as a heading:

```json
{
  "navigation": {
    "tabs": [
      { "tab": "Home", "pages": ["index"] },
      {
        "tab": "Developers",
        "dropdowns": [
          {
            "dropdown": "Resources",
            "icon": "book",
            "page": "dev/resources",
            "dropdowns": [
              { "dropdown": "Webhooks", "icon": "webhook", "pages": ["dev/webhooks/intro", "dev/webhooks/events"] },
              { "dropdown": "Testing", "icon": "flask-conical", "pages": ["dev/testing/intro"] },
              { "dropdown": "Changelog", "icon": "history", "href": "https://example.com/changelog" }
            ]
          },
          {
            "dropdown": "Platforms",
            "icon": "layers",
            "dropdowns": [
              { "dropdown": "Marketplaces", "pages": ["platforms/marketplaces/intro"] },
              { "dropdown": "White label", "pages": ["platforms/white-label/intro"] }
            ]
          },
          { "dropdown": "Authentication", "icon": "key-round", "pages": ["dev/auth"] }
        ]
      }
    ]
  }
}
```

- **Pointing at an entry** - or tapping its arrow - opens its flyout.
- **Clicking an entry** opens [its own page](#an-items-own-page) when it has one - like **Resources** above; its heading in the flyout links there too. An entry without a page - like **Platforms** - opens its flyout instead.
- **Choosing a dropdown in the flyout** opens its first page, with its sidebar. The tab, the entry and the dropdown are all highlighted.
- **Keyboard:** Down and Up move between the menu's entries, Right opens an entry's flyout, and Left or Escape go back to the entry.
- **Near the right end of the tab row**, the flyout opens to the left of the menu, so it stays in view.
- **On a phone**, the menu that opens from the topbar lists each level - the tab, the entry, the dropdown.

The menu goes two levels deep at most: a dropdown inside a flyout's dropdown is an error in `writedocs validate`. Use [products](#products) or groups for the next level. The flyout is only in a tab's menu - dropdowns inside dropdowns anywhere else are switchers next to the site name.

## Versions

A version switcher next to the site name.

**`version`** `string` required

The version's name, like `v2`.

**`label`** `string`

Shown in the switcher in place of `version`, like `v2 (latest)`.

**`tag`** `string`

A small label next to the name, like `Latest` or `Deprecated`.

**`default`** `boolean`

The version the site opens on. Without it, the first version is.

```json
{
  "navigation": {
    "versions": [
      { "version": "v2", "tag": "Latest", "default": true, "pages": ["v2/index", "v2/quickstart"] },
      { "version": "v1", "tag": "Deprecated", "pages": ["v1/index", "v1/quickstart"] }
    ]
  }
}
```

Switching versions keeps the reader on the same page in the other version - the page in the same place in its navigation - rather than sending them to its first page. Versions often live in different folders, so this goes by position, not by file name.

## Languages

A language switcher next to the site name.

**`language`** `string` required

The language's code, like `en` or `pt-br`. The pages under it are marked as that language, for browsers and screen readers.

**`label`** `string`

Shown in the switcher, like `English` or `Português`. Without it, the code is.

```json
{
  "navigation": {
    "languages": [
      { "language": "en", "label": "English", "pages": ["en/index", "en/quickstart"] },
      { "language": "pt-br", "label": "Português", "pages": ["pt-br/index", "pt-br/quickstart"] }
    ]
  }
}
```

Each language has its own pages, usually in a folder per language. Like versions, switching languages keeps the reader on the same page, by its place in the navigation. Every page under a language is in that language, so a language can't contain another `languages` list - `writedocs validate` rejects it. Put languages at one level, with tabs, versions and the rest inside each language.

## Products

A switcher for docs that cover several products.

**`product`** `string` required

The product's name.

**`icon`** `string`

Shown before the name. Any [icon](https://preview.writedocs.io/docs/content/components/icon/#icons).

**`description`** `string`

A short line under the name, in the switcher at the top of the sidebar.

```json
{
  "navigation": {
    "products": [
      { "product": "Payments", "icon": "credit-card", "pages": ["payments/index"] },
      { "product": "Billing", "icon": "receipt", "pages": ["billing/index"] },
      { "product": "Status page", "href": "https://status.example.com" }
    ]
  }
}
```

Where the switcher shows depends on where the products are:

- **At the top level**, it's next to the site name.
- **Inside a tab or a dropdown**, it's at the top of the sidebar, with each product's `icon` and `description`:

  ```json
  {
    "navigation": {
      "tabs": [
        { "tab": "Guides", "pages": ["guides/intro"] },
        {
          "tab": "Platform",
          "products": [
            { "product": "Payments", "icon": "credit-card", "description": "Accept cards and wallets", "pages": ["platform/payments/overview"] },
            { "product": "Billing", "icon": "receipt", "description": "Subscriptions and invoices", "pages": ["platform/billing/overview"] }
          ]
        }
      ]
    }
  }
  ```

  A page without a sidebar (`mode: frame`, `custom` or `blank`) doesn't show it - a hand-built page, like a product overview, links to the products itself. On a phone, the menu still lists them.

## Dropdowns

A switcher next to the site name, like versions - for sections that aren't versions, languages or products.

**`dropdown`** `string` required

The dropdown item's name.

**`icon`** `string`

Shown before the name. Any [icon](https://preview.writedocs.io/docs/content/components/icon/#icons).

```json
{
  "navigation": {
    "dropdowns": [
      { "dropdown": "Docs", "icon": "book-open", "pages": ["index", "docs/quickstart"] },
      { "dropdown": "API", "icon": "code", "pages": ["api/index"] }
    ]
  }
}
```

Inside a tab, dropdowns are that tab's menu instead - see [Tabs](#tabs).

## Nesting

Any of the five can go inside any other, as deep as your docs need. A tab with versions, each version with its own tabs:

```json
{
  "navigation": {
    "tabs": [
      { "tab": "Guides", "pages": ["index"] },
      {
        "tab": "API reference",
        "versions": [
          {
            "version": "v2",
            "tabs": [
              { "tab": "REST", "pages": ["api/v2/rest/overview"] },
              { "tab": "Webhooks", "pages": ["api/v2/webhooks/overview"] }
            ]
          },
          { "version": "v1", "pages": ["api/v1/overview"] }
        ]
      }
    ]
  }
}
```

Each branch goes as deep as it needs: a product with versions and tabs can sit next to a product that has just `pages`, like `v1` above.

Two limits:

- **Two levels of tabs.** Tabs inside tabs are a second row, under the first: the outer tabs on top, the tabs of the current one below - counting through anything in between, like the versions above. A third level is an error in `writedocs validate`; use dropdowns or groups for it.
- **One level of languages.** See [Languages](#languages).

On a phone, the tabs and switchers move into the menu that opens from the topbar, with the sidebar.

## An item's own page

Any tab, version, language, product or dropdown can have a `page` of its own - an overview of what's in it. Choosing the item opens that page, instead of the item's first page.

```json
{
  "navigation": {
    "tabs": [
      { "tab": "Home", "pages": ["index"] },
      {
        "tab": "Payments",
        "dropdowns": [
          {
            "dropdown": "Online payments",
            "icon": "globe",
            "page": "payments/online",
            "products": [
              { "product": "Checkout", "pages": ["payments/checkout/intro", "payments/checkout/setup"] },
              { "product": "Payments API", "pages": ["payments/api/intro"] }
            ]
          },
          {
            "dropdown": "In person",
            "icon": "store",
            "page": "payments/in-person/intro",
            "pages": ["payments/in-person/intro", "payments/in-person/terminals"]
          }
        ]
      },
      {
        "tab": "Guides",
        "page": "guides/overview",
        "pages": [{ "group": "Guides", "pages": ["guides/start", "guides/advanced"] }]
      }
    ]
  }
}
```

**`page`** `string`

A page, written like the ones in `pages`: `"payments/online"` is `payments/online.mdx`. Not on an item with `href` - that's a link, and `writedocs validate` rejects it. A page that doesn't exist is an error in `writedocs validate`.

Where the page opens depends on whether a sidebar lists it:

- **A sidebar lists it** - like **In person** above, whose page is the first in its own sidebar: it opens there, highlighted, like any page.
- **No sidebar lists it** - like **Online payments** and **Guides**: it opens inside the item. The item is the current one on its level, and below it:
  - **An item with `pages`** shows its sidebar, with nothing highlighted. The page's **Next** link is the sidebar's first page.
  - **An item holding products** shows the product switcher at the top of the sidebar with the item's name, and no product chosen. Choosing one opens that product's first page.
  - **An item holding tabs** shows them in a second row with none chosen; versions, languages and dropdowns show their switcher with the item's name. With nothing for a sidebar, the page has none, like [`mode: frame`](https://preview.writedocs.io/docs/content/page-modes/).

  On a phone, the menu lists the item's options right under it.

  Switching the version or language on such a page goes to the same item in the other one: its own page, or its first page when it has none. When the other version or language isn't organized the same way, it goes to its first page.

The page also counts where the navigation names it - before the item's own pages:

- When the first item has a page, the site's address `/` opens it (if the site has no `index.mdx`).
- A folder address leads to it when it's the first page under that folder - `/payments/` opens **Online payments**.
- `llms.txt` lists it first under the item's heading.

## Where a reader lands

The site's address, `/`, shows the home page (`index.mdx`). Without one, it sends the reader to the first page of the first item - or of the `default` version.

Clicking a tab, version, language, product or dropdown opens [its own page](#an-items-own-page), when it has one, or its first page. Opening the address of a folder with no page of its own - `/docs/payments/` - sends the reader to the first page under it. See [Redirects](https://preview.writedocs.io/docs/configuration/redirects/#folder-addresses).