# Frontmatter

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

The fields at the top of a page - its title and description, address, layout, whether it's a draft, how it shows in the sidebar, and its meta tags.

A page starts with frontmatter: YAML between two `---` lines, describing the page.

```mdx
---
title: Webhooks
description: Get an HTTP request when something changes in your account.
sidebarTitle: Webhooks
icon: webhook
tag: New
---

Webhooks send ...
```

| Field | Type | What it does |
| --- | --- | --- |
| [`title`](#title) | string | The page's heading and name |
| [`description`](#description) | string | A summary, for search engines and AI tools |
| [`slug`](#slug) | string | A different address |
| [`mode`](#mode) | string | The page's layout |
| [`draft`](#draft) | boolean | Keep the page off the published site |
| [`sidebarTitle`](#sidebartitle) | string | A shorter name in the sidebar |
| [`icon`](#icon) | string | An icon in the sidebar |
| [`tag`](#tag) | string | A label in the sidebar |
| [`deprecated`](#deprecated) | boolean | A **Deprecated** label |
| [`hidden`](#hidden) | boolean | Leave the page out of the sidebar |
| [`url`](#url) | string | Make the page a link to another site |
| [`hideFooterPagination`](#hidefooterpagination) | boolean | No previous and next links |
| [`openapi`](#openapi) | string | An API endpoint for the page |
| [`hideApiMarker`](#hideapimarker) | boolean | No method label in the sidebar |
| [`seo`](#seo) | object | Meta tags for search engines and social media |

Every field is optional. A page in the navigation doesn't need frontmatter at all; one outside it needs at least the `---` lines to be a page - see [Project structure](https://docs.writedocs.io/docs/project-structure/#pages).

## The page

### `title`

The page's main heading, its name in the sidebar and in previous/next links, and the browser tab's title. Without it, the title comes from the file name: `getting-started.mdx` is "Getting started", and an `index.mdx` takes its folder's name.

Don't repeat the title as a `#` heading in the page - it's already shown.

### `description`

A one-sentence summary of the page. It's the page's `<meta name="description">` - what search engines show under the link, and the text of link previews. It's also the page's summary in `llms.txt`, and in the MCP server's page list. Without it, the page uses the site's `description` from `writedocs.json`.

### `slug`

A different address for the page, without moving the file:

```mdx
---
title: Authentication
slug: guides/auth
---
```

`docs/security/authentication.mdx` with this slug is served at `/guides/auth/`. The navigation still lists it by its file: `docs/security/authentication`. Slashes at either end don't matter - `guides/auth` and `/guides/auth/` are the same - and `slug: /` makes the page the home page.

When you change a published page's address, add a [redirect](https://docs.writedocs.io/docs/configuration/redirects/) from the old one.

### `mode`

The page's layout - how much of the site's frame (topbar, sidebar, table of contents) is around it: `default`, `wide`, `frame`, `custom` or `blank`. See [Page modes](https://docs.writedocs.io/docs/content/page-modes/).

### `draft`

`draft: true` keeps the page off the published site while you write it:

```mdx
---
title: Webhooks
draft: true
---
```

The published site doesn't have the page at all: it has no address, and it isn't in the navigation, the site's search, `sitemap.xml`, `llms.txt`, `llms-full.txt` or the MCP server, or anyone's previous/next links. Take `draft: true` out (or set `draft: false`) and the page is published as usual.

`writedocs dev` shows drafts, so you can see how they look: at the top of the page a **Draft: not published** strip, and a **Draft** label next to its name in the sidebar. Turning `draft` on or off while `writedocs dev` runs updates the page without a restart.

What else changes while a page is a draft:

- **The navigation.** Its entry in `writedocs.json`'s navigation is left out, and so is a group or tab whose pages are all drafts - you don't have to edit the navigation. A group whose own `page` is a draft keeps its other pages.
- **Links to it** lead nowhere on the published site. [`writedocs broken-links`](https://docs.writedocs.io/docs/cli/#writedocs-broken-links) lists them, saying the page is a draft.
- **A [redirect](https://docs.writedocs.io/docs/configuration/redirects/) to it** stays, and shows "not found" until the page is published.
- **A draft home page** (`index.mdx`): the site's address opens the navigation's first page instead, as on a site with no home page.
- **Its folder's address.** When a folder's own page (`guides/index.mdx`) is a draft, `/guides/` opens the folder's first page instead, as for any folder with no page of its own.

The build lists each of these - every navigation entry, group and tab it left out, every redirect to a draft and a draft home page - as warnings, and says how many drafts it left out.

`draft` has to be `true` or `false`: `draft: yes` and `draft: "true"` are errors in [`writedocs validate`](https://docs.writedocs.io/docs/cli/#writedocs-validate). [`writedocs validate`](https://docs.writedocs.io/docs/cli/#writedocs-validate) checks drafts like any other page, so they're ready when you publish them. Only pages have frontmatter: snippets and other files can't be drafts, and neither can the API pages generated from an OpenAPI spec.

#### `draft` or `hidden`

| | Hidden page | Draft |
| --- | --- | --- |
| Published at its address | Yes | No |
| In the sidebar and previous/next links | No | No |
| In the site's search | Yes | No |
| In search engines, `sitemap.xml`, `llms.txt`, the MCP server | No | No |
| Links to it | Work | Broken |
| In `writedocs dev` | Like on the site | Shown, marked as a draft |

Use `hidden` for a page that's finished but shouldn't be in the menus - one you link to from somewhere else. Use `draft` for a page that isn't ready. With both, `draft` wins.

## How the page appears in the sidebar

### `sidebarTitle`

A shorter name for the sidebar and menus, when the title is long:

```mdx
---
title: Authenticating requests with OAuth 2.0
sidebarTitle: OAuth 2.0
---
```

The page's heading and previous/next links still use `title`.

### `icon`

An icon before the page's name in the sidebar: an icon name, an emoji, or an image - see [Icons](https://docs.writedocs.io/docs/content/components/icon/#icons).

### `tag`

A small label after the page's name in the sidebar, like `New` or `Beta`.

### `deprecated`

`deprecated: true` shows a **Deprecated** label next to the page's title, and in the sidebar.

### `hidden`

`hidden: true` leaves the page out of the sidebar, menus and previous/next links, even when the navigation lists it. The page is still published at its address, and links to it work.

A hidden page is also `noindex` - out of search engines, `sitemap.xml` and `llms.txt` - unless it sets `seo.noindex: false`. To hide a whole tab, version or product, see [Hidden sections](https://docs.writedocs.io/docs/configuration/hidden-sections/).

### `url`

Makes the page a link to another site:

```mdx
---
title: Status page
url: https://status.example.com
---
```

Its sidebar entry opens `url` in a new tab, and its own address redirects there. The page's content isn't shown anywhere, and the page is left out of `sitemap.xml`, `llms.txt` and previous/next links.

### `hideFooterPagination`

`hideFooterPagination: true` removes the **Previous** and **Next** links at the bottom of the page.

## API pages

### `openapi`

Makes the page an API reference page for one endpoint: your text, then the endpoint's parameters, responses and **Try it** playground, from the spec.

```mdx
---
title: Create a refund
openapi: POST /refunds
---
```

See [Your own page for an endpoint](https://docs.writedocs.io/docs/openapi/multi-spec-and-overrides/#your-own-page-for-an-endpoint).

### `hideApiMarker`

On an API page, `hideApiMarker: true` removes the method label (`GET`, `POST`, ...) from its sidebar entry.

## `seo`

Meta tags for this page. Each field replaces the site's default from `writedocs.json`'s [`seo`](https://docs.writedocs.io/docs/configuration/seo-and-sitemap/#seo); the rest still apply.

```mdx
---
title: Enterprise SSO
seo:
  ogImage: /images/social/sso.png
  ogType: article
  twitterCard: summary_large_image
  keywords:
    - sso
    - saml
  noindex: false
  title: "Single sign-on (SSO) with SAML - Acme"
  description: Connect Acme to Okta, Entra ID or any SAML identity provider.
  canonical: /docs/security/sso/
  metatags:
    "og:locale": en_GB
---
```

**`title`** `string`

The page's `<title>` - what the browser tab and search results show - and the title in link previews. Used exactly as written; the site's name isn't added. The heading on the page and the sidebar keep the page's `title`.

**`description`** `string`

The description search engines and link previews get, when it should differ from the page's `description`.

**`canonical`** `string`

The page's canonical URL, when it isn't its own address: a path on the site, or a full URL. See [Canonical URLs](https://docs.writedocs.io/docs/configuration/seo-and-sitemap/#canonical-urls).

**`ogImage`** `string`

The image in link previews: a path in your project, or a URL. Without it, the site's `seo.ogImage` - or a picture [generated for the page](https://docs.writedocs.io/docs/configuration/seo-and-sitemap/#link-preview-images).

**`ogType`** `string`

The page's `og:type`.

**`twitterCard`** `"summary" | "summary_large_image"`

The kind of preview on X (Twitter).

**`keywords`** `string[]`

The page's `<meta name="keywords">`.

**`noindex`** `boolean`

`true` keeps the page out of search engines, `sitemap.xml`, `llms.txt`, `llms-full.txt` and the MCP server. The page is still published and in the site's search.

**`robots`** `string`

The whole `<meta name="robots">` value, like `"noindex, follow"`. Replaces `noindex`. See [Leaving pages out of search engines](https://docs.writedocs.io/docs/configuration/seo-and-sitemap/#leaving-pages-out-of-search-engines).

**`metatags`** `object`

Other meta tags for this page, as name and content. They're added to the site's; one with the same name replaces it. See [Other meta tags](https://docs.writedocs.io/docs/configuration/seo-and-sitemap/#other-meta-tags).

**`jsonLd`** `object | object[]`

Structured data of your own for this page - a schema.org block, or a list of them. See [Structured data](https://docs.writedocs.io/docs/configuration/seo-and-sitemap/#a-pages-own).

## Mistakes

A field with the wrong type, or a `mode` that doesn't exist, is an error in [`writedocs validate`](https://docs.writedocs.io/docs/cli/#writedocs-validate), with the file and line. Frontmatter that isn't valid YAML is too - a common cause is a value with a colon in it, which needs quotes: `title: "Step 2: Configure"`.