Tinycast 文档网站实现:Next.js 与 Fumadocs 加 llms.md 的完整做法
2026/9/20 11:51:42 网站建设 项目流程

Tinycast 文档网站实现:Next.js 与 Fumadocs 加 llms.md 的完整做法

【免费下载链接】tinycastTinycast — a tiny, fully native macOS launcher, hotkeys, and clipboard history.项目地址: https://gitcode.com/GitHub_Trending/ti/tinycast

Tinycast 是一款小型、全原生的 macOS 启动器(Launcher)、热键与剪贴板历史工具,而它的文档网站是一个值得参考的工程范例:用Next.js 16 + Fumadocs构建静态文档站,并通过llms.txtllms.md路由让 AI 助手能直接"读懂"每一篇文档,最终零服务器部署到 Cloudflare。本文完整拆解这套文档站的做法,适合想给自己的项目搭建 AI 友好文档站的新手。

技术栈总览:Next.js + Fumadocs 的最小组合

整个网站位于 website/ 目录,核心依赖在 website/package.json 中一目了然:

依赖作用
nextApp Router 框架,负责页面、路由与静态导出
fumadocs-core/fumadocs-ui文档数据源模型与现成的文档 UI(侧边栏、目录、搜索)
fumadocs-mdxMDX 编译器,把content/docs目录变成可查询的页面树
tailwindcssv4样式系统
wranglerCloudflare Pages 部署工具

可以看到没有任何 CMS、数据库或数据库驱动的路由——全部内容都是 Markdown 文件,构建时一次性生成 HTML。

文档内容组织:fumadocs-mdx 的三件套

第一步:定义文档目录。website/source.config.ts 只做两件事:

  • defineDocs({ dir: "content/docs" })声明 Markdown 文档的存放目录;
  • 通过defineConfig注入rehypePlugins与代码高亮配置。

这里有两个很实用的细节:

  1. rehype-raw的坑:Fumadocs 会向 AST 注入 MDX 节点,rehype-raw默认拒绝处理它们,必须显式传入passThrough: MDX_NODES白名单,否则快捷键表里的<kbd>标签会被静默吞掉;
  2. 按需引入高亮语法rehypeCodeOptions.langs只声明了["bash", "json", "markdown"],避免把用不到的语法包打进构建产物,且高亮在构建期完成、浏览器端零成本。

第二步:管理页面顺序。website/content/docs/meta.json 用数组顺序声明侧边栏导航:index → install → permissions → palette → launcher → features → ai → extensions → reference

第三步:生成数据源。website/src/lib/source.ts 用loader({ baseUrl: "/docs", source: docs.toFumadocsSource() })把文档目录变成运行时可查询的source对象,侧边栏、sitemap、llms.txt 全部复用它。

llms.md 实现:把原始 Markdown 喂给 AI

这是本仓库最有意思的部分——网站为 AI Agent 提供了两层"机器可读接口":

1.llms.txt:全站文档索引

website/src/app/llms.txt/route.ts 在构建时遍历source.getPages(),把 37 个页面按章节(Launcher、Features、AI、Reference……)分组,生成一份text/plain索引:每一行是"页面标题 + 链接 + 一句话描述",AI 只需一次请求就能了解整站结构。

2.llms.md/docs/[slug]/index.md:单页原始 Markdown

website/src/app/llms.md/docs/[...slug]/route.ts 为每个页面输出一份纯 Markdown 文件(Content-Type: text/markdown),配合 website/src/lib/get-llm-text.ts 剥掉 frontmatter、补上标题与描述,得到 AI 可直接消费的正文。

一个巧妙的工程决策在 website/src/lib/source.ts 的注释里:静态导出中"既是文件又是目录"的路径会冲突(例如/docs/launcher既要当文件夹又要当页面),所以给所有页面的 Markdown 统一命名为叶子文件index.md,从根本上消灭这类冲突。generateStaticParams()则在导出时为每个页面预生成对应的.md文件——线上没有任何运行时请求。

这套机制同时服务于人类的"Copy Markdown"按钮,一份代码、两种读者。

静态导出与部署:无 Node 进程的文档站

website/next.config.mjs 是理解部署形态的关键:

  • output: "export":纯静态导出,Cloudflare 直接托管文件,背后没有 Node 进程;
  • images: { unoptimized: true }:图片优化 API 需要服务端,导出场景下必须关闭;
  • trailingSlash: true:生成/docs/palette/index.html,这是静态主机唯一能正确服务的形态;
  • reactCompiler: true:启用 React Compiler 自动记忆化。

部署只需一条命令:pnpm deploy(即wrangler deploy),配置见 website/wrangler.jsonc;截图类媒体由 Scripts/upload-website-media.sh 单独上传。

SEO 细节:元数据、sitemap 与结构化数据

website/src/app/layout.tsx 集中处理了分享与搜索引擎元数据:

  • 标题模板"%s — Tinycast",所有子页自动带上品牌后缀;
  • Open Graph / Twitter Card:统一使用 1200×630 的og.png分享卡片;
  • 结构化数据:内嵌schema.org/SoftwareApplication的 JSON-LD,声明应用类别、操作系统与免费许可;
  • 自托管字体next/font在构建时下载 Geist 与 Instrument Serif 并生成度量匹配的 fallback,无第三方请求、无布局偏移(layout shift)。

而 website/src/app/sitemap.ts 直接从文档树生成——新增一篇文档,sitemap 自动多一条,无需维护两份清单。文档布局 website/src/app/docs/layout.tsx 则用 Fumadocs 的DocsLayout一行代码获得带侧边栏、主题切换与社交链接的完整文档框架。

快速上手:五步复刻这套文档站

  1. 初始化:next@16+fumadocs-mdx+fumadocs-core+fumadocs-ui,文档写入content/docs/
  2. source.config.tsdefineDocs并加入rehype-raw(记得passThrough白名单);
  3. loader({ baseUrl: "/docs" })生成source,所有动态功能(导航、sitemap、llms.txt)都从它取数;
  4. 添加llms.txt索引路由 + 每页index.md路由,全部标记force-static
  5. next.config.mjs开启output: "export"wrangler deploy上线。

总结:这套做法好在哪

  • 纯静态:构建期生成一切,托管零成本,无服务端运维;
  • 一份内容三个出口:人看的 HTML、人复制的 Markdown、AI 读的llms.md/llms.txt,全部来自同一目录的同一批文件;
  • 约定优于配置:新增文档后,导航、sitemap、AI 索引全部自动生效;
  • 细节克制:按需的代码高亮语言、自托管字体、统一叶子文件名,都是"小决定换大省心"的典型案例。

如果你正在为开源项目搭建文档站,website/ 目录就是一个可直接对读的完整参考实现。

【免费下载链接】tinycastTinycast — a tiny, fully native macOS launcher, hotkeys, and clipboard history.项目地址: https://gitcode.com/GitHub_Trending/ti/tinycast

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询