首页
/ Reactive Resume Schema 参考详解:resumeDataSchema 全字段手册与可校验简历 JSON 生成指南

Reactive Resume Schema 参考详解:resumeDataSchema 全字段手册与可校验简历 JSON 生成指南

2026-09-05 14:50:36作者:滕妙奇

本文基于仓库中自动生成的 schema 参考文档,完整解析 Reactive Resume 简历数据的六个必需顶层字段、12 种内置节区的条目结构、customSections 判别联合(discriminated union)的全部变体,以及 metadata 中的布局、页面、设计与排版参数。读完后你可以直接构造出一份能通过 schema 校验、可导入 Reactive Resume 的完整简历 JSON,并理解每个字段的约束、默认值与底层 Zod 实现。

文档定位:由 resumeDataSchema 自动生成的参考

skills/resume-builder/references/schema.md 的开头明确声明:

Generated by pnpm docs:gen from resumeDataSchema. Do not edit this file directly.

它不是手写文档,而是从 Zod 模式 resumeDataSchema 生成的字段参考,服务于 resume-builder 技能(供对话式 AI 按 schema 生成简历 JSON)。生成链路可以从源码中完整追踪:

  1. 模式定义packages/schema/src/resume/data.ts 用 Zod 定义了全部子 schema(pictureSchemabasicsSchema、12 种 *ItemSchemametadataSchema 等),并在 resumeDataSchema 处 组合为顶层对象,同时导出解析函数 parseResumeData
  2. JSON Schema 转换packages/schema/src/resume/json-schema.ts 中的 createResumeDataJsonSchema() 通过 z.toJSONSchema(schema, { io: "input" }) 将 Zod 模式转换为 draft 2020-12 的 JSON Schema,即服务对外暴露的规范(canonical)schema(对应官方站点根路径的 /schema.json 端点,其使用说明见 docs/guides/json-resume-schema.mdx)。
  3. 文档再生成:根目录 package.json 中的 docs:gen 脚本依次执行 pnpm --filter server docs:gen(生成 docs/spec.json 等 OpenAPI 文档)和 pnpm --filter @reactive-resume/tooling docs:gen,后者由 tooling/semantic-css/generate-reference.ts 驱动,把 JSON Schema 展平为字段目录(field catalog),同时再生成 docs/guides/json-resume-schema.mdx 与本文所讲的 skills/resume-builder/references/schema.md

因此当你修改了 data.ts 中的任何字段定义(约束、描述文案),运行 pnpm docs:gen 即可同步更新参考文档——这正是“不要直接编辑该文件”的原因。

必需顶层字段

schema 文档列出的六个必需顶层字段是:

  • picture:照片配置
  • basics:作者简介(姓名、邮箱、电话、地址、网站)
  • summary:摘要/自我介绍
  • sections:12 种内置节区
  • customSections:自定义节区数组
  • metadata:模板、布局、页面、设计、排版等设计元数据

这与 data.ts 中 resumeDataSchema 的定义 完全一致;顶层使用 z.looseObject 包裹,额外字段会被保留而不报错。下面按字段逐一展开。

picture:照片的 9 个配置字段

对应 pictureSchema。所有字段均为必需(hidden 为 true 时其余字段仍需按默认值填写)。

路径 类型 必需 约束与默认值 说明
picture object 简历上照片的配置
picture.hidden boolean 是否隐藏照片
picture.url string 照片 URL,优先使用应用自托管路径(如 /uploads/...,通过上传接口填充)
picture.size number 最小 32,最大 512 显示尺寸,单位为 pt
picture.rotation number 最小 0,最大 360 旋转角度(度)
picture.aspectRatio number 最小 0.5,最大 2.5 宽高比(宽/高,如 1.5 表示 1.5:1)
picture.borderRadius number 最小 0,最大 100 圆角,单位为 pt
picture.borderColor string 边框颜色,rgba(r, g, b, a) 格式
picture.borderWidth number 最小 0 边框宽度,单位为 pt
picture.shadowColor string 阴影颜色,rgba(r, g, b, a) 格式
picture.shadowWidth number 最小 0 阴影宽度,单位为 pt

defaultResumeData 可以看到一组可直接复制的照片基线值:size: 80rotation: 0aspectRatio: 1borderRadius: 0borderColor: "rgba(0, 0, 0, 0.5)"borderWidth: 0shadowColor: "rgba(0, 0, 0, 0.5)"shadowWidth: 0

basics:作者简介与自定义字段

对应 basicsSchema

路径 类型 必需 约束与默认值 说明
basics.name string 简历作者全名
basics.headline string 职业头衔/一句话定位
basics.email string 邮箱地址
basics.phone string 电话号码
basics.location string 所在城市/地区
basics.website object 个人网站
basics.website.url string 链接 URL,必须带协议(http://https://
basics.website.label string 显示文本;留空则原样显示 URL
basics.customFields array 自定义字段列表
basics.customFields[].id string 唯一标识,通常为 UUID
basics.customFields[].icon string @phosphor-icons/web 图标名;空字符串表示隐藏。不确定时默认填 ''
basics.customFields[].text string 显示文本
basics.customFields[].link string 默认 "" 若该字段是链接,填写目标 URL

注意 websitebasics 层是导出的 websiteSchema(仅 url + label),而节区条目里的 websiteitemWebsiteSchema,额外多了 inlineLink 布尔字段(为 true 时 URL 渲染在标题上而非底部单独一行),且带 catch({ url: "", label: "", inlineLink: false }) 兜底——缺失或非法时自动降级为空值而非校验失败。

summary:摘要节

对应 summarySchema

路径 类型 必需 约束与默认值 说明
summary.title string 节标题
summary.icon string 默认 "" Phosphor 图标名;"" 使用默认图标,'none' 隐藏
summary.columns integer 最小 1,最大 6,默认 1 跨列数
summary.hidden boolean 是否隐藏该节
summary.keepTogether boolean 默认 false true 时整节保持在同一页,不跨页拆分
summary.startOnNewPage boolean 默认 false true 时该节强制从新页开始
summary.content string HTML 富文本内容

sections:12 种内置节区的统一骨架

sections 是一个固定键的对象,包含 12 个节区profilesexperienceeducationprojectsskillslanguagesinterestsawardscertificationspublicationsvolunteerreferences。源码中它们由 itemSection 工厂函数 统一生成,因此每个节区共享同一组骨架字段(baseSectionSchema):

路径(以 sections.experience 为例) 类型 必需 约束与默认值 说明
.title string 节标题
.icon string 默认 "" Phosphor 图标名;"" 用默认节图标,'none' 隐藏
.columns integer 最小 1,最大 6,默认 1 跨列数
.hidden boolean 是否隐藏该节
.keepTogether boolean 默认 false 保持在单页内,不跨页拆分
.startOnNewPage boolean 默认 false 强制从新页开始
.items array 条目数组,结构由节区类型决定
.items[].id string 条目唯一标识,通常为 UUID
.items[].hidden boolean 是否隐藏该条目

所有条目都以 baseItemSchemaid + hidden)为基类扩展。default.ts 中为每个节区预设了默认图标(profilesmessenger-logoexperiencebriefcaseeducationgraduation-cap 等,见 defaultResumeData)。

下面给出各节区条目(items[])的类型专属字段。

sections.profiles.items[](社交/平台主页)

对应 profileItemSchema

字段 类型 必需 约束与默认值 说明
icon string Phosphor 图标名,空字符串隐藏
iconColor string 默认 "" 图标颜色,rgba(r, g, b, a);留空用模板默认色
network string minLength: 1 平台名称,如 LinkedIn、GitHub
username string 该平台上的用户名
website object 默认 {"url":"","label":"","inlineLink":false} 主页链接
website.url / website.label string URL(需带协议)/显示文本
website.inlineLink boolean 默认 false true 时 URL 作为标题超链接渲染

sections.experience.items[](工作经历,含多职位 roles

对应 experienceItemSchema

字段 类型 必需 约束与默认值 说明
company string minLength: 1 公司/组织名称
position string 职位;单职位时填写;若使用 roles 则作为总括标题或留空
location string 公司所在地
period string 任职总时段;使用 roles 时应为整体任期
website object 默认 {"url":"","label":"","inlineLink":false} 公司网站
description string HTML 描述
roles array 默认 [] 该公司下的多个职位,用于展示晋升轨迹
roles[].id string 职位唯一标识,UUID
roles[].position string 该职位头衔
roles[].period string 该职位的时段
roles[].description string 该职位的 HTML 描述

sections.education.items[](教育背景)

对应 educationItemSchema

字段 类型 必需 约束与默认值 说明
school string minLength: 1 学校/机构名称
degree string 学位或资质
area string 专业方向
grade string 成绩/绩点(可留空字符串)
location string 学校所在地
period string 就读时段
website object 默认 {"url":"","label":"","inlineLink":false} 学校网站
description string HTML 描述

sections.projects.items[](项目)

对应 projectItemSchemaname(string,必需,minLength 1)、period(string,必需)、website(可选,默认空值对象)、description(string,必需,HTML)。

sections.skills.items[](技能)

对应 skillItemSchema

字段 类型 必需 约束与默认值 说明
icon string Phosphor 图标名,空字符串隐藏
iconColor string 默认 "" 图标颜色,rgba(r, g, b, a)
name string minLength: 1 技能名称
proficiency string 熟练度文本,如 'Beginner'、'Intermediate'、'Advanced'
level number 最小 0,最大 5,默认 0 0–5 数值等级;为 0 时隐藏等级图标
keywords array<string> 默认 [] 以标签形式显示在名称下方

sections.languages.items[](语言)

对应 languageItemSchemalanguage(string,必需,minLength 1)、fluency(string,必需,任意文本如 'Native'/'Fluent',也支持 CEFR 等级 A1–C2)、level(number,0–5,默认 0,0 时隐藏等级图标)。

sections.interests.items[](兴趣)

对应 interestItemSchemaicon(string,必需)、iconColor(可选,默认 "")、name(string,必需,minLength 1)、keywords(string 数组,默认 [])。

sections.awards.items[](奖项)

对应 awardItemSchematitle(必需,minLength 1)、awarder(颁奖方)、date(获奖日期,字符串)、website(可选)、description(HTML)。

sections.certifications.items[](认证)

对应 certificationItemSchematitle(必需,minLength 1)、issuer(颁发机构)、date(获得日期)、website(可选)、description(HTML)。

sections.publications.items[](出版物)

对应 publicationItemSchematitle(必需,minLength 1)、publisher(出版方)、date(发表日期)、website(可选)、description(HTML)。

sections.volunteer.items[](志愿活动)

对应 volunteerItemSchemaorganization(必需,minLength 1)、locationperiodwebsite(可选)、description(HTML)。

sections.references.items[](推荐人)

对应 referenceItemSchemaname(必需,minLength 1,可写 'Available upon request' 之类的说明)、positionwebsite(可选,可为 LinkedIn 主页)、phone(必需,字符串,可留空)、description(可放引语/推荐信摘要,HTML)。

customSections:按 type 判别的 14 种自定义节区

customSections 是数组,每个元素是判别联合type 字段决定使用哪套条目 schema。schema 文档给出的“代表必需形状”(representative required shape)汇总如下——每个变体都是“从 baseSectionSchema 扩展出 idtypeitems 的节区外壳 + 该类型专属的条目字段”:

customSections[] 变体 条目 schema 条目代表必需形状
summary summaryItemSchema { id, hidden, content }
profiles profileItemSchema { id, hidden, icon, network, username }
experience experienceItemSchema { id, hidden, company, position, location, period, description }
education educationItemSchema { id, hidden, school, degree, area, grade, location, period, description }
projects projectItemSchema { id, hidden, name, period, description }
skills skillItemSchema { id, hidden, icon, name, proficiency }
languages languageItemSchema { id, hidden, language, fluency }
interests interestItemSchema { id, hidden, icon, name }
awards awardItemSchema { id, hidden, title, awarder, date, description }
certifications certificationItemSchema { id, hidden, title, issuer, date, description }
publications publicationItemSchema { id, hidden, title, publisher, date, description }
volunteer volunteerItemSchema { id, hidden, organization, location, period, description }
references referenceItemSchema { id, hidden, name, position, phone, description }
cover-letter coverLetterItemSchema { id, hidden, recipient, content }

所有变体共有的节区外壳字段:title(string,必需)、icon(string,可选,默认 ""'none' 隐藏)、columns(integer,可选,1–6,默认 1)、hidden(boolean,必需)、keepTogether / startOnNewPage(boolean,可选,默认 false)、id(string,必需,通常为 UUID)、type(string,必需,决定使用哪套条目 schema 与表单字段)、items(array,必需,条目遵循该类型 schema)。

从源码结构看,这里的实现是 customSectionItemDefinitionByType 一张 type → { schemaName, schema } 的映射表,14 个类型逐一枚举(cover-letter 刻意排在 summary 之前,注释说明是为了保持重叠内容形状的既有优先级);随后 z.discriminatedUnion("type", ...) 把它编译成真正的判别联合。这意味着:

  • type 必须是 sectionTypeSchema 枚举中的 14 个值之一,写错会直接校验失败;
  • 条目 schema 均带 .catchall(z.any()),允许携带额外字段(例如前端状态字段),不会因未知键被拒绝——但核心必需字段仍强制存在;
  • cover-letter 是唯一天然属于“自定义节区”而非固定 sections 的类型:其条目字段为 recipient(收件人地址块,HTML:姓名、头衔、公司、地址、邮箱)与 content(正文,HTML:称呼、段落、结尾、签名),见 coverLetterItemSchema

一个典型的自定义节区实例(type 为 awards 的第二份奖项节):

{
  "id": "b2e3f4a1-7c9d-4e5f-8a6b-0c1d2e3f4a5b",
  "type": "awards",
  "title": "竞赛获奖",
  "icon": "",
  "columns": 1,
  "hidden": false,
  "keepTogether": false,
  "startOnNewPage": false,
  "items": [
    {
      "id": "c3d4e5f2-8d0e-4f6a-9b7c-1d2e3f4a5b6c",
      "hidden": false,
      "title": "全国大学生程序设计竞赛 二等奖",
      "awarder": "CCF",
      "date": "2024",
      "website": { "url": "", "label": "", "inlineLink": false },
      "description": "<p>带领 4 人团队完成算法与工程任务</p>"
    }
  ]
}

metadata:模板、布局、页面、设计与排版

metadatametadataSchema 的核心,控制简历的整体外观。

模板:metadata.template

字符串枚举,共 15 个取值,与 templates.ts 中的 templateSchema 一致,默认 onyx(Zod 侧 .catch("onyx") 兜底):

azurillbronzorchikoritaditgardittogengarglaliekakunalaprasleafishmeowthonyxpikachurhyhornscizor

metadata.layout:分栏与分页

对应 layoutSchema / pageLayoutSchema

路径 类型 必需 约束与默认值 说明
metadata.layout.sidebarWidth number 最小 10,最大 50,默认 35 侧栏宽度,占页宽的百分比
metadata.layout.pages array 页面布局列表
metadata.layout.pages[].fullWidth boolean true 时主栏占满全页宽,此时侧栏不应有任何条目
metadata.layout.pages[].main array<string> 主栏条目:节区 ID(experienceeducationprojectsskillslanguagesinterestsawardscertificationspublicationsvolunteerreferencesprofilessummary)或自定义节区的 UUID
metadata.layout.pages[].sidebar array<string> 侧栏条目,取值规则同 main

节区的显示顺序完全由 layout.pages 中的字符串数组决定sections 对象本身不携带顺序信息。默认布局(见 defaultResumeData)是单页:主栏依次排 profiles, summary, education, experience, projects, volunteer, references,侧栏排 skills, certifications, awards, languages, interests, publications。需要多页简历时,向 pages 追加新的页面对象,并用 startOnNewPage 控制节区翻页。

metadata.page:页边距、纸张与本地化

对应 pageSchema

路径 类型 必需 约束与默认值 说明
metadata.page.gapX number 最小 0 节区间水平间距(pt)
metadata.page.gapY number 最小 0 节区间垂直间距(pt)
metadata.page.marginX number 最小 0,最大 100,默认 14 水平页边距(pt)
metadata.page.marginY number 最小 0,最大 100,默认 12 垂直页边距(pt)
metadata.page.format string enum: a4 / letter / free-form,默认 a4 纸张格式
metadata.page.locale string 默认 "en-US" 语言区域,用于显示预翻译的节标题
metadata.page.hideLinkUnderline boolean 默认 false 是否隐藏链接下划线
metadata.page.hideIcons boolean 默认 false 是否隐藏条目级图标(skills、profiles、interests)
metadata.page.hideSectionIcons boolean 默认 true 是否隐藏节标题前的图标

注意 gapX/gapY 是必填项而 marginX/marginY 有默认值——生成 JSON 时容易遗漏前两者,最小可用值为 0

metadata.design:等级样式与配色

对应 levelDesignSchemacolorDesignSchema

路径 类型 必需 约束与默认值 说明
metadata.design.level.icon string Phosphor 图标名,typeicon 时生效
metadata.design.level.type string enum: hidden / circle / square / rectangle / rectangle-full / progress-bar / icon 技能/语言等级(level 0–5 数值)的视觉呈现方式
metadata.design.colors.primary string 主色,rgba(r, g, b, a)
metadata.design.colors.text string 文字色,通常为黑色 rgba(0, 0, 0, 1)
metadata.design.colors.background string 背景色,通常为白色 rgba(255, 255, 255, 1)

默认设计值(defaultResumeData):主色 rgba(220, 38, 38, 1)(红色),等级样式为 circle + star 图标。

metadata.typography:正文字体与标题字体

对应 typographySchemabodyheading 共享同一组字段结构:

路径(以 body 为例) 类型 必需 约束与默认值 说明
metadata.typography.body.fontFamily string 字体族名,必须是支持的简历字体
metadata.typography.body.fontWeights array enum: "100""900"(步长 100),默认 ["400"] 字重集合,不确定可用性时默认 400
metadata.typography.body.fontSize number 最小 6,最大 24,默认 11 字号(pt)
metadata.typography.body.lineHeight number 最小 0.5,最大 4,默认 1.5 行高倍数

heading 字段与之一致。默认排版(defaultResumeData):正文 IBM Plex Serif、字重 ["400","500"]、10pt;标题 IBM Plex Serif、字重 ["600"]、14pt;行高均 1.5。可用字体清单由 packages/fonts 包维护(Google Fonts 子集),技能文档中也要求“字体必须可用”。

metadata.notes / metadata.styleRules / metadata.stylesheet

路径 类型 必需 说明
metadata.notes string 作者私有备注,HTML 格式,不出现在简历输出中,仅编辑时可见
metadata.styleRules array 默认 []。结构化样式规则,按语义节区与槽位(slot)定向调整 React PDF 渲染
metadata.stylesheet object 语义样式表:mode(enum: legacy / semantic,必需)+ source(必需:languageVersion 整数、text 字符串)

styleRulesSchema 的实现 可以看到,styleRules 采用宽容解析策略:原始数组逐条尝试解析,未知键被丢弃、非法样式意图被过滤,全部无效时降级为空数组(.catch([])),保证导入历史数据不会因样式规则而失败。每条规则包含 idlabelenabledtargetglobal / 按 sectionType / 按 sectionId 三种作用域)与 slotssectionheadingitemtextlinkiconlevelrichParagraph 等语义槽位)。

默认值基线:defaultResumeData

packages/schema/src/resume/default.ts 导出的 defaultResumeData 是一份可直接作为“空简历”起点的完整对象,汇总了 schema 中所有 catch() 兜底值在实际产品中的取值:

{
  "picture": { "hidden": false, "url": "", "size": 80, "rotation": 0, "aspectRatio": 1, "borderRadius": 0, "borderColor": "rgba(0, 0, 0, 0.5)", "borderWidth": 0, "shadowColor": "rgba(0, 0, 0, 0.5)", "shadowWidth": 0 },
  "basics": { "name": "", "headline": "", "email": "", "phone": "", "location": "", "website": { "url": "", "label": "" }, "customFields": [] },
  "summary": { "title": "", "icon": "article", "columns": 1, "hidden": false, "keepTogether": false, "startOnNewPage": false, "content": "" },
  "sections": {
    "profiles": { "title": "", "icon": "messenger-logo", "columns": 1, "hidden": false, "keepTogether": false, "startOnNewPage": false, "items": [] },
    "experience": { "title": "", "icon": "briefcase", "columns": 1, "hidden": false, "keepTogether": false, "startOnNewPage": false, "items": [] }
  },
  "customSections": [],
  "metadata": {
    "template": "onyx",
    "layout": { "sidebarWidth": 35, "pages": [{ "fullWidth": false, "main": ["profiles", "summary", "education", "experience", "projects", "volunteer", "references"], "sidebar": ["skills", "certifications", "awards", "languages", "interests", "publications"] }] },
    "page": { "gapX": 4, "gapY": 6, "marginX": 14, "marginY": 12, "format": "a4", "locale": "en-US", "hideLinkUnderline": false, "hideIcons": false, "hideSectionIcons": true },
    "design": { "colors": { "primary": "rgba(220, 38, 38, 1)", "text": "rgba(0, 0, 0, 1)", "background": "rgba(255, 255, 255, 1)" }, "level": { "icon": "star", "type": "circle" } },
    "typography": { "body": { "fontFamily": "IBM Plex Serif", "fontWeights": ["400", "500"], "fontSize": 10, "lineHeight": 1.5 }, "heading": { "fontFamily": "IBM Plex Serif", "fontWeights": ["600"], "fontSize": 14, "lineHeight": 1.5 } },
    "notes": "",
    "styleRules": []
  }
}

(为可读性,sections 中仅展示两个节区;完整 12 个节区键均在 default.ts 中定义。)

这份默认值与 SKILL.md 中的最小结构示例 相互印证:技能要求所有条目 id 必须是合法 UUID、描述字段为 HTML 字符串、website 必须同时带 urllabel、颜色一律 rgba(r, g, b, a) 格式、字体须在可用字体范围内。

如何校验你生成的简历 JSON

结合仓库中的两条证据链,生成的 JSON 可以用以下方式验证:

  1. Zod 侧:直接调用 parseResumeData,它是 resumeDataSchema.parse 的封装,失败时抛出带路径信息的 Zod 错误。
  2. JSON Schema 侧:官方 schema 以 draft 2020-12 方言从服务的 /schema.json 端点提供(由 createResumeDataJsonSchema() 生成)。JSON Resume Schema 指南 给出了用 Ajv 2020 校验导出文件的示例,也说明了如何把导出的 *.json 简历文件在编辑器中关联该 schema 以获得自动补全;指南同时提醒:简历文档本身不含 version 字段,也不包含 schema 文档的 $schema 字段,应直接拿导出的简历对象对照规范 schema 校验。

一份合法的最小简历 = 上节默认值基线 + 真实 basics 内容 + 至少一个填入 items 的节区 + layout.pages 中引用这些节区 ID。

小结

schema 参考文档 以“必需顶层字段 → 判别联合变体 → 字段目录”三层结构,把 resumeDataSchema 的每个字段路径、类型、必需性、约束与描述完整展平;配合 defaultResumeData 的取值基线与 json-schema.ts 的转换实现,即可离线构造、校验和导入一份完整的 Reactive Resume 简历 JSON。由于该文档由 pnpm docs:gen 再生成,阅读源码(packages/schema/src/resume/)永远是理解字段语义的最终依据。

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