首页
/ Twenty 文档站迁移 Mintlify 实践:从 twenty-website 到 twenty-docs 的完整落地路径

Twenty 文档站迁移 Mintlify 实践:从 twenty-website 到 twenty-docs 的完整落地路径

2026-09-07 16:45:38作者:温玫谨Lighthearted

本文基于 Twenty 仓库中的 MIGRATION.md 展开,完整还原其官方文档站从旧站点(twenty-website)迁移到 Mintlify 独立包 packages/twenty-docs 的范围、组件转换规则、目录结构、本地验证与部署流程,并结合当前仓库中的 Nx 项目配置docs.json 与导航生成脚本,深入讲解迁移完成后这套文档工程如何演进为多语言、可校验的持续化文档管线。读完后你将掌握:如何在 Nx monorepo 中托管并本地预览 Mintlify 文档站、如何复现“旧自定义组件 → Mintlify 等价组件”的转换映射,以及文档导航如何由单一基础结构文件自动生成为多语言配置。

一、迁移背景与范围:一次性搬完 69 篇 MDX 与 81 张图

MIGRATION.md 开篇以“Mintlify Migration Summary”的形式记录了这次迁移搬动的全部内容。Twenty 官方文档原先嵌在 twenty-website 站点中,采用自研 React 组件渲染;迁移后文档独立为仓库内的 packages/twenty-docs 包,由 Mintlify 托管渲染与部署。迁移范围如下表(数字以迁移文档记录为准):

类别 数量 说明
MDX 文档文件 69 篇 从 twenty-website 复制到 twenty-docs
用户指南文章 45 篇 面向产品使用者
开发者文档文章 22 篇 面向贡献者与集成开发者
入门指南 2 篇 迁移前已存在
图片与资产 81 张 用户指南截图、开发者文档配图、Logo 与品牌资产

导航结构随内容一并迁移:Mintlify 主配置中包含带 Tab 与嵌套分组的完整导航——迁移时 User Guide 标签页有 11 个分组(section),Developers 标签页有 6 个分组。

从当前仓库结构看,这套内容已经明显“长大”:packages/twenty-docs 下的英文 MDX 覆盖 getting-started/(11 篇)、developers/(49 篇)、user-guide/(一百余篇,含 Data Model、Data Migration、Workflows 等 15 个主题目录),并且 l/ 目录下沉淀了 12 种语言的翻译副本。这说明迁移是一次“底座铺设”:把内容与导航整体搬入 Mintlify 约定后,后续多语言与内容扩展都建立在这个结构之上。

二、组件转换映射:旧自定义组件如何落到 Mintlify 等价物

旧文档页大量使用自研 React 组件,Mintlify 只提供一套固定组件库,因此迁移的核心工作之一是逐类替换。MIGRATION.md 给出的转换规则与后续人工复核清单如下:

已完成的机械替换

旧组件 迁移方式
<ArticleWarning> 替换为 Mintlify 的 <Warning> 提示组件
<ArticleLink href="...">text</ArticleLink> 降级为原生 Markdown 链接 text
<ArticleEditContent> 直接删除(Mintlify 侧无需对应物)

需要人工复核的部分

  • <ArticleTabs>:Mintlify 的对应组件是 <Tabs>,需逐页转换;
  • 嵌入式 iframe / 视频:可能需要调整实现方式;
  • 自定义样式元素:需逐一检查 Mintlify 兼容性。

对于“视频嵌入”这一已知难点,仓库中的实际答案是保留了一个可复用的 MDX 片段 snippets/vimeo-embed.mdx:它导出一个 VimeoEmbed 组件,内部用 69.01% 的 padding-top 撑出 16:9 比例的容器,通过 iframe 内嵌 player.vimeo.com 播放地址并开启 autoplay/loop 参数。文档页引入该片段即可替代原站点的视频组件——这正是迁移文档中“Embedded iframes/videos - May need adjustment”一条的最终落点。

三、迁移后的目录结构:从 Mintlify 约定到实际仓库

MIGRATION.md 记录的迁移期目录结构如下(原样保留,便于对照迁移意图):

packages/twenty-docs/
├── mint.json                       # 主配置
├── user-guide/
│   ├── getting-started/             # 7 文件
│   ├── data-model/                  # 6 文件
│   ├── crm-essentials/              # 4 文件
│   ├── views/                       # 2 文件
│   ├── workflows/                   # 7 文件
│   ├── collaboration/               # 3 文件
│   ├── integrations-api/            # 3 文件
│   ├── reporting/                   # 1 文件
│   ├── settings/                    # 9 文件
│   ├── pricing/                     # 1 文件
│   └── resources/                   # 2 文件
├── developers/
│   ├── self-hosting/                # 5 文件
│   ├── api-and-webhooks/            # 2 文件
│   ├── frontend-development/        # 8 文件
│   ├── backend-development/         # 7 文件
│   ├── local-setup.mdx
│   └── bug-and-requests.mdx
└── public/
    └── images/                      # 81 张图片

对照当前仓库,可以确认两处后续演进(属于迁移完成后的正常调整,非迁移文档本身的范围):

  1. 主配置文件由 mint.json 演变为 docs.json。当前 docs.json 顶部声明 "name": "Twenty Documentation""theme": "almond",并配置了 logo(/logo.svg,明暗主题共用)、favicon、主色(#141414)、导航栏按钮与 styling.eyebrows: "breadcrumbs"navigation 字段则被扩展为 languages 数组,包含英文与法语、阿拉伯语等 12 种语言的完整 Tab/Group/Page 树。
  2. 图片目录由 public/images/ 收敛为 images/。当前 README 明确约定“图片放入 /images/ 目录”,并在 MDX 中以 Alt text 引用,或用 Mintlify 的 <Frame> 组件包裹 <img>

内容目录也从迁移期的 11+6 个分组重组为现在的三大 Tab:getting-started/(Welcome + Core Concepts)、user-guide/(Overview、Data Model、Data Migration、Calendar & Emails、Workflows、AI、Layout、Dashboards、Permissions & Access、Billing、Settings、Legal 等分组)、developers/(Apps、API、Self-Host、Contribute 等分组),这些分组名可直接在 docs.jsonen 语言块中逐一对应到真实 MDX 路径。

四、本地验证:Nx 目标驱动 Mintlify Dev Server

MIGRATION.md 的 Testing 章节给出的验证方式是在 monorepo 根目录启动本地 Mintlify 开发服务器,并在浏览器打开 3000 端口预览全部迁移后的文档:

npx nx run twenty-docs:dev

这个命令的实际执行链路可以在 project.json 中完整核对:dev 目标使用 nx:run-commands 执行器,以包目录为工作目录运行 mintlify dev;同文件还定义了另外四个目标,构成完整的本地验证矩阵:

  • devmintlify dev,启动开发服务器(默认 http://localhost:3000);
  • validatemintlify validate,校验文档构建是否合法,对应根目录命令 npx nx run twenty-docs:validate
  • lint:先跑 npx oxlint -c .oxlintrc.json .(通用 TS/JS 规则),再跑 npx tsx scripts/lint-mdx.ts(MDX 专用规则),串行执行;
  • testnpx vitest run --config vitest.config.mts,用于脚本层单测;
  • fmt:Prettier 检查/修复,带缓存目录。

运行前提也写得很明确:package.json 声明 engines 为 Node ^24.5.0、Yarn ^4.0.2npm 字段为 please-use-yarn,即强制 Yarn),mintlify 依赖版本锁定在 ^4.2.790。复现迁移文档的验证步骤时,应使用仓库统一的 Yarn 工作区环境,而不是单独 npm install

五、部署流程:仓库即文档源

MIGRATION.md 的 Deployment 章节给出了四步上线流程,核心思想是“文档以仓库文件为唯一事实来源,Mintlify 只负责拉取与构建”:

  1. 将变更推送到代码仓库;
  2. 在 Mintlify 控制台关联该仓库;
  3. 将子目录(subdirectory)设置为 packages/twenty-docs——即 Mintlify 不会构建整个 monorepo,只以该包为文档根;
  4. 之后 Mintlify 在检测到变更时自动部署,并自动生成搜索 embeddings。

这套“子目录 + 自动部署”模式与仓库内的工程配置互相印证:docs.json 中配置了 SEO canonical 指向线上文档域名,意味着自动部署后的页面会声明规范链接;而本地 validate 目标正是上线前对同一份配置做静态校验的对应手段。

六、迁移完成后的演进:导航从手写 JSON 变成生成管线

MIGRATION.md 在 Status 一节宣布迁移完成:旧的文档载体被移除,文档此后全部存放在 packages/twenty-docs。(从当前源码结构看,packages/twenty-website 包仍然存在,但从其 package.json 看它现在是基于 Next.js 的营销站点,不再承担文档职责——可以推断迁移文档所指的“removed”是旧版内嵌文档的 website 形态,而非当前这个营销站点目录。)

迁移完成后,docs.json 没有停留在手写状态,而是长出了一条“基础结构 + 翻译标签 → 生成”的管线,这是理解当前文档站导航的关键:

导航事实来源与生成脚本

  • navigation/base-structure.json:唯一的事实来源(source of truth),只含英文标签与页面 slug,按 tabs → groups → pages 三级组织,且支持分组嵌套(如 Workflows 的 How-Tos 下再分 CRM Automations / Connect to Other Tools / Advanced Configurations / Need More Help 四个子组)。按 README 说明,该文件不上传翻译平台。
  • scripts/generate-docs-json.ts:读取 base-structure,并为每种支持语言加载 l/<language>/navigation.json 中的标签映射,最终把结果写回 docs.jsonnavigation.languages。语言清单由 navigation/supported-languages.ts 从 twenty-shared 的 DOCUMENTATION_SUPPORTED_LANGUAGES 常量复用而来,保证文档站语言列表与产品常量同源。
  • 根目录通过 package.json 暴露为 yarn docs:generateyarn docs:generate-navigation-template 两个命令,对应上述脚本。

生成逻辑里有一段值得注意的工程约束(generate-docs-json.ts 的源码注释):Mintlify 要求每个页面路径只能出现在一种语言的导航里,否则语言切换器无法解析等价页面、会回退到第一篇页面。因此脚本只在 l/<lang>/<slug>.mdx 真实存在时才把该页面挂进对应语言(见 formatPageSlug,第 156–164 行),空的分组与 Tab 会被整体丢弃。这就是 l/ 目录中每种语言恰好是 117 篇 user-guide + 74 篇 developers + 11 篇 getting-started 的由来——翻译缺口的页面会自动从该语言导航中消失,而不是渲染出死链。

MDX 质量门禁:为翻译管线定制的 Lint

scripts/lint-mdx.ts 是迁移“人工复核清单”沉淀下来的自动化防线。它解决一个非常具体的问题:翻译平台会把正文中的 <foo> 解析成标签,导致尖括号占位符在每种语言的译文里丢失或变形;而花括号 {foo} 能安全往返(见 第 3–6 行 的注释)。脚本的判定细节包括:

  • 跳过 node_moduleslimagesscripts 目录,只扫描源 MDX;
  • 内置约 60 个合法 HTML 元素名单(imgiframevideo 等),避免误报真实元素;
  • 精确计算围栏代码块(支持不同长度的反引号围栏配对)与行内代码区间,代码内的占位符不计为违规;
  • 命中时输出 文件:行:列 并提示“reads as a tag in Crowdin, use {name} instead”,有违规则退出码 1。

配合 lint 目标中的 oxlint,MDX 内容在进入翻译管线前就有机器校验——这是对迁移文档中“Custom styled elements - Review for compatibility”这类遗留项的长期治理。

七、已知问题清单与遗留事项

MIGRATION.md 末尾的 Known Issues to Review 是迁移期的诚实存档,逐条对照当前仓库可作如下收束:

  • ArticleTabs 组件可能需手工转换:Mintlify 使用 <Tabs> 组件,需逐页处理——对应现在 MDX 页面中的 Tabs 用法;
  • 部分图片路径可能不正确:当前图片统一收敛在 images/ 下,按 README 约定以 /images/... 绝对路径引用;
  • 自定义样式组件可能需要调整:以 snippets/ 中的可复用片段(card-title、chart-icon、vimeo-embed)+ oxlint/MDX lint 双重约束来收敛;
  • 视频嵌入可能需要复核:已用 VimeoEmbed 片段给出统一实现。

八、小结:一次迁移如何变成一套可持续的文档工程

回顾这次迁移的完整轨迹:先用明确的范围清单(69 篇 MDX、81 张图、完整导航)完成一次性搬迁;再用“旧组件 → Mintlify 等价物”的映射表消除渲染层差异;随后以 npx nx run twenty-docs:dev 在 3000 端口做整站预览、以 validate 做构建校验,并把子目录 packages/twenty-docs 接入 Mintlify 的自动部署。迁移结束后,仓库又把导航改造成 base-structure.json → generate-docs-json.ts → docs.json 的生成式管线,让 12 种语言共用一份结构、各取一份标签,并用专门的 MDX lint 守住翻译往返的一致性。对需要把文档站从自研组件迁移到 Mintlify(或同类托管文档平台)的团队来说,这份仓库内的完整案例提供了从范围盘点、组件转换、本地验证到多语言持续治理的可复制路径。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388