Editorial OG Card
每篇文章获得一张一致的链接预览图。每张卡片包含:
- 顶部一条分隔线,带有引语(系列或板块)、主题和元信息行(阅读时间或日期),
- 大号衬线标题,以真实文本呈现,确保拼写正确,仅缩放到刚好适应,且包含一两个强调色单词,
- 署名(姓名首字母或照片)和文章 URL,
- 右侧艺术区:四种区块构图之一(根据文章的 slug 选择,确保每篇文章的卡片固定),用户选择的图片,或无,此时标题占据更宽的宽度。
一个脚本将文章读取为 cards.json,经您审核后,第二个脚本利用机器上已有的 Chrome 渲染每张卡片。无需安装其他组件。
所需条件
- Node.js 18 或更高版本。
- Chrome、Chromium 或 Edge。脚本会在常见位置自动查找;如果找不到,请设置
CHROME_PATH。 - 渲染时需要网络连接,以加载 Google Fonts 样式表(Instrument Serif、Inter、IBM Plex Mono)。如需离线渲染,请参阅“故障排除”部分。
本技能的文件夹为 <skill>(即本 SKILL.md 文件所在的文件夹)。
步骤
1. 创建 cards.json
从 Markdown 文章生成(支持 Astro、Hugo、Jekyll、Eleventy、Next.js MDX 等任何带有前置元数据的格式):
node <skill>/scripts/from-posts.mjs content/blog --site=yourblog.example --path=/blog/ --out-dir=public/og
该命令会读取指定文件夹下的所有 .md、.mdx 和 .markdown 文件,每篇文章生成一张卡片,按最新文章排列。标记为 draft: true 的文章会被跳过。从前置元数据中提取以下字段:
| 卡片字段 | 来源 |
|---|---|
slug | slug,否则 permalink,否则文件名(如果是 index.md 则为文件夹名),不含开头的日期 |
title | og_title,否则 title |
kicker | kicker,否则 series,否则 --kicker=...,否则 "Article" |
topic | topic,否则第一个 category,否则第一个标签 |
meta | reading_time,否则按 230 字/分钟计算字数,例如 "8 min read" |
author | author(文本,或其中的 name),否则 --author=... |
url | --site + --path + slug,显示在作者下方 |
out | <out-dir>/<slug>.png;如果不指定 --out-dir,则位于文章旁边,文件名为 <name>.og.png(如果是 index.md 则为 og.png) |
每次添加新文章后重新运行此命令:cards.json 中已有的卡片会保留您的编辑,新文章会被添加,已删除的文章会被移除。
手动创建,适用于非 Markdown 页面(如新闻稿、着陆页、文档章节):只需以相同的结构编写 JSON 文件:
{
"theme": { "paper": "#131313", "ink": "#f2ede4", "accent": "#ff7a45" },
"defaults": { "kicker": "Night Desk", "author": "Ines Varga" },
"cards": [
{
"slug": "issue-41",
"title": "Why every newsroom is quietly *rebuilding its CMS*",
"topic": "Issue 41",
"meta": "Oct 2026",
"url": "nightdesk.example/41",
"tags": ["#media", "№ 41"]
}
]
}
defaults 中的值会填充卡片中缺失的字段。
2. 编辑卡片
打开 cards.json 并审阅所有标题:
- 用
*星号*包裹一两个承载关键含义的单词;它们将以斜体显示并采用强调色。例如:"Shipping a design system *in a week*"。 - 标题最佳长度在 70 字符以内,上限为 110 字符。超过约 80 个字符时字体将缩小。可以通过文章前置元数据中的
og_title缩短标题,或直接在cards.json中修改。
卡片可包含的所有字段:
| 字段 | 含义 | 限制 |
|---|---|---|
title | 标题(必填) | 110 |
slug | 命名文件并选择布局(除非设置了 out,否则必填) | – |
out | PNG 文件的输出路径,相对于 cards.json(默认 og/<slug>.png) | – |
kicker | 左上角标签,使用强调色 | 24 |
topic | 引语后的文本;同时也是艺术区的默认话题标签 | 28 |
meta | 右上角:阅读时间、日期、期号 | 20 |
author | 署名名称;首字母显示在圆圈中 | 32 |
avatar | 用于圆圈的头像照片(路径或 URL),替代首字母 | – |
url | 显示在名称下方 | 48 |
art | blocks(默认)、image 或 none | – |
image | 当 "art": "image" 时的图片(路径或 URL);图片会被裁剪为 390×430 | – |
layout | 1 到 4,手动选择区块构图 | – |
tags | 艺术区上最多两个小标签,例如 ["#css", "Part 2"] | 每项 16 |
主题设置所有卡片的视觉风格:paper(背景色)、ink(文字色)和 accent(强调色,均为十六进制),以及用于其他 Google Fonts 字体的 serif、sans 和 mono。强调色直接用于区块;对于文字,卡片会将其加深或变亮,直到可读为止。提供两个初始主题:默认墨蓝色(#fafaf7、#17181c、#2433e8)和暗夜(#131313、#f2ede4、#ff7a45)。
3. 渲染
node <skill>/scripts/render.mjs cards.json
该命令首先检查所有卡片,一次性列出所有问题,然后四张一组进行渲染(每张约需一秒),并验证每张 PNG 是否为 1200×630。添加 --scale=2 可生成 2400×1260 的图像(在高密度屏幕上更清晰,文件大小约为两倍),或使用 --only=slug,slug 仅重新渲染部分卡片。
4. 查看
打开 og-preview.html(与 cards.json 在同一目录),可以看到所有卡片并排显示。检查标题是否过度缩小(如有则缩短标题)、强调词是否落在错误的短语上、相邻卡片是否看起来足够不同。可以通过修改卡片的 layout 字段选择其他构图。
5. 集成到网站
卡片只有在每页指向其图片的链接为绝对 URL 时才会在预览中显示。在页面的 <head> 中添加:
<meta
property="og:image"
content="https://yourblog.example/og/design-system-in-a-week.png"
/>
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="Shipping a design system in a week" />
<meta name="twitter:card" content="summary_large_image" />
只需在文章布局或模板中一次性添加,基于 slug 构建,无需逐篇文章处理:
- Next.js(App Router):在文章路由的
generateMetadata中返回openGraph: { images: [{ url:/og/${slug}.png, width: 1200, height: 630 }] }和twitter: { card: 'summary_large_image' },并在根布局中设置metadataBase,使 URL 变为绝对路径。 - Astro、Eleventy、Jekyll、Hugo:将标签添加到基础布局的 head 中,使用站点 URL 加
/og/加页面的 slug。 - 图片随文章存放(未使用
--out-dir):使用框架提供同路径文件的路径。
部署后,将文章 URL 粘贴到链接预览检查器,或 X、LinkedIn、Slack 的草稿中,即可查看卡片。平台会缓存预览;更改图片后可能需要一段时间才能显示。
6. 持续运行(可选)
要在每次构建时为新文章生成卡片,请将此技能的 scripts/ 和 template/ 文件夹复制到仓库中(例如 tools/og/),并在构建前依次运行两个脚本,例如在 package.json 中添加 prebuild 脚本:
"prebuild": "node tools/og/scripts/from-posts.mjs content/blog --site=yourblog.example --path=/blog/ --out-dir=public/og && node tools/og/scripts/render.mjs cards.json"
构建机器需要安装 Chrome;大多数 CI 镜像自带 Chrome,或者设置 CHROME_PATH。
故障排除
render: fix cards.json first:每一行会指出卡片、字段和限制。- 未找到 Chrome:安装 Chrome 或 Chromium,或者设置
CHROME_PATH指向可执行文件。 - 标题显示为普通衬线字体或标签显示为系统字体:Google Fonts 样式表未加载。如需离线渲染,请安装 Instrument Serif、Inter 和 IBM Plex Mono(均可从 Google Fonts 免费获取),并在主题中设置
"fonts": ""。"fonts"也可以设置为其他字体的样式表 URL。 - 平台预览显示旧图片或无图片:检查
og:imageURL 能否在浏览器中打开,并确保是绝对 URL(包含https://和您的域名),然后请平台重新抓取页面,或等待其缓存过期。
文件
scripts/from-posts.mjs:将前置元数据转换为cards.json,后续运行时保留用户的编辑。无依赖。scripts/render.mjs:检查cards.json、渲染 PNG 并生成og-preview.html。无依赖。scripts/chrome.mjs:查找 Chrome 并截图。template/:卡片本身。card.html和card.css为布局,card.js填充文本、选择可读颜色、绘制艺术区并适配标题。examples/field-notes/:一个小型博客(posts/)以及通过from-posts.mjs生成的cards.json,并添加了强调词。examples/night-desk/:一个为新闻稿手动编写的cards.json,暗色主题。Lookbk 上的预览即基于这两个示例渲染。NOTICE.md:本技能使用的字体和软件。