Communitygithub.com

timerise-ai/blog-markdown

Agent 技能:在 Next.js App Router 中构建一个基于文件的多语言 Markdown 博客——按地区划分文章、通过共享 translationKey 关联不同语言的 slug、基于 slug 的标签页面、相关文章、封面图、RSS、站点地图、hreflang、CI 内容校验——无需 CMS。

blog-markdown 是什么?

本技能指导 AI 代理如何在 Next.js App Router 中构建一个完全基于 Markdown 文件的多语言博客。其核心设计理念是:**一篇博文的身份由 `translationKey` 决定,而非其 slug 或 URL**。slug 是可以本地化的,用于 SEO;而 `translationKey` 将不同语言版本的文件关联为同一篇文章,从而驱动 hreflang、语言切换器、相关文章以及跨语言重定向。该技能详细阐述了从内容模型定义(frontmatter 结构)、文件加载(带缓存和 YAML 异常回退解析)、多语言路由与 i18n、标签系统(基于 slug 而非标签名聚合),到页面生成、元数据、JSON-LD、站点地图和 RSS Feed 的完整架构。它特别强调了一些关键事实和硬性规则,例如:永远不要基于 slug 进行跨语言查找;相关文章仅在默认语言中编写一次,通过 translationKey 自动映射到所有语言;以及必须对 `gray-matter` 的缓存失败和 YAML 解析错误进行处理。该技能支持 Claude Code、Cursor 和 Codex 等代理平台,旨在让 AI 代理能够根据详尽的技术参考文档(如 content-model.md、content-loader.md、tags.md 等),一步步生成或复制这一经过实战验证的模块。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add timerise-ai/blog-markdown

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Markdown 博客(多语言,带标签)

一个内容为文件而非数据库行的博客。整个设计围绕一个核心理念: 博文的身份是它的 translationKey,而不是它的 slug。 Slug 是为 SEO 而本地化的,不同语言各不相同;而 translationKey 将三个文件关联为一篇文章,并驱动 hreflang、语言切换器、相关文章和跨语言重定向。只要这个字段设置正确,其他所有事情都只是查找。

由已成功交付此模块的工程师编写。它此前被审计对照的早期实现是一个多语言、静态生成的营销博客,包含其站点地图和 SEO 表面。以下的事实和规则是内容层套件和构建过程所验证的;references/provenance.md 中有记录。

何时使用

  • 内容以 Markdown 形式存储在仓库中,随应用一起部署
  • 不止一种语言,且不同语言拥有不同的 slug
  • 涉及标签页面、相关文章、Feed 或 hreflang
  • 你希望整个博客在构建时完全静态生成

何时不应使用

以下情况应使用
托管 CMS 是真相源使用该 CMS 的 SDK;只保留 references/content-model.md
文档站点 / 帮助中心(分类、侧边栏、搜索)使用帮助中心技能——其导航模型不同
少于 10 篇文章的单语言博客直接内联使用 fs + gray-matter;本技能对此过于复杂
渲染用户提交的 Markdown使用带消毒的渲染器;参见 references/rendering.md 中的 XSS 说明

架构

content/blog/<locale>/<localized-slug>.md   # frontmatter + body
        |
        v
 parseFrontmatter  --YAML,在引号格式错误时回退到行解析器
        |
        v
   getAllPosts(locale)  <-- 生产环境中按语言记忆
        |
        +--> translationKey ----> 替代页 / hreflang / 语言切换
        +--> tags -> 标签 SLUG ---> 标签页面(slug 是身份,不是标签名)
        +--> related (EN slugs) -> 相关文章,带 EN 回退
        |
        v
  /blog   /blog/[slug]   /blog/tag/[slug]   sitemap.xml   feed.xml

关键事实

  1. 关联关系只在默认语言中编写一次,使用默认语言的 slug。 翻译后的文件可以完全省略 related 字段,但仍然能通过 translationKey 获得正确的相关文章,使每个翻译版本渲染出相同的相关文章区域。回退测试保障了这一点。
  2. 标签的身份是其 slug,而非标签名。 "AI Agents" 和 "AI agents" 的 slug 指向同一个 URL。按 slug 分组,并按 slug 匹配文章,这样每个拼写变体的文章都出现在同一个标签页面上。两个测试保障了这一点。
  3. gray-matter 会在双引号 YAML 标量包含原始引号字符时抛出异常——翻译摘录中的印刷体引号就会触发此问题。没有回退解析器,构建就会卡在单个文件上;逐行回退解析可以确保加载继续。已针对该库验证,并有测试覆盖。
  4. gray-matter 会将失败的解析缓存为空结果。 它在解析之前就会写入缓存条目,因此第二次及以后对同一文件的解析都会返回 {}——没有错误,也没有 frontmatter。始终调用 matter(contents, {});任何 options 对象都会跳过缓存。
  5. 如果不记忆化,每次页面加载的时间复杂度是 O(文章数 x 语言数)。 按语言记忆化,使每个内容文件在每次构建中只被读取一次;否则,在 generateMetadata 中解析替代页会导致 71 倍的文件读取放大(在早期实现中测量得到)。
  6. getPostSlugs 必须过滤 .md。 此过滤器防止将意外的 .DS_Store 文件读取为 .DS_Store.md 并导致 ENOENT 错误。有测试保障。
  7. 标签页面没有跨语言身份。 标签是每种语言的自由文本,因此语言切换器在标签 URL 上必须回退到博客首页,而不是构建一个会导致 404 的 URL。

硬性规则

永远不要基于 slug 进行跨语言查找。 Slug 是有意本地化的。 translationKey 是连接列;跨语言的 slug 匹配只是巧合,不是关系。

永远不要让 getPostBySlug 隐式决定草稿可见性。 在加载器中过滤草稿;dynamicParams = false 只是作为副作用隐藏草稿,一旦该标志改变就会失效。草稿测试保障了过滤功能。

永远不要渲染一个固定的 "5 分钟阅读"。 根据正文计算它;只需一次 split,阅读时间测试保障了它。

永远不要在读取时从标签名推导标签页的 URL,并在渲染时从 URL 推导标签名,而不进行冲突检查。 这种往返仅在每个标签名都唯一 slug 化时才是无损的。

快速开始

  1. 设置语言约定和 frontmatter 模式——content-model.md
  2. 构建加载器(记忆化、过滤 .md、带回退解析器)——content-loader.md
  3. 接入语言、替代页和跨语言重定向——i18n-and-routing.md
  4. 添加标签分组和标签页面——tags.md
  5. 构建三个路由、元数据和 JSON-LD——pages-and-seo.md
  6. 渲染正文和封面——rendering.md
  7. 添加验证脚本并阅读运维差距——operations.md
  8. 运行测试固件和测试——testing.md

要移植到现有应用?先填写 adaptation.md 中的接缝表——只需十分钟,可避免后续的重命名。

参考文档目录

场景触发关键词参考文档
Frontmatter 字段、草稿、翻译键、关联关系frontmatter, schema, translationKey, draft, related, excerptcontent-model.md
文件读取、缓存、YAML 失败、阅读时间gray-matter, fs, cache, memoize, ENOENT, YAMLException, parsecontent-loader.md
语言、hreflang、替代页、错误语言链接i18n, locale, hreflang, alternates, canonical, language switcher, redirecti18n-and-routing.md
标签 URL、冲突、稀疏标签页面tag, slug, diacritics, collision, tag page, taxonomytags.md
路由、元数据、JSON-LD、站点地图、RSSpage.tsx, generateStaticParams, generateMetadata, dynamicParams, sitemap, RSS, feed, BlogPostingpages-and-seo.md
Markdown 转 React、代码块、封面图片react-markdown, remark-gfm, syntax highlighting, cover, motif, accent, XSSrendering.md
内容验证、构建成本、编辑工作流validation, CI check, build time, drafts, authoring, operatoroperations.md
测试固件及通过的测试套件test, fixture, vitest, node:test, regression, asserttesting.md
适配到宿主应用:接缝、重命名、探测adapt, port, host, seam, rename, CMS, integrateadaptation.md
审计记录:与早期实现相比,哪些变更、保留、新增provenance, deviations, fidelity, audit, ledgerprovenance.md

相关技能