首页
/ Supabase 文档工程实战:从 MDX 规范到 spec 生成的 apps/docs 内容体系

Supabase 文档工程实战:从 MDX 规范到 spec 生成的 apps/docs 内容体系

2026-09-06 12:43:10作者:平淮齐Percy

本文基于 Supabase 官方仓库的 apps/docs/CONTRIBUTING.md,完整拆解其文档写作体系:通用写作原则、四类文档(Explainer / Tutorial / Guide / Reference)的定位、AI Agent Skills 写作流水线、MDX 指南与 spec 生成式参考页的结构、内容复用与组件规范,以及词表 lint 与混合搜索索引的实现。读完后,你能掌握在 apps/docs 中新增一篇 Guide(含 frontmatter 与导航注册)、维护参考文档 spec、复用 partial 与 ContentListings 组件的完整工作流,并能理解文档站从 MDX 到 Mermaid、搜索索引的底层实现。

通用写作原则:为读者,也为了 Agent 写作

apps/docs/CONTRIBUTING.md 开宗明义:文档面向全球读者,必须 helpful、concise、understandable。文档中列出的核心原则如下:

  • 为用户写作:先想清楚读者读完这篇文档要完成什么任务,只告诉他们必须知道的东西。
  • 像说话一样写作:口语化的英语对全球读者(尤其是把英语作为第二语言的读者)更易理解、更易本地化。删掉不必要的词,大声读一遍自己的文稿来挑选最清晰的短语。
  • 短句优先:一句话只表达一个关系,避免复杂的复合结构,便于理解、本地化与一致解释。
  • 一段一个主题:主题变化就换段落,段落可以很短。
  • 避免习语和俚语(如 piece of cake),它们往往带有地域或文化属性。
  • 人称约定:用 you 指代读者;we 只用于指 Supabase 团队,不用于指读者。

值得注意的是,这份原则不仅是给人看的。仓库中配套的 AI 写作技能明确要求 Agent 把 CONTRIBUTING.md 当作"voice/terminology reference"——即写作风格与术语的唯一参照,例如 write-the-docs 技能 的核心规则第 3 条:"Follow CONTRIBUTING.md and WORD_LIST.md for voice, terminology, and formatting only, never for content accuracy"。也就是说:内容准确性由代码阅读决定,文风由 CONTRIBUTING.md 决定,两者职责分离。

术语与拼写:word list + supa-mdx-lint

文档规定使用美式英语,拼写以 WORD_LIST.md 为准,该词表同时是 lint 工具检查术语的依据。检查命令在 apps/docs 下运行 pnpm lint:mdx,对应 package.json 中的脚本:

"lint:mdx": "supa-mdx-lint content --config ../../supa-mdx-lint.config.toml"

仓库根目录的 supa-mdx-lint.config.toml 定义了实际执行的规则,从源码结构看包括:

  • Rule001HeadingCase:标题必须为 sentence case(首词与专有名词大写,其余小写);
  • Rule003Spelling:拼写检查,词表之外的词会报错;
  • Rule002AdmonitionTypes:admonition 只允许四种类型 note / caution / deprecation / danger——这与下文 Admonitions 一节的四种 type 严格对应,属于"规范即代码"的直接印证;
  • Rule004ExcludeWords:一组禁用词表(filler、marketing、vague_verbs、slang、first_person 等,配置在 supa-mdx-lint/Rule004ExcludeWords 下);
  • Rule006NoAbsoluteUrls:禁止以 https://supabase.com 开头的绝对链接,要求使用站内路径,对应文档中"站内链接不要带域名"的规则。

AI Agent Skills:把写作清单装进 Agent

apps/docs/CONTRIBUTING.md 专门有一节 "AI agent skills for docs authoring":如果你使用任何会读取 .agents/skills/ 目录的 AI 编码代理(Claude Code、Codex 等),仓库自带一组支撑 Write the docs 写作清单 的 skills。按名字调用即可(pm-the-docsask-the-docswrite-the-docsedit-the-docstest-the-docsreview-the-docs),在 Claude Code 中也可以作为 /name 斜杠命令使用。

文档给出的 skills 与写作阶段对应关系:

Skill 清单阶段 用途
pm-the-docs Frame / Shape 读者画像、产品阶段、跨模块范围决策(有 Supabase org 权限时走 universe 检索,否则走 OSS 路径)
ask-the-docs Frame / Shape apps/docs 架构、信息架构(IA)落位、内容存放位置
write-the-docs Draft 基于代码实证起草全新内容
edit-the-docs Edit 重构与改进已有页面
test-the-docs Draft / Self-review 在 Docker 隔离的本地栈中执行文档代码片段,产出验证报告
review-the-docs Self-review / PR review 草稿检查与 PR 分诊/验证

这些文件的权威位置在 .agents/skills/.claude/skills 是指向该目录的 Git 符号链接(git ls-files -s 中 mode 为 120000),以便 Claude Code 也能发现它们。

write-the-docs/SKILL.md 的实现看,这套流水线比表格更细。它把工作流拆为四个阶段:

  1. Phase 1 — Gather(只读收集):按固定顺序收集四类输入——风格指南(CONTRIBUTING.md + WORD_LIST.md)、产品意图(内部工具 Linear,OSS 贡献者非必需)、代码("PRD 描述意图,代码描述实际交付的行为",若两者冲突以代码为准)、以及作者补充的截图等材料(截图用于逐字核对 UI 按钮/菜单/字段标签);
  2. Phase 1.5 — 内容类型门禁:起草前先分类目标内容属于 Guide/Tutorial、Troubleshooting,还是生成式 Reference。若请求的其实是参考类内容(新 API 端点、配置项、SDK 方法),技能明确要求停止手写 MDX——因为它会与生成管线发散或被静默覆盖,正确路径是 apps/docs/spec/ + apps/docs/generator/ 管线;
  3. Phase 2 — Draft:遵循 MDX 约定(组件、frontmatter、代码示例接线),要求"placement(放在哪个分区)与 nav enablement(是否真的显示)是两件事",不能只把文件放进正确目录就认为完成;同时要求"为永恒而写"(优先记录当前已存在的东西,而不是承诺未来功能);
  4. Phase 2.5 / 3 — 审查与交接:交接前逐项核对(每条行为论断可追溯到代码阅读、术语与 WORD_LIST 一致、无单条列表滥用等),并主动提议运行 test-the-docs 对可执行片段做验证。

这条链路说明文档仓库的一个设计取向:写作规范本身被编码为 Agent 可读的结构化流程,人与 Agent 共用同一套 CONTRIBUTING.md 作为单一事实来源。

四类文档:先想清楚要写哪种

文档将 Supabase 文档分为 4 类,写之前必须先判断类型:

Explainers(解释型)

帮助读者学习一个主题,偏概念性、以散文为主。可以包含:

  • 一个功能是什么(what)
  • 为什么有用(why)
  • 何时使用的示例(when)
  • 如何工作的高层解释(how)

但 Explainers 不包含"如何使用它的步骤"——那是 Guide/Tutorial 的职责。

Tutorials(教程型)

目标导向,帮助读者完成一个大而复杂的目标,例如搭建一个使用多个 Supabase 功能的 Web 应用。Tutorial 混合散文解释与步骤(procedures),并为"为什么要这样做"提供上下文。

Guides(指南型)

同样是目标导向,但聚焦更短、更聚焦的任务,例如"为应用配置用户登录"。Guide 以步骤为主。文档对 Guide 提出了几条强约束:

  • 首句声明意图:每篇 guide 以一句话声明目标,如 This guide explains how to set up email login.,帮助读者和 Agent 确认该指南匹配其目标;
  • 保持步骤聚焦:把大量背景或概念解释移到独立小节或 explainer 中,交叉引用权威解释而不是在步骤里复述——保持行动路径可扫读,维护单一事实来源。推荐写法:This guide explains how to enable Row Level Security. To learn how Row Level Security controls access, see Row Level Security;不推荐先写几段 RLS 原理再说明本指南做什么;
  • 混合信息类型:当 guide 含有大量上下文或参考资料时,按信息类型分组,让背景信息不打断步骤流;
  • 导航:长 guide 开头给出主要章节组的短大纲并链接到每组,说明何时使用;短 guide 若标题已易扫读则不必加章节导航;
  • 交叉引用与衔接:在上下文小节与对应步骤之间建立连接(帮助读者导航时才加),为每个章节组加简短引言、信息类型切换时加过渡句、步骤结束后给出结果句(outcome),链接要克制地加而不是每节互链。

Reference(参考型)

参考文档"像字典词条",事实化、直接。包含:函数参数、返回类型、代码示例、可能导致数据丢失等关键错误的警告。不包含:功能背景解释、使用场景示例、多步骤操作。

这一分类不是纸上谈兵——上文 write-the-docs 技能的"内容类型门禁"正是把 Reference 识别为"由 spec/ 生成,不得手写 MDX",与本文档的 Reference 定义形成闭环。

仓库组织:content、federated 与 spec 三条内容管线

文档的 "Repo organization" 一节指出:

  • 大部分文档页在 apps/docs/content 目录;
  • 部分文档章节联邦化(federated)自其他仓库(例如 pg_graphql 仓库的 docs 目录);
  • 参考文档由 spec 目录中的 spec 文件生成

并给出了识别方法:联邦或参考文档通常使用 Next.js 动态路由(例如 [[...slug]].tsx),查找 spec 文件 import 或 repo 定义即可定位内容来源。原文给出的两个识别示例:

spec 文件 import 示例:

import specFile from '~/spec/transforms/analytics_v0_openapi_deparsed.json' with { type: 'json' }

repo 定义示例:

const org = 'supabase'
const repo = 'pg_graphql'
const branch = 'master'
const docsDir = 'docs'
const externalSite = 'https://supabase.github.io/pg_graphql'

Guide 结构:MDX + frontmatter + 导航注册

新增一篇 Guide 需要两样东西:

  1. YAML frontmatter
  2. 独立的导航文件中的 navigation 条目

frontmatter 中 title 必填,另有可选属性控制页面展示,包括 subtitletocVideohideToc

---
title: How to connect to Supabase
hideToc: true
---

一个真实对照:auth-email-passwordless.mdx 的 frontmatter 正是这种形态——title: 'Passwordless email sign-in' + subtitle: 'Email sign-in using Magic Links or One-Time Passwords (OTPs)',正文首句即声明意图,符合前文 Guide 的"首句声明目标"规则。

导航定义在 NavigationMenu.constants.ts:为新页面添加 nameurl 以及可选 icon 的条目。从源码看,该文件顶部先通过 isFeatureEnabled([...]) 读取了 20 多个特性开关(如 docs:auth_flowsdocs:local_developmentsdkDart 等),导航项的显示与否受特性开关门控——这意味着**"文件放在正确目录"不等于"页面出现在导航中"**,导航启用由特性开关与 constants 条目共同决定。这与 write-the-docs 技能强调的 "placement vs nav enablement 是两件事"完全一致。

Reference 结构:common spec + specific spec 双层生成

参考文档由 spec 与库源码共同产出,分为两层:

Common spec file

每种库类型(语言 SDK 或 CLI)有一个 common spec 文件,例如 common-client-libs-sections.json,它定义公共 SDK 函数,每个条目包含:

  • id:标识函数;
  • title:人类可读标题;
  • slug:URL slug;
  • product:归属的 Supabase 产品(如数据库操作归 database,Auth 操作归 auth);
  • typefunction(结构化函数定义)或 markdown(散文式解释小节)。

新增一个函数需要手动向该 common 文件添加条目。实际文件验证了这一点:条目形如 { "title": "Initializing", "id": "initializing", "slug": "initializing", "type": "function" },而 markdown 类型条目可带 excludes 字段,将某些小节从特定参考站(如 reference_python_v2)中排除。

Specific spec file

每个库还有自己的 spec 文件,包含库专属细节(原文以 JavaScript SDK 的 supabase_js_v2.yml 为例)。该文件列出的函数与 common spec 中的定义相匹配;每个函数包含描述、代码示例和可选注释。参数通过 $ref 属性从源码仓库拉取函数定义,参考 spec/Makefile 中的命令下载并转换。

spec/Makefile 的实际内容看,make 的默认目标是 run,串联四个阶段:download(用 curl 拉取 Management API、MCP 工具权限、Storage、tsdoc 等 spec 源)→ transformgenerateformat,生成器代码位于 packages/generator

文档同时给出了库维护者更新函数参数/返回值的标准流程:

  1. 将改动合入库的 master 分支;
  2. 等待 action 更新 gh-pages 分支中的 spec;
  3. supabase/supabase 仓库的 apps/docs/spec 目录运行 make
  4. 在本地文档站验证改动。

非库维护者无需关心此流程。

内容复用:partials

如果同一段内容要在多个文件复制出现,应创建 partial 而不是复制粘贴。Partials 是位于 apps/docs/content/_partials 的 MDX 文件,包含可插入多个页面的可复用片段——例如为一组教程定义一个公共 setup 步骤。该目录中实际存在 create_client_snippet.mdxdatabase_setup.mdxauth_methods.mdx 等大量片段。

使用方式有两种:

  1. 在你的 MDX 文件中 import 该 partial;
  2. 把 partial 加入 MdxBase.shared.tsxcomponents,实现自动注入。该文件同时是所有文档页面共享组件(ContentListingsMermaidButtonTabs 等)的统一路由点。

组件与元素规范

Admonitions

Admonition(警示框)用于引起读者对重要信息的注意。文档强调"用则慎用":只用于读者可能忽略且影响任务结果的信息,或把"有用但可选"的指引与主流程分离;不要堆叠、不要当装饰。并且每条 admonition 必须开篇即说明影响与目的("so what")——推荐 Deleting this project permanently removes its database and backups. Export any data that you want to keep before you continue.,不推荐 Before you continue, there are a few things that you should know about project deletion.

四种 type 各有严格适用场景:

  • danger:可能造成数据丢失、敏感数据泄露或其他难以逆转的严重后果。先说后果,再说如何避免;
  • deprecation:标识已弃用的功能/行为,说明对读者的影响并给出替代或迁移路径;
  • caution:可能导致 bug、操作失败、意外结果或严重不便,但未到 danger 级别;
  • note:重要前置条件、约束、澄清或可选捷径(无风险)。若信息是完成某步的必需项,应直接写进步骤。

结构属性:title(可选,短标题,内部不要再放 Markdown/HTML 标题——需要标题时应把标题及其小节移出 admonition)、children(正文富内容)、actions(可选,独立的行动按钮,上下文的链接和交互示例仍留在正文):

<Admonition
  type="note"
  title="Optional title"
  actions={<Button>Continue</Button>}
>

Your content here

</Admonition>

这四种类型正是 lint 规则 Rule002AdmonitionTypes 允许的全部取值,风格错误会被 CI 拦截。

Blockquotes 与 Footnotes

两条禁令:不要使用 blockquote;不要使用 footnote。

Code blocks

代码行保持短,避免横向滚动,例如用 \ 拆分长 shell 命令。语言约定:

  • JavaScript/TypeScript:仓库使用 Prettier,它同样格式化代码块中的 JS/TS;Prettier 检查不过 PR 会被阻止合并。从仓库根目录运行 pnpm format(根 package.json 中为 prettier --config prettier.config.mjs --write '{apps,packages,blocks,examples,i18n}/**/*.{js,jsx,ts,tsx,css,md,mdx,json}'),或在 IDE 中配置自动格式化;
  • SQL:偏好小写,如 select * from table 而非 SELECT * FROM table

两个可选扩展:在开反引号后指定文件名(```ts environment.ts),以及用 mark=${lineNumber} 高亮行:

```js mark=12:13
// your code

### Emphasis

粗体、斜体、行内代码各有专属用途,不得互换或仅用于视觉强调:

- **粗体**:读者会交互的 UI 标签(按钮、菜单项、字段名),如 `Click **Save**.`;以及读者绝不能漏掉的关键术语,如 `**Never** commit your service role key.`;
- *斜体*:首次引入一个新术语,或引用按惯例用斜体的标题/第三方产品名。少用;不用于 UI 标签或一般强调;
- `代码`:读者逐字输入或复制的内容,以及系统按字面读取的内容——文件名、路径、命令、flag、环境变量、函数/参数名、配置键、字面值。例如 `` Set `SUPABASE_URL` in your `.env` file. ``

一个短语若同时符合多类,选**最具体**的那一类:命令名是 `code` 而不是粗体。

### Content listings(内容清单组件)

概览页与索引页使用单个 `<ContentListings id="..." />` 组件承载"Get started"、"Next steps"、"Examples"、"Resources"等精选链接区。完整示例见 [storage.data.ts](https://gitcode.com/GitHub_Trending/supa/supabase/blob/e0280cb650d29ded05c080e35a52d22bf9dd84b9/apps/docs/data/content-listings/storage.data.ts?utm_source=gitcode_repo_files) 与 [storage.mdx](https://gitcode.com/GitHub_Trending/supa/supabase/blob/e0280cb650d29ded05c080e35a52d22bf9dd84b9/apps/docs/content/guides/storage.mdx?utm_source=gitcode_repo_files)。

手动添加的三步流程:

1. 在 [data/content-listings/](https://gitcode.com/GitHub_Trending/supa/supabase/blob/e0280cb650d29ded05c080e35a52d22bf9dd84b9/apps/docs/data/content-listings?utm_source=gitcode_repo_files) 下对应主题的 `[topic].data.ts` 中新增/更新 `ContentListingGroup` 导出。`id` 字段必须**全局唯一**(如用 `storage-get-started` 而不是 `get-started`)——该 ID 既是查找键,也是遥测中的 `listingId`;
2. 在 guide MDX 中内联放置组件,如 `<ContentListings id="storage-get-started" />`。仅当该块被复用、或需要在 partial 层级用 `$Show` 门控时才走 partial;对依赖特性开关的单个条目(如 `sdk:dart`),在条目上设置 `feature` 字段,而不是包裹整个 listing;
3. 从 `apps/docs` 运行 `pnpm test:local lib/content-listings.test.ts` 验证。

实际数据形态([storage.data.ts](https://gitcode.com/GitHub_Trending/supa/supabase/blob/e0280cb650d29ded05c080e35a52d22bf9dd84b9/apps/docs/data/content-listings/storage.data.ts?utm_source=gitcode_repo_files) 中的 `storageGetStarted`):

```ts
export const storageGetStarted: ContentListingGroup = {
  id: 'storage-get-started',
  heading: 'Get started',
  description: 'Choose the bucket type that fits your use case:',
  type: 'grid',
  items: [
    {
      title: 'Files buckets',
      href: '/guides/storage/quickstart',
      description: 'Store and serve images, videos, documents, ...',
    },
    // ...
  ],
}

文档还附了一段可直接投喂给 Agent 的 prompt 模板("Add a content listing block for [TOPIC] / [SECTION] … Follow CONTRIBUTING § Content listings in apps/docs. …"),并指出手动添加的代码片段模板在 .vscode/content-listing.code-snippetscl-data 生成带命名空间 ID 的数据导出,cl-inline 生成 MDX 组件用法——再次体现"规范同时服务于人与 Agent"的设计。该机制在 auth.mdx 同级的 auth.mdx 等索引页中可看到实际用法(<ContentListings id="auth-get-started" /> 等)。

Graphs(Mermaid 图表)

流程图、时序图、ER 图通过语言标识为 mermaid 的围栏代码块渲染。MDX 渲染管线会把这些块路由给共享的 Mermaid 组件——在 MdxBase.shared.tsx 中可以看到对应实现:检测 className 包含 language-mermaid 的 code 块并替换为 Mermaid 组件,因此主题会随明暗模式自动切换。

用法示例(时序图):

```mermaid
sequenceDiagram
  participant User
  participant Browser
  participant Supabase

  User->>Browser: Clicks "Sign in"
  Browser->>Supabase: Request authorization
  Supabase->>Browser: Return token

`flowchart` 关键字可带方向参数(`LR`、`TD`):

```mdx
```mermaid
flowchart LR
  A["content/**/*.md"] -->|Contentlayer| B[MDX]
  B --> C[Rehype]

写作要点:首行使用标准 Mermaid 图类型关键字(`sequenceDiagram`、`flowchart`、`erDiagram`);一张图只聚焦一个流程或概念,太密就拆;含特殊字符(`*`、`/`、空格、标点)的节点标签用双引号包裹,如 `A["content/**/*.md"]`;不要硬编码颜色(组件自动处理主题);图表辅助文字而非替代文字。

### Images

图片上传到 `apps/docs/public/img` 目录。矢量插画用 `.svg`,截图与非矢量图用 `.png`,受支持的浏览器会自动收到 `.webp` 版本。务必涂黑 API key 等敏感信息。

### Links

- 链接文本要有描述性(可访问性要求),例如不要用 `here` 当链接文本;
- 保持链接文本简短,用"足够描述的最短部分",例如 `see the reference section` 而不是 `see the reference section`;
- 站内链接**不要带域名**:文档页用 `/docs/...` 路径(如 `getting started`),文档外站点页用站点根路径(如 `open the Supabase Dashboard`)。这条规则同样被 `Rule006NoAbsoluteUrls` 在 lint 层强制执行。

### Procedures(步骤)

当人或 Agent 必须执行动作才能达到结果时,使用 procedure 格式来显式表达这一预期。写作规则:

- 顺序动作用有序列表;每步以祈使动词开头,每步一个动作(或紧密相关的一组动作),并给出足够上下文让读者知道在哪里操作;
- 应用信息映射的**分块原则**:每次呈现 7 ± 2 个相关步骤(5 到 9 个动作);任务复杂或不熟悉时取区间低端;
- 超过 9 步时,把相关步骤归入命名阶段或更小的 procedure;一步含多个独立动作就拆开;**不要为了凑数加步骤**;
- 存在真实的"定位动作"时,一步可拆成两步,例如:1. Open a terminal in your project directory. 2. Run `supabase start`。第一步为读者和 Agent 都建立了操作上下文;但真正原子的指令不要加冗余定位步骤(写 `Click **Save**.`,而不是另起一步 `Locate the **Save** button`)。

### Lists(列表)

必须依次执行的步骤用有序列表,顺序无关的用无序列表。有序用阿拉伯数字(`1`、`2`、`3`),无序用短横线(`-`)。**嵌套不超过两层**。

### Tabs

用 tabs 为不同平台或语言提供替代说明。可选的 `queryGroup` 属性支持通过 query 参数直达某个 tab(如 `?packagemanager=npm`):

<Tabs scrollable size="small" type="underlined" defaultActiveId="npm" queryGroup="packagemanager"

// ...

// ...

```

Videos

视频以 TOC 视频形式提供,而不是放在正文中。在页面 frontmatter 定义:

---
tocVideo: 'rzglqRdZUQE'
---

风格、格式与语法

文档在 "Styling, formatting, and grammar" 一节的总体态度是:语法在让表达更清晰时才使用。默认使用完整句子(明确动作主体与行为,减少读者、译者与 Agent 的歧义),仅在标题、标签、短列表项等利于扫读处使用句子片段。

  • 标题只是路标:标题下的内容必须脱离标题可理解,首句可以复述标题;
  • 不用括号做旁白:补充信息改写进句子或另起一句;括号只用于拼出全称后引入缩写(如 full-text search (FTS))或标注 (Optional);Markdown 链接或代码语法必需的括号不算旁白括号。

几条硬性规则:

  • 标题用 sentence case:Set up authentication 而非 Set Up Authentication
  • 使用牛津逗号:functions, tables, and indexes
  • 尽可能用现在时:the AI assistant answers your question 而非 will answer

搜索:FTS + pgvector 混合检索的文档站实现

文档最后一节 "Search" 解释了文档站的搜索架构,并与仓库中的搜索脚本互相印证:

  • 搜索运行在一个 Supabase 实例上。CI 中由脚本 generate-embeddings.ts 收集 guides、参考文档与其他内容,创建 OpenAI embeddings 并把搜索索引存入 Supabase 数据库;
  • 运行时是混合检索:Postgres 原生全文搜索(FTS)与基于 pgvector 的 embedding 相似度搜索结合。一次 PostgREST 调用触发加权 FTS RPC,而 Edge Function 负责运行 embedding 搜索。

generate-embeddings.ts 的源码可进一步确认实现细节:配置项中 EMBEDDING_MODELtext-embedding-ada-002、维度 1536,批量大小 128、最多 3 次重试;超过 16000 字符的输入会被截断后重试(字符级启发式而非精确 token 计算);Supabase 写入最多重试 2 次;来源抓取并发度为 10;指数退避还加入了抖动(jitter)。数据库侧的支撑结构可在 supabase/migrations 中找到对应的迁移文件(如 doc_embeddings.sql20250714120000_hybrid_search.sql),印证了"FTS 列 + embedding 列"的双通道索引设计。

落地清单:向文档仓库贡献一篇 Guide 的最小工作流

综合全文,一次完整的 Guide 贡献流程是:

  1. 判断类型:确认是 Guide/Tutorial 而非 Reference(Reference 走 spec/ 生成管线,不要手写 MDX);
  2. 新建 MDX:放在 apps/docs/content 对应目录,frontmatter 至少含 title(可选 subtitletocVideohideToc);
  3. 注册导航:在 NavigationMenu.constants.ts 添加 name / url / 可选 icon 条目,并留意特性开关对导航的启用控制;
  4. 复用与组件:重复内容进 apps/docs/content/_partials,精选链接区用 <ContentListings id="..." /> + data/content-listings/[topic].data.ts(id 全局唯一);
  5. 执行规范:首句声明意图、7 ± 2 分块步骤、admonition 开篇讲影响、代码块文件名与 mark= 高亮、SQL 小写、站内链接不带域名;
  6. 跑检查pnpm lint:mdx(术语与标题大小写等)、pnpm format(Prettier,CI 拦截)、pnpm test:local lib/content-listings.test.ts(若涉及 listings);
  7. 可选验证:通过 test-the-docs 技能在 Docker 隔离的本地栈中执行文档内的代码片段并产出验证报告。

这套体系的核心特征是"规范三重落地":CONTRIBUTING.md 供人阅读,supa-mdx-lint 规则供 CI 拦截,.agents/skills 供 Agent 执行——同一套写作标准同时约束人类作者、自动化检查与 AI 代理,这也是 Supabase 文档仓库值得其他开源项目参考的设计。

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