文档、博客与法律内容
使用 Fumadocs MDX 编写文档、博客文章和法律页面。
模板把文档、博客与法律页面保存在可版本管理的 MDX 文件中。Fumadocs 将它们 编译为 App Router 页面使用的类型化集合,无需 CMS 或内容数据库。
重要文件
| 路径 | 用途 |
|---|---|
source.config.ts | 定义 docs、blog、legal 集合及 schema |
src/lib/source.ts | 在 /docs 加载本地化文档树 |
src/lib/blog.ts | 排序、筛选、分页和查找博客/法律内容 |
mdx-components.tsx | 全局默认 Fumadocs MDX 组件映射 |
content/docs/ | 文档树与 meta.json 导航 |
content/blog/ | 博客集合 |
content/legal/ | 法律页面集合 |
.source/ | 生成的集合模块与类型(已 gitignore) |
文档
defineDocs({ dir: "content/docs" }) 注册文档集合。src/lib/source.ts
以 baseUrl: "/docs" 加载集合,并声明 en、zh 两种语言。catch-all 页面
通过以下代码解析内容:
const page = source.getPage(params.slug, params.locale);添加双语页面
若页面名为 guides/launch,请同时创建:
content/docs/guides/launch.mdx
content/docs/guides/launch.zh.mdx---
title: Launch
description: Prepare your product for release.
---
## Checklist
Your English content.两种语言使用相同 slug;无后缀文件为英文,.zh.mdx 为中文。这种双语命名只
应用于 docs 集合。当前 blog 与 legal 集合没有配置本地化,因此同一份内容会显示
在两种 locale 的路由外壳中。
使用 meta.json 控制导航
根目录 content/docs/meta.json 排列顶层分区与文件夹;嵌套 meta.json 排列
文件夹内页面。可用 "---Essentials---" 这类标签创建分隔项:
{
"title": "Guides",
"pages": ["index", "launch", "---Advanced---", "operations"]
}模板当前只有一个文档根。Fumadocs 可通过在另一个顶层文档文件夹的 meta.json
加入 "root": true 表示额外根目录,但要提供完整的根目录切换体验,还需相应
定制 docs layout。页面(以及需要的翻译)存在之前,不要把根目录或 slug 加入导航。
MDX 组件
mdx-components.tsx 返回 Fumadocs 默认组件映射;文档、博客与法律渲染器也会
把 defaultMdxComponents 传给编译后的正文,因此 Callout、Cards、Card
等默认元素可以直接使用。
若要加入非默认组件,请在共享组件映射中导出它,并把同一映射传给所有需要支持它 的渲染器(docs、blog 和/或 legal)。只改一个渲染器,会导致内容在某个页面可用、 换到另一个页面却失败。
博客
博客 frontmatter 由 blog schema 校验:
---
title: Shipping the First Version
description: What we learned while launching.
date: 2026-06-23
author: Leo
tags: [Product, Launch]
image: /images/blog/launch.jpg
---title、date 必填;description、author、image 可选,tags 默认为
空数组。
src/lib/blog.ts 实现以下行为:
- 文章按
date从新到旧排序。 getBlogPostsByTag(tag, page)按精确标签筛选,每页 6 篇。getAllTags()统计标签,默认返回使用最多的 10 个。/blog?tag=Product&page=2驱动筛选与分页。/blog/[slug]按文件路径查找文章,渲染正文与 TOC,并生成静态参数和 metadata。
移除 .mdx 后的文件路径就是 slug,请避免路径重复。
法律页面
法律内容 frontmatter 如下:
---
title: Privacy Policy
description: How we handle personal data.
date: 2026-06-23
published: true
---title、date 必填,description 可选,published 默认为 true。页面通过
/legal/[slug] 渲染。
当前代码会解析 published,但不会执行过滤。getLegalPages() 返回完整集合,
getLegalPage() 也能找到 published: false 的条目,所以该字段并不能隐藏页面。
若要把它用作发布开关,需要同时过滤列表/静态参数与单页查询:
export function getLegalPages() {
return legal.filter((page) => page.published);
}
export function getLegalPage(slug: string) {
return getLegalPages().find((page) => getLegalSlug(page) === slug);
}生成的 .source 目录
Fumadocs 会在开发/构建时生成 .source/。该目录已被 gitignore,并在
tsconfig.json 中映射给 fumadocs-mdx:collections/server 等导入。
若集合导入或生成类型缺失:
- 对照
source.config.ts的 schema 检查 MDX frontmatter。 - 检查
meta.jsonJSON,并确认其中每个页面/文件夹都存在。 - 停止开发服务器,删除生成的
.source/,再运行pnpm dev或pnpm build。 - 运行
pnpm build,捕获无效内容和路由渲染错误。
不要手动编辑或提交 .source/;应修复源 MDX 或配置。
