Scribe

内容模型

文件、frontmatter、内置字段、重定向以及 scribe validate 的检查项。

View as Markdown

文件

一个文档等于该类型文件夹中的一个 .mdx(或 .md)文件:

content/
  blog/
    hello-world.mdx        → slug 为 "hello-world"
    _redirects.json        → 该类型的重定向规则(可选)
  authors/
    jane.mdx               → slug 为 "jane"
  • 文件名即为英语版本的 slug。Slug 采用小写,并且使用连字符分隔(kebab-case)。
  • 磁盘上只存在英语文件;其他语言版本的数据保存在 SQLite 数据库中。
  • 如果文件名以 _ 或大写字母开头(例如 PUBLISHING.md),系统会忽略它们,因此你可以把笔记跟内容文件放在一起。

Frontmatter

Frontmatter 使用 YAML 编写,并根据该类型的 Zod schema 进行验证:

---
title: "Hello, world"
description: "满足 schema 要求的长度足够的描述。"
author: jane
publishedAt: "2026-01-15"
updatedAt: "2026-02-01"
---

正文使用 MDX 格式。

Schema 验证遵循你的 Zod schema:对于普通的 z.object,未知的键会被静默丢弃;如果你希望字段名称拼写错误时能触发验证失败,请使用 .strict()

内置的 frontmatter 字段

以下字段在每个内容类型中都可用,无需在 schema 中声明。这些字段会在你的 schema 运行前从 frontmatter 中提取,因此在 Zod schema 中声明它们没有任何作用:

字段类型说明
publishedAtISO 日期发布日期。
updatedAtISO 日期最后一次重要更新的日期。默认与 publishedAt 相同。用于生成站点地图的 lastModified
noindex布尔值从站点地图中排除该页面;你可以在页面中将其作为 robots meta 标签输出。
canonicalPath字符串手动覆盖规范(canonical)URL 路径。

多语言文档会从它们的英语源文档继承 publishedAtupdatedAtnoindexcanonicalPath;翻译人员无法更改这些字段。

每一个加载的文档都会附带 slugenSlug(英语源文档的 slug,在英语文档中与 slug 相同)、localefrontmatter 以及 content 属性。

无正文(Bodyless)类型

那些仅供引用的集合(例如 modelcategory 类型,其 schema 完全是结构化的数据)通常根本没有 MDX 正文。你可以在该类型上声明 body: false 来明确指出这一点:

defineContentType({
  id: "model",
  contentDir: "models",
  schema: modelSchema,
  body: false, // 条目仅包含 frontmatter
});

默认值为 body: true,所以这是完全向后兼容的。对于 body: false 的类型,包含除空白字符以外的任何正文内容都会导致验证错误。加载器会跳过 MDX 解析,并且静态导出不会输出正文。如果一个无正文类型同时具有零个可翻译字段,那么它将不会进入任何翻译流程(不会产生未翻译或内容已旧的干扰信息);如果无正文类型仍包含可翻译字段,它将带着仅有 frontmatter 的有效负载保留在待办事项列表中。关于可翻译性的规则,请参见 翻译

超越 Frontmatter

MDX 正文不仅能用于编写普通的纯文本:

  • 行内标记(Inline tokens) 可以将链接、资源 URL 以及不可翻译的字面量直接嵌入正文中,这些标记在读取时会根据具体语言进行解析。
  • 通过 field.asset() 声明的 资源(Assets) 会在磁盘上进行验证,并在加载时解析为公开 URL。

重定向:_redirects.json

在每个内容类型文件夹中,你可以添加一个可选的 _redirects.json 文件来声明 slug 的变更和已停用的文档。删除源 MDX 文件后,重定向规则依然生效;被翻译的源 slug 会自动通过 SQLite 展开。

{
  "redirects": [
    { "from": "hello-world", "toSlug": "hello-scribe" },
    { "from": ["old-a", "old-b"], "toSlug": "hello-scribe" },
    { "from": "moved-post", "toType": "glossary", "toSlug": "virtual-try-on" },
    { "from": "retired-page", "toUrl": "/pricing" },
    { "from": "retired-ext", "toUrl": "https://example.com/app" }
  ]
}

共有三种重定向类型(每个条目只能有一个目标):

类型字段说明
同类型toSlug相同内容类型下的目标英文 slug。URL 根据该类型的 path 生成,并随语言本地化。
跨类型toType + toSlug另一个可路由内容类型(必须有 path)下的目标英文 slug。
任意位置toUrl基于站点根目录的相对路径,或外部的绝对 URL。不同语言环境的目标相同。
  • from:仅限英文 slug。翻译的源 slug 会从 SQLite 解析。
  • 可选字段 permanent(默认为 true)。

要停用或重命名文档:请在 _redirects.json 中添加相应的条目,删除(或重命名)源 MDX 文件,然后运行 scribe validate 并重新构建项目。重定向规则由 buildAllContentRedirects() 输出,供你的代理服务器或框架配置使用。

验证

scribe validate

针对每个英文文件执行以下检查:schema 解析、内置字段的格式、你编写的 crossValidate 钩子,以及对正文进行 MDX 编译。无论是英文原文还是存储的翻译内容,如果正文无法作为 MDX 成功解析,都会产生阻断构建的错误。

在整个项目级别,它还会检查以下内容:关系完整性(缺失必填关系 = 错误,缺失可选关系 = 警告)、_redirects.json 规则(目标是否有效、源是否重复、是否存在重定向链)、本地化 slug 后缀规则、声明的资源字段(文件是否存在、formatsmaxKB)、行内正文标记(格式错误的 span、缺失关系、对不可路由类型的 :href 引用、缺失的 vars 键、缺失的资源文件)、声明为 body: false 但仍带有正文内容的类型、当设置了资源目录时缺失的图片资源,以及翻译存储库是否存在。

如果发现任何错误,退出状态码将非零。请在构建项目前运行它:

{
  "scripts": {
    "build": "scribe validate && <your framework build>"
  }
}
内容模型 · Scribe