---
title: Write
description: Write clear, scannable MDX pages with structure, links, and media, then verify in preview.
---

**Before you begin**

- A [docs.page](https://docs.page) project with `docs.json` at the repository root and page files under `docs/`
- Basic [Markdown familiarity](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax): headings, lists, links, and fenced code blocks

---

## Write a new page

Each page is a `.mdx` or `.md` file under `docs/`. Work through these steps in order:

1. **Choose a URL path:** add `docs/{path}.mdx` (or `.md`). The path without the extension becomes the URL.
2. **Declare title and description:** set `title` and `description` in YAML frontmatter at the top of the file. See [Frontmatter](#frontmatter).
3. **Make the page scannable:** structure the body with `##` headings and short paragraphs. See [Page structure and prose](#page-structure-and-prose).
4. **Help readers follow along:** add root-relative links, fenced code blocks, and images where they clarify the task. See [Links and assets](#links-and-assets).
5. **Expose the page to readers:** add it to the sidebar in [Organize](/authoring/organize), then confirm in [Preview](/authoring/preview).

## Page structure and prose

Structure the body with `##` headings. The **On this page** [table of contents](/features/table-of-contents) derives from Markdown heading levels, keep one main idea per section and nest subsections one level deeper. Set `content.headerDepth` in `docs.json` when you need deeper entries in that list.

Write so a busy reader can skim: state the outcome first, keep paragraphs short, use imperative voice (**Run**, **Set**, **Open**), and bold UI labels while putting commands and paths in `backticks`.

Match page shape to what the reader needs:

| Reader goal | Page shape | Link out for |
| --- | --- | --- |
| Learn by doing | Step-by-step walkthrough | Field lookup, API tables |
| Complete one task | Focused how-to with a verify step | Architecture essays |
| Look up a value | Reference tables or property rows | Tutorial narrative |
| Understand why | Explanation with a mental model | Numbered setup steps |

Stay in one mode per page. Link to Reference and Components instead of mixing exhaustive lists into prose.

### Frontmatter

Start each page with YAML frontmatter between `---` delimiters:

```yaml
---
title: Install the CLI
description: Install the docs.page CLI on macOS, Linux, or Windows.
---
```

At minimum, set `title` and `description`. Additional keys control redirects, previous/next links, hero images, and indexing, see [Page frontmatter](/reference/page-frontmatter).

### Where pages live

Store every page under `docs/`. The file path (without the extension) becomes the URL path:

| File | URL |
| --- | --- |
| `docs/index.mdx` | `/` |
| `docs/getting-started.mdx` | `/getting-started` |
| `docs/api/authentication.mdx` | `/api/authentication` |

Create a new file when you add a topic. Rename the file and add a [redirect](/authoring/redirects) when you move a published URL.

## Links and assets

**Internal links:** use root-relative paths with no domain and no `.mdx` extension:

```mdx
See [Preview](/authoring/preview) before you open a pull request.
```

**Code examples:** wrap snippets in fenced blocks with a language tag (`bash`, `json`, `tsx`). For multiple equivalent snippets, use a [code group](/components/code-group) or [tabs](/components/tabs). See [Code blocks](/components/code-blocks) for titles and diff markers.

**Images:** commit under `docs/` and reference with a leading slash (`/assets/dashboard.png`). Use [`<Image>`](/components/image) when you need captions, light/dark variants, zoom behavior, or sizing, see `content.zoomImages` in [docs.json](/reference/docs-json).

**Video and embeds:** [`<YouTube>`](/components/youtube), [`<Vimeo>`](/components/vimeo), [`<Video>`](/components/video) (public `https` URL only), or [`<Tweet>`](/components/tweet).

## When to use components

Plain Markdown covers most writing. docs.page also ships **built-in MDX components** with no imports and no extra packages.

| Reader need | Start with |
| --- | --- |
| Body copy and lists | Plain Markdown |
| One highlighted snippet | Fenced code block |
| Platform or language variants | [`<Tabs>`](/components/tabs) or [`<CodeGroup>`](/components/code-group) |
| Prerequisites, cautions, tips | [`<Info>`](/components/callouts), [`<Warning>`](/components/callouts), or siblings |
| Collapsible sections | [`<Accordion>`](/components/accordion) and [`<AccordionGroup>`](/components/accordion) |
| Numbered setup flow | [`<Steps>`](/components/steps) |
| Custom heading anchors | Markdown `##` headings (recommended) or [`<Heading>`](/components/heading) |
| Inline icons | [`<Icon>`](/components/icon) |
| API or config field rows | [`<Property>`](/components/property) on Reference pages |
| Section landing links | [`<Card>`](/components/card) and [`<CardGroup>`](/components/card) |

Author components with PascalCase JSX tags. Unknown names show an inline error in preview, match the tag to the [Components](/components) reference. For props and examples, use the Components tab; for how the library fits the product, see [Features → Components](/features/components).

After you edit, use [Preview](/authoring/preview) to confirm layout, run `docs check` for broken links, then continue to [Publish](/authoring/publish).

## Troubleshooting

| Symptom | Likely cause | Fix |
| --- | --- | --- |
| Page returns 404 in preview | File is outside `docs/` or the path does not match the URL you opened | Keep pages under `docs/` and match the file path to the URL (no extension) |
| Internal link goes nowhere | Link includes a domain, file extension, or wrong path | Use root-relative paths like `/authoring/preview`. No `https://` and no `.mdx`. |
| Image does not render | Asset path is wrong or the file is not committed | Store images under `docs/` and reference them with a leading slash, e.g. `/assets/screenshot.png` |
| Inline component error in preview | Misspelled or unsupported component name | Match the tag to the [Components](/components) reference. Names are PascalCase. |
| `{{ variable }}` shows literally | Substitution used in frontmatter or the path is undefined | Use variables in the MDX body only; define values in `docs.json`. See [Global variables](/features/global-variables) or [docs.json: variables](/reference/docs-json#variables). |

## Related

<CardGroup cols={2}>
  <Card title="Organize" icon="sitemap" href="/authoring/organize">
    Add the page to sidebar groups, tabs, and navigation order in `docs.json`.
  </Card>
  <Card title="Preview" icon="eye" href="/authoring/preview">
    Iterate locally with live reload while you edit.
  </Card>
  <Card title="Components overview" icon="cubes" href="/components">
    Look up every built-in component, prop, and example.
  </Card>
  <Card title="Components feature" icon="puzzle-piece" href="/features/components">
    How global MDX components work in preview and production.
  </Card>
  <Card title="Global variables" icon="code" href="/features/global-variables">
    Reuse version numbers and URLs across pages from `docs.json`.
  </Card>
  <Card title="Table of contents" icon="list" href="/features/table-of-contents">
    How the on-page heading list is built and how `content.headerDepth` works.
  </Card>
  <Card title="Page frontmatter" icon="file-lines" href="/reference/page-frontmatter">
    Field reference for `title`, `description`, redirects, and more.
  </Card>
</CardGroup>
