文档、博客与法律内容

使用 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.tsbaseUrl: "/docs" 加载集合,并声明 enzh 两种语言。catch-all 页面 通过以下代码解析内容:

const page = source.getPage(params.slug, params.locale);

添加双语页面

若页面名为 guides/launch,请同时创建:

content/docs/guides/launch.mdx
content/docs/guides/launch.zh.mdx
content/docs/guides/launch.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 传给编译后的正文,因此 CalloutCardsCard 等默认元素可以直接使用。

若要加入非默认组件,请在共享组件映射中导出它,并把同一映射传给所有需要支持它 的渲染器(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
---

titledate 必填;descriptionauthorimage 可选,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
---

titledate 必填,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 等导入。

若集合导入或生成类型缺失:

  1. 对照 source.config.ts 的 schema 检查 MDX frontmatter。
  2. 检查 meta.json JSON,并确认其中每个页面/文件夹都存在。
  3. 停止开发服务器,删除生成的 .source/,再运行 pnpm devpnpm build
  4. 运行 pnpm build,捕获无效内容和路由渲染错误。

不要手动编辑或提交 .source/;应修复源 MDX 或配置。

相关页面

On this page