首页
/ Quick comparison

Quick comparison

2026-09-05 13:02:32作者:蔡丛锟

Quick comparison

Where Canva is a better fit

Where Reactive Resume is a better fit

Which should you choose?

Reactive Resume limitations in this comparison

Sources


其中竞品优势一节的标题必须形如 `## Where {竞品} is a better fit`(竞品名不能写成 Reactive Resume),这一条被整群验证脚本用正则强制检查。`Sources` 节列出第一手来源链接,并紧跟时效标记 `Last checked: July 28, 2026`;页面最后是唯一 CTA 卡片,例如 Canva 页的:

```mdx
<Card title="Try a resume-specific editor" icon="arrow-right" href="https://rxresu.me">
  Use structured resume sections and keep the option to export or self-host when you do not need a general design canvas.
</Card>

CTA 的 title 全集群不得重复。已发布的 Canva 对比页 完整体现了该契约:开头一句给出结论,Quick comparison 用六行表格对比主工作流、设计控制、导出、数据可携带性、部署方式与套餐边界,并在正文中嵌入指向 exporting-your-resume、license、Docker 自托管 的内部链接。

分批验证:每批交付后的固定动作

Step:Markdown lint(每批)。对当批文件运行 markdownlint-cli2,期望退出码 0:

pnpm exec markdownlint-cli2 \
  docs/comparisons/reactive-resume-vs-canva.mdx \
  docs/comparisons/reactive-resume-vs-adobe-express.mdx \
  docs/comparisons/reactive-resume-vs-overleaf.mdx

Step:批次内容契约断言(Task 1 示例)。用内联 Node 脚本检查每个文件是否包含全部必需小节、时效标记和 CTA 链接:

node - <<'NODE'
const fs = require("node:fs");
const files = [
  "docs/comparisons/reactive-resume-vs-canva.mdx",
  "docs/comparisons/reactive-resume-vs-adobe-express.mdx",
  "docs/comparisons/reactive-resume-vs-overleaf.mdx",
];
for (const file of files) {
  const text = fs.readFileSync(file, "utf8");
  for (const required of [
    "## Quick comparison",
    "## Where Reactive Resume is a better fit",
    "## Which should you choose?",
    "## Reactive Resume limitations in this comparison",
    "## Sources",
    "Last checked: July 28, 2026",
    'href="https://rxresu.me"',
  ]) {
    if (!text.includes(required)) throw new Error(`${file}: missing ${required}`);
  }
}
console.log("Task 1 content contract passed");
NODE

期望输出 Task 1 content contract passed。之后按批次提交(如 docs: compare Reactive Resume with design editorsdocs: compare mainstream resume builders 等),保证每个内容批次一个 commit。

各批次的「内容要求」同样写得很细,例如:

  • Task 2 要求保留关键产品边界差异:Resume.com 支持免费 PDF 与纯文本下载;MyPerfectResume、Resume-Now、Zety 的免费下载仅 TXT;Resume.io 当前仅其 Vancouver 模板可免费下载 PDF 加 TXT,其他模板/功能需付费流程——并且不得引用任何套餐价格。
  • Task 3 要求把一切 ATS/结果类表述视为厂商定位而非已证实结果;只有当官方页面明确文档化了 checker、分数、关键词定向流程或职位描述分析时,才可陈述该功能存在。
  • Task 4 要求只描述有文档依据的产品行为,不复述面试结果承诺、ATS 保证、评论评分或用户数量。

Task 5:导航接入与全量验证

插入导航组。在 docs/docs.json 的 Documentation tab 中、Use Cases 分组之后插入名为 Comparisons 的分组,页面顺序与文章批次对齐,且不新增 hub 页:

{
  "group": "Comparisons",
  "pages": [
    "comparisons/reactive-resume-vs-canva",
    "comparisons/reactive-resume-vs-adobe-express",
    "comparisons/reactive-resume-vs-overleaf",
    "comparisons/reactive-resume-vs-resume-com",
    "comparisons/reactive-resume-vs-myperfectresume",
    "comparisons/reactive-resume-vs-resume-now",
    "comparisons/reactive-resume-vs-resume-io",
    "comparisons/reactive-resume-vs-zety",
    "comparisons/reactive-resume-vs-kickresume",
    "comparisons/reactive-resume-vs-resumegemini",
    "comparisons/reactive-resume-vs-jobscan",
    "comparisons/reactive-resume-vs-resumod",
    "comparisons/reactive-resume-vs-rezi",
    "comparisons/reactive-resume-vs-careercircle",
    "comparisons/reactive-resume-vs-novoresume",
    "comparisons/reactive-resume-vs-livecareer",
    "comparisons/reactive-resume-vs-freesumes"
  ]
}

全量内容契约验证。这是计划中最核心的验证脚本:它同时校验 docs.json 的导航路径与顺序、每页 frontmatter 的 title/description 存在且全局唯一、七个必需片段存在、竞品优势小节存在且主语不是自己、CTA 标题全局唯一:

node - <<'NODE'
const fs = require("node:fs");

const paths = [
  "canva",
  "adobe-express",
  "overleaf",
  "resume-com",
  "myperfectresume",
  "resume-now",
  "resume-io",
  "zety",
  "kickresume",
  "resumegemini",
  "jobscan",
  "resumod",
  "rezi",
  "careercircle",
  "novoresume",
  "livecareer",
  "freesumes",
].map((slug) => `comparisons/reactive-resume-vs-${slug}`);

const config = JSON.parse(fs.readFileSync("docs/docs.json", "utf8"));
const docsTab = config.navigation.tabs.find((tab) => tab.tab === "Documentation");
const group = docsTab.groups.find((entry) => entry.group === "Comparisons");
if (!group) throw new Error("Missing Comparisons navigation group");
if (JSON.stringify(group.pages) !== JSON.stringify(paths)) {
  throw new Error("Comparison navigation paths or order do not match the approved set");
}

const titles = new Set();
const descriptions = new Set();
const ctas = new Set();

for (const pagePath of paths) {
  const file = `docs/${pagePath}.mdx`;
  const text = fs.readFileSync(file, "utf8");
  const frontmatter = text.match(/^---\n([\s\S]*?)\n---/);
  if (!frontmatter) throw new Error(`${file}: missing frontmatter`);

  const title = frontmatter[1].match(/^title: "(.+)"$/m)?.[1];
  const description = frontmatter[1].match(/^description: "(.+)"$/m)?.[1];
  if (!title || !description) throw new Error(`${file}: missing title or description`);
  if (titles.has(title)) throw new Error(`${file}: duplicate title`);
  if (descriptions.has(description)) throw new Error(`${file}: duplicate description`);
  titles.add(title);
  descriptions.add(description);

  for (const required of [
    "## Quick comparison",
    "## Where Reactive Resume is a better fit",
    "## Which should you choose?",
    "## Reactive Resume limitations in this comparison",
    "## Sources",
    "Last checked: July 28, 2026",
    'href="https://rxresu.me"',
  ]) {
    if (!text.includes(required)) throw new Error(`${file}: missing ${required}`);
  }

  const competitorFit = text.match(/^## Where (.+) is a better fit$/m)?.[1];
  if (!competitorFit || competitorFit === "Reactive Resume") {
    throw new Error(`${file}: missing competitor advantage section`);
  }

  const cta = text.match(/<Card title="([^"]+)"/)?.[1];
  if (!cta) throw new Error(`${file}: missing CTA title`);
  if (ctas.has(cta)) throw new Error(`${file}: duplicate CTA title`);
  ctas.add(cta);
}

console.log(`Validated ${paths.length} comparison pages`);
NODE

期望输出 Validated 17 comparison pages。注意导航断言假设 Comparisons 组位于 Documentation tab 的 groups 中,且 pages 数组顺序必须与批准集合完全一致——这是刻意设计,防止有人在补页面时悄悄改动顺序破坏锚点语义。

违禁语言扫描。用 ripgrep 检查营销与结果承诺词汇:

rg -n -i \
  '\b(best|winner|superior|revolutionary|seamless|guaranteed|guarantees|will pass|land an interview)\b' \
  docs/comparisons

期望零命中;若某个词只出现在官方来源标题里,要改写成中性的链接文案,而不是保留宣传性标题。

Markdown 与 Mintlify 链接校验

pnpm exec markdownlint-cli2 "docs/comparisons/*.mdx"

cd docs && pnpm dlx mint@4.2.748 broken-links --check-redirects
登录后查看全文
热门项目推荐
相关项目推荐