Skip to Content
Fumadocs

Page Slugs & Page Tree

A shared convention for organizing your documents

This guide only applies for content sources that uses loader() API, such as Fumadocs MDX.

Overview

Fumadocs generates page slugs and page tree (sidebar items) from your content directory using loader(), the routing functionality will be handled by your React framework.

You can define folders and pages similar to file-system based routing.

index.mdx
getting-started.mdx

To customize its output further, you may use Loader Plugins.

File

For MDX & Markdown file, you can customize page information from frontmatter.

---
title: My Page
description: Best document ever
icon: House
---

## Learn More

Fumadocs detects from the following properties to construct page trees.

namedescription
titleThe title of page
descriptionThe description of page
iconThe name of icon, see Icons

Good to Know

Page information is supplied by the content source such as Fumadocs MDX.

On Fumadocs MDX, you can specify a schema option to customize frontmatter schema.

Slugs

The slugs of a page are generated from its file path.

path (relative to content folder)slugs
./dir/page.mdx['dir', 'page']
./dir/index.mdx['dir']

Folder

Organize multiple pages, you can create a Meta file to customize folders.

Folder Group

By default, putting a file into folder will change its slugs. You can wrap the folder name in parentheses to avoid impacting the slugs of child files.

path (relative to content folder)slugs
./(group-name)/page.mdx['page']

Root Folder

Marks the folder as a root folder, only items in the opened root folder will be visible.

meta.json
{
  "title": "Name of Folder",
  "description": "The description of root folder (optional)",
  "root": true
}

For example, when you are opening root folder framework, the other folders (e.g. headless) are not shown on the sidebar and other navigation elements.

index.mdx
current-page.mdx
other-pages.mdx
my-page.mdx

Fumadocs UI

Fumadocs UI renders root folders as Layout Tabs, which allows users to switch between them.

Root Type

root also accepts a string, the type of root folder: root folders of the same type under the same parent scope are interchangeable, such as versions of the same docs.

meta.json
index.mdx
guide.mdx
meta.json
index.mdx
guide.mdx
{
  "title": "1.0.0",
  "root": "version"
}

root: true is simply the default type, displayed as tabs.

Switching to another root folder of the same type maps a page to its structural projection, the page at the same path relative to the root folder:

PageProjection in v2
v1/guide.mdxv2/guide.mdx
v1/python/guide.mdxv2/python/guide.mdx, nested root folders are kept

Fumadocs UI

Fumadocs UI renders a dropdown for each root folder on the current page's path to switch between root folders of its type, see Versioning for a complete example.

Path Params

A folder or file named [name] is a dynamic segment. The meta file of a dynamic folder lists the values in staticParams, and Fumadocs generates a page for every value:

[framework]/meta.json
{
  "title": "Framework",
  "root": true,
  "staticParams": [{ "framework": "waku" }, { "framework": "astro" }]
}
path (relative to content folder)slugs
./[framework]/deploy.mdx['waku', 'deploy'], ['astro', 'deploy']

Each page is compiled once per param value. The content reads the params as props.framework and can branch on them with <show>. In loader code, the params are in page.params.

The meta file of [framework] applies to every generated folder (waku, astro). A [name] segment whose meta file has no staticParams stays a literal folder name.

Page Params

A page can also list staticParams in its frontmatter. When a page and its folder both list the same param name, the page is generated only for values that appear in both lists.

[framework]/fumadocs-mdx.mdx
---
title: Fumadocs MDX
staticParams:
  - framework: waku
---

The page only exists for waku, at /docs/waku/fumadocs-mdx.

Data in Code

Frontmatter and meta files written in YAML or JSON are the same for every param value. To set a different title or description for each value, like a title that names the framework, write them in code. Fumadocs MDX and local Markdown sources support it.

A meta file can be a module (meta.ts or meta.js). In a dynamic folder, the default export is a function that receives the params, and staticParams is a named export:

[framework]/meta.ts
const names = { waku: 'Waku', astro: 'Astro' };

export const staticParams = [{ framework: 'waku' }, { framework: 'astro' }];

export default ({ framework }: { framework: keyof typeof names }) => ({
  title: names[framework],
  root: true,
});

An MDX page can export frontmatter in code. The export is merged over the YAML frontmatter, and the page reads its params as props:

[framework]/deploy.mdx
---
title: Deploy
---

export const frontmatter = {
  description: props.framework === 'astro' ? 'Deploy with an adapter.' : 'Deploy your docs.',
};

staticParams stays in YAML frontmatter, because the loader reads it before the export runs.

Static Paths

A file at a literal path overrides the generated page for that value. astro/deploy.mdx overrides the astro page of [framework]/deploy.mdx, and astro/meta.json overrides the meta file of the astro folder.

With i18n, files of a locale take priority over those of its fallback locale: astro/deploy.cn.mdx, then [framework]/deploy.cn.mdx, then astro/deploy.mdx.

A localized page, like deploy.cn.mdx, reads staticParams from meta.cn.json before meta.json. With the dir parser, each language folder lists its own staticParams.

Meta

Customize folders by creating a meta.json file in the folder.

meta.json
{
  "title": "Display Name",
  "icon": "MyIcon",
  "pages": ["index", "getting-started"],
  "defaultOpen": true
}
namedescription
titleDisplay name
iconThe name of icon, see Icons
defaultOpenOpen the folder by default
collapsibleCollapsible folder content (default: true)
pagesFolder items (see below)
pagesIndexThe index item (see below)

Pages

Folder items are sorted alphabetically by default, you can add or control the order of items using pages.

meta.json
{
  "pages": ["index", "getting-started"]
}

When specified, items are not included unless they are listed in pages.

TypeSyntaxDescription
Path./path/to/pagea path to page or folder.
Separator---Label---
---[Icon]Label---
a separator between two sections (icon supported).
Link[Text](url)
[Icon][Text](url)
external:[Text](url)
insert links (icon supported)
add a external: prefix to mark links as external.
Rest...include remaining pages (sorted alphabetically).
Reversed Restz...areversed Rest item.
Extract...folderextract the items from a folder.
Except!itemExclude an item from ... or z...a.
meta.json
{
  "pages": [
    "components",
    "---My Separator---",
    "...folder",
    "...",
    "!file",
    "!otherFolder",
    "[Vercel](https://vercel.com)",
    "[Triangle][Vercel](https://vercel.com)"
  ]
}

No Duplicated URL

The same page URL must not appear more than once in the entire page tree. Duplicated page items are not allowed for the same reason.

This is intentional, such that Fumadocs can locate the active tree item purely based on current pathname.

Folder Index

When folder owns a index item, it becomes clickable and jumps to the index item when clicked.

By default, it is the index file under each folder. You can specify the index item of a folder, it accepts Path and Link.

{
  // assume there's a "overview.mdx" file under the folder
  "pagesIndex": "overview"
}

Icons

Since Fumadocs doesn't include an icon library, you have to convert the icon names to JSX elements in runtime, and render it as a component.

You can add an icon handler to loader().

i18n Routing

You can define different style for i18n routing.

lib/i18n.ts
import type { I18nConfig } from 'fumadocs-core/i18n';

export const i18n: I18nConfig = {
  // default
  parser: 'dot',
  // or
  parser: 'dir',
};

Add Markdown/meta files for different languages by attending .{locale} to your file name, like:

meta.json
meta.cn.json
get-started.mdx
get-started.cn.mdx

For the default locale, the locale code is optional.

How is this guide?

Last updated on