---
title: Pages
description: How the files in your content folder become pages, and how to organize and name them so routing and navigation are inferred automatically.
---

Your docs are just a folder of Markdown and MDX files. Blume turns each file into a page — routing, navigation, and metadata are inferred from the file system, so there's no manifest to keep in sync.

Content lives under your **content root** (`docs/` by default; change it with `content.root` in [`blume.config.ts`](/docs/configuration)).

## Markdown and MDX

Blume renders two kinds of file:

- **`.md`** — Markdown for plain prose: GFM, frontmatter, smart punctuation, and super/subscript.
- **`.mdx`** — everything `.md` has, plus [components](/docs/content/components) and the MDX-only [directives, package installs, and math](/docs/content/syntax).

Reach for `.md` when a page is just prose, and `.mdx` when it needs components or directives. Switching is as simple as renaming the file.

## Files and routes

Each file maps to a route by its path under the content root:

| File                      | Route             |
| ------------------------- | ----------------- |
| `docs/index.mdx`          | `/`               |
| `docs/quickstart.mdx`     | `/quickstart`     |
| `docs/guides/theming.mdx` | `/guides/theming` |
| `docs/guides/index.mdx`   | `/guides`         |

Nested folders become nested routes, and an `index.mdx` inside a folder becomes that folder's own page.

## Ordering with numeric prefixes

Prefix a file or folder with a number to control its order in the sidebar. The prefix is stripped from the URL, so you can reorder pages without breaking links:

```txt
01-introduction.mdx  ->  /introduction
02-installation.mdx  ->  /installation
```

Ordering has several layers — see [Navigation](/docs/content/navigation) for the full precedence rules.

## Group folders

Wrap a folder name in parentheses to group its pages in the sidebar **without** adding a URL segment:

```txt
docs/(internal)/security.mdx  ->  /security
```

The pages share an “Internal” sidebar group but keep flat, parenthesis-free URLs.

## Drafts

Mark a page as a draft to keep it out of production builds while still previewing it in `blume dev`:

```yaml lineNumbers
---
title: Work in progress
draft: true
---
```

`blume build` skips drafts; `blume dev` renders them so you can work in the open.

## Content types

Every page has a **type**, set with the `type` frontmatter field (default `doc`). Types let Blume treat groups of pages differently — most importantly, `blog` and `changelog` pages are collected into [feeds](#feeds).

```yaml lineNumbers
---
title: v1.2.0
type: changelog
date: 2026-06-20
changelog:
  version: 1.2.0
  category: Features
---
```

The type is independent of where the file lives, but by convention blog posts go under `blog/` and changelog entries under `changelog/`. Both get an RSS feed automatically, and changelog entries are also collected into a generated [`/changelog` timeline](/docs/advanced/changelog). See [Blog](/docs/advanced/blog) and [Changelog](/docs/advanced/changelog) for authoring each.

## Feeds

Blume generates an RSS feed automatically for each content type listed in [`rss.types`](/docs/configuration/seo#rss-feeds) — `blog` and `changelog` by default — as long as it has at least one page. Feeds are served at `/<type>/rss.xml`:

| Type        | Feed                 |
| ----------- | -------------------- |
| `blog`      | `/blog/rss.xml`      |
| `changelog` | `/changelog/rss.xml` |

Give each entry a `date` so items sort newest-first and carry a `pubDate`. An unquoted YAML date is fine — Blume normalizes it:

```yaml lineNumbers
---
title: Introducing Blume
type: blog
date: 2026-06-22
description: Why we built a markdown-first docs framework.
---
```

Feeds need an absolute site URL, so set [`deployment.site`](/docs/deployment). Blume adds `<link rel="alternate">` tags to every page so browsers and feed readers discover them automatically. See [Blog](/docs/advanced/blog) and [Changelog](/docs/advanced/changelog) for authoring each content type.

## On this page

Every page gets an automatic table of contents, built from its headings. On wide screens it sits in a sticky sidebar beside your content; on narrower screens it collapses into an **On this page** panel above the page. As you scroll, the entry for the section you're reading is highlighted, so you always know where you are in a long page.

Blume slugifies each heading into an anchor, so every entry links straight to its section — and you can deep-link to any heading by appending its slug to the URL (`.../my-page#getting-started`).

The contents list your `##` and `###` headings (H2 and H3). A page with no headings at that level simply has no table of contents.

## Where to next

<CardGroup cols={2}>
  <Card title="Frontmatter" href="/docs/reference/frontmatter" icon="file">
    Page metadata: title, description, sidebar, SEO, and search.
  </Card>
  <Card title="Syntax" href="/docs/content/syntax" icon="book-open">
    Every Markdown and MDX feature you can write.
  </Card>
  <Card title="Components" href="/docs/content/components" icon="folder">
    The JSX components available in any MDX page.
  </Card>
  <Card title="Navigation" href="/docs/content/navigation" icon="menu">
    Shape the sidebar, ordering, and tabs.
  </Card>
  <Card title="Folder meta" href="/docs/content/meta" icon="panel-left">
    Configure a sidebar group with a `meta.ts` file.
  </Card>
</CardGroup>
