AI SDK 官方文档站(ai-sdk.dev)技术架构与实践:基于 Geistdocs 的多版本文档应用构建指南
【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai
本文面向希望了解或复刻 AI SDK 官方文档站点实现方式的开发者。AI SDK(The AI Toolkit for TypeScript)的官方文档站是一个基于 Vercel Geistdocs 框架构建的包级应用,托管于仓库的apps/docs目录,负责ai-sdk.dev的文档、Providers、Cookbook 等全部内容面。读完本文,你将掌握该文档应用的本地开发流程、三版本(v5/v6/v7)内容同步管线的完整原理、Geistdocs 多版本路由配置、Vercel 部署要点,以及 llms.txt、站点地图与社交卡片等面向搜索引擎与 LLM 的 SEO 基建实现。
一、应用定位:一个由包驱动的文档站
apps/docs是仓库中的一个独立包(package name 为ai-sdk-docs),其核心定位在 apps/docs/README.md 中写得很清楚:
This is the package-backed Geistdocs application for
ai-sdk.dev.
所谓"package-backed",意味着文档站的依赖、脚本和构建配置全部收拢在这个包内,与仓库中content/目录的原始文档源相互独立。文档站本身并不直接消费content/下的 MDX 文件,而是先通过内容同步脚本把源文件变换并拷贝到apps/docs/content/生成目录,再由 Geistdocs/Fumadocs 消费。
从 apps/docs/package.json 可以看到其技术栈:
- 框架:Next.js 16.2.12 + React 19.2.3,使用
@vercel/geistdocs1.20.4 作为文档框架; - 文档管线:
fumadocs-core/fumadocs-mdx/fumadocs-ui负责 MDX 编译与 UI; - 代码高亮:
shiki3.23.0 配合@shikijs/langs与@shikijs/transformers; - 其他:
zod(配置与 Frontmatter 校验)、lucide-react(图标)、@vercel/analytics(站点分析)。
二、本地开发:三步起一个文档站
README 明确要求使用Node.js 22 或更新版本,并在仓库根目录执行命令:
pnpm install pnpm --filter ai-sdk-docs dev:site其中dev:site脚本(见 apps/docs/package.json)实际上是三件事的串联:
"dev:site": "pnpm sync-content && fumadocs-mdx && next dev"pnpm sync-content:执行内容同步脚本,把多版本文档源变换到apps/docs/content/;fumadocs-mdx:生成 Fumadocs 的 MDX 集合配置;next dev:启动 Next.js 开发服务器。
因此,如果你直接运行next dev而跳过前两步,站点会因为缺少content/目录而无法渲染页面——这也是 README 强调"内容同步生成apps/docs/content/"的原因。
完整本地校验
运行完整的本地校验命令:
pnpm --filter ai-sdk-docs validate:site它等价于先跑单测再跑生产构建:
"test:site": "node --test scripts/*.test.mjs", "build:site": "pnpm sync-content && fumadocs-mdx && next build", "validate:site": "pnpm test:site && pnpm build:site"其中test:site使用 Node 内置的node --test运行scripts/*.test.mjs(当前为 sync-content-utils.test.mjs),对内容变换工具函数做单元测试。
另外需要注意:生成后的内容(apps/docs/content/)、Fumadocs 源文件和 Next.js 构建输出均被 Git 忽略,不会提交进仓库,每次构建都从源重新生成。
三、内容同步管线:三版本文档的单一事实来源
这是整个文档应用最核心的机制。同步脚本 apps/docs/scripts/sync-content.mjs 从三个经过评审的来源拉取内容:
| 版本 | 来源 | 说明 |
|---|---|---|
| v7 | 当前工作区的content/docs/ | 即仓库main分支的实时内容 |
| v6 | 固定 commit31e168b16f71a2abc03a1fae69176886577337f4 | 在脚本中显式 pin 的 SHA |
| v5 | 固定 commit1319452c1f1a75045950817242ef3207dac1e540 | 同上 |
脚本头部注释明确解释了 pin 版本的目的:"Pinning keeps builds reproducible and content changes reviewable"(固定 commit 保证构建可复现、内容变更可评审)。这意味着 v6/v5 的稳定文档不会跟随 v7 主线的每次修改而漂移,只有在明确更新 SHA 时才会发布新的维护版文档。
同步的内容家族
脚本遍历families = ["docs", "providers", "cookbook"]三个内容家族,对应仓库根目录的content/docs、content/providers、content/cookbook。对每个版本 × 家族组合,输出到:
apps/docs/content/{v5|v6|v7}/{docs|providers|cookbook}例如 v7 文档最终位于apps/docs/content/v7/docs,这正是 apps/docs/geistdocs.tsx 中content配置所指向的目录。
拉取策略:git 优先,tarball 兜底
fetchRef函数为固定 commit 提供了三层回退策略(sync-content.mjs第 60-86 行):
- origin 远程:
git fetch --depth=1 origin <ref>后用git archive FETCH_HEAD content | tar -x解出content/; - 本地 git 对象:直接
git archive <ref> content(适合仓库已包含该对象的情况); - GitHub tarball:
curl -sfL https://codeload.github.com/vercel/ai/tar.gz/<ref>下载并解压(为无 git 访问权限的环境兜底)。
拉取结果缓存于apps/docs/node_modules/.cache/ai-sdk-docs,第二次运行直接使用缓存;需要强制刷新缓存时传--force参数:node scripts/sync-content.mjs --force。
四、内容变换规则:从NN-前缀到 Fumadocs 的完整映射
原始内容(仓库content/目录)使用NN-数字前缀组织目录与文件名(例如02-foundations),而 Fumadocs 需要干净的 slug。变换逻辑集中在 apps/docs/scripts/sync-content-utils.mjs,共 4 步:
1. 剥离NN-数字前缀并生成 meta.json
parseSegment用正则/^(\d+)-(.+)$/解析路径段,transformDir递归遍历并按数字前缀排序,为每个目录生成meta.json(pages数组即排序后的干净文件名列表)。同时处理两个特殊场景:
collapsed: true:目录index.mdx的 Frontmatter 若标记collapsed: true,则在 meta.json 中写入"defaultOpen": false,使侧边栏默认折叠;- 前缀冲突检测:如果两个文件剥离前缀后撞名(如
01-foo.mdx与02-foo.mdx),脚本会直接抛错,防止生成不可预测的路由。
2. 丢弃 index.mdx,避免重复的 Overview 页面
如果目录内同时存在index.mdx和overview.mdx,则丢弃index(它曾是旧站点的卡片网格落地页)。原因是 Geistdocs 会把文件夹索引页渲染为侧边栏中合成的 "Overview" 项,从而与真实的 Overview 页面重复。被丢弃 index 的 Frontmatter 信号(如collapsed)仍会保留到目录的 meta.json。纯 Frontmatter 的 index 页(Cookbook 各章节)同理被丢弃,因为旧应用从未渲染它们。
3. 剥离正文首个# H1
Geistdocs 用 Frontmatter 的title作为页面 H1,因此stripLeadingH1会把 MDX 正文开头(Frontmatter 之后)的第一个# 标题行删除,避免重复标题。
4. 代码围栏 meta 重写与遗留链接修复
rewriteLines处理代码块的展示约定:
| 原始写法 | 变换后 | 说明 |
|---|---|---|
```ts filename="x" | ```ts title="x" | filename/file→ Fumadocs 的title |
highlight="1,3-5" | {1,3-5} | 高亮行 →transformerMetaHighlight语法 |
```typescript" | ```typescript | 清理围栏语言后的多余引号 |
```prompt/```env/```rego | txt/dotenv/txt | 重映射 Shiki 未内置的语言 |
同时,rewriteLegacyLinks会把旧版锚点批量重定向到新锚点,例如#ui-message-stream-protocol→#data-stream-protocol、#multi-modal-messages→#file-parts、#attachments-experimental→#attachments等共 10 组映射,保证存量外链不失效。addLegacyAnchors还为streamText、Output、Telemetry等特殊页面插入<span id="..."/>形式的兼容锚点。
变换后的渲染配置
变换产出的{1,3-5}高亮 meta 由 apps/docs/source.config.ts 中的transformerMetaHighlight()消费;文档集合通过defineDocs注册,并启用includeProcessedMarkdown: true以输出处理后的 Markdown(供 llms.txt 等场景使用)。
五、多版本路由:Geistdocs 版本化配置
版本切换与路由挂载完全由 apps/docs/geistdocs.tsx 声明:
- 站点身份:
title = 'AI SDK',siteId = 'ai-sdk'用于向 Geistdocs 平台上报反馈问题(feedback)与 markdown 请求追踪; - 导航:Docs、Resources(Recipes / Tools Registry / Templates / Showcase)、Providers 三大导航入口;
- 内容集合:共 9 个集合(v5/v6/v7 × docs/providers/cookbook),v7 挂载在无前缀路由(
/docs、/providers、/cookbook),v6/v5 分别挂载在/v6、/v5前缀下; - 版本列表:
current: 'v7',v6 描述为 "v6 maintenance documentation",v5 为 "v5 maintenance documentation",版本切换 UI 由此驱动。
路由重定向矩阵
apps/docs/next.config.ts 中配置了大量重定向,核心规则包括:
- v4 归档:
/v4与/v4/:path*永久重定向到独立的 v4 归档站(v4 不纳入本应用构建,以控制内存占用); - v7 无前缀化:
/v7→/,/v7/:path*→/:path*; - 章节落地页折叠:
/docs/:section(基础章节)/重定向到对应的overview页(与内容同步丢弃 index.mdx 的行为呼应,见 sync-content-utils.mjs); - 遗留资源 URL:
/tools-registry→/resources/tools、/showcase→/resources/showcase、/elements→ 独立站点、/model-library→ Vercel AI Gateway 文档; - Cookbook 双表面:
/cookbook与/resources/recipes均可用,章节落地页(如/cookbook/node)重定向到该章节第一篇菜谱generate-text; - 内容迁移:
/docs/ai-sdk-core/prompts→/docs/foundations/prompts,validate-json-rpc-message→create-mcp-client。
这些重定向的目标是完全镜像生产站 ai-sdk.dev 的 URL 行为,保证搜索引擎收录的旧链接全部可达。
六、Vercel 部署:外部源码目录与构建命令
README 的 "Vercel project" 一节明确了三个关键配置:
| 配置项 | 值 | 原因 |
|---|---|---|
| Root Directory | apps/docs | 以文档包为部署根 |
| Include source files outside the Root Directory | enabled | 内容同步需要读取仓库根目录的content/docs/与 Git 元数据 |
| Node.js | 仓库支持的版本 | README 要求本地 Node.js 22+,部署环境同样需要满足 |
第二个设置至关重要:由于构建脚本会从仓库根目录的content/同步内容,并执行git fetch/git archive操作,Vercel 必须在构建镜像中包含根目录源码与.git元数据。
apps/docs/vercel.json 补充了部署策略:
{ "buildCommand": "pnpm build:site", "git": { "deploymentEnabled": { "release-v*": false, "changeset-release/release-v*": false, "changesets-ghcommit-temp/**": false, "backport-pr-*": false } } }即发布分支(release-v*等)不触发自动部署,避免中间态发布到生产。
七、面向搜索引擎与 LLM 的基建
README 提到"镜像生产环境",这背后是一整套可被搜索引擎与 LLM 消费的产物:
llms.txt 与 Markdown 代理
apps/docs/proxy.ts 使用 Geistdocs 的createProxy将文档 URL 映射到llms.mdx渲染路由。每个 URL 面(/docs/*、/v6/docs/*、/providers/*、/cookbook/*及/resources/recipes/*)都对应一个[lang]/...-llms.mdx路由,为 Agent/LLM 提供纯 Markdown 版本的页面内容。目录中同时存在app/[lang]/llms.txt/route.ts与app/[lang]/sitemap.md/route.ts,即标准化的llms.txt索引与可读站点地图。
双 URL 表面与 canonical
每条 Cookbook 菜谱同时服务在/cookbook/...与/resources/recipes/...两个 URL 面,而sitemap、llms.txt 与搜索 canonical 统一指向/cookbook,避免重复内容影响 SEO 权重。
社交卡片(Open Graph 图片)
社交卡片由app/[lang]/og/[...slug]/route.tsx渲染(对应 README 中的路径),同时支持两种 URL 形态:
- Geistdocs 形态:
/og/<slugs>/image.png; - 遗留生产形态:
/og/docs?title=…&description=…(查询参数形态)。
该路由(见 apps/docs/app/[lang]/og/[...slug]/route.tsx)只对**当前版本(v7)**的三个源(docs/providers/cookbook)生成卡片,维护版本(v5/v6)是 noindex 且无卡片。实现上使用 Next.jsImageResponse,对标题(140 字符)与描述(320 字符)做截断以控制渲染成本,并通过两种缓存策略优化 CDN 命中:查询参数形态(URL 随内容变化)使用immutable缓存一年,slug 形态(URL 稳定)让浏览器每次 revalidate、CDN 缓存一年。
八、第三方 Logo 的版权边界
README 最后说明public/images/中的第三方资源:
public/images/icons/:Providers 索引页上的第三方提供商 Logo(提名性使用);public/images/showcase/:Showcase 页面的产品截图与 Logo;components/docs/upsell.tsx:内联的客户 Logo。
这些标识属于各自所有者,不涵盖在本仓库的开源许可范围内。若你复刻此文档站,需要注意保留该版权声明并遵守各 Logo 的使用条款。
九、实践要点总结
- 本地开发三步:
pnpm install→pnpm --filter ai-sdk-docs dev:site,Node.js 需 22+; - 内容同步是三段式:拉取(git archive / tarball 兜底)→ 变换(剥前缀、去 H1、改围栏 meta、修链接)→ 输出到
apps/docs/content/{v5,v6,v7}/,产物不入 Git,缓存可--force刷新; - 多版本靠 Geistdocs 声明式配置:
geistdocs.tsx的content与versions是唯一事实来源,重定向矩阵在next.config.ts中镜像生产行为; - 部署关键在"外部源码":Vercel 必须开启 "Include source files outside the Root Directory",否则同步脚本无法读取根目录
content/; - SEO/LLM 基建分层:
llms.txt+ Markdown 代理 + 双 URL canonical 归一到/cookbook+ v7-only 社交卡片。
若想深入源码,建议依次阅读 apps/docs/scripts/sync-content.mjs(同步主流程)、apps/docs/scripts/sync-content-utils.mjs(变换规则与测试对象)、apps/docs/geistdocs.tsx(站点配置)以及 apps/docs/next.config.ts(重定向矩阵),它们共同构成了 ai-sdk.dev 这套"内容源与文档应用解耦、多版本可复现构建"的完整工程方案。
【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考