og-images
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCreating Share Images for Next.js
为Next.js创建分享图片
Generate dynamic OpenGraph (1200x630) and Twitter (1200x600) images using ImageResponse.
next/og使用的ImageResponse生成动态OpenGraph(1200x630)和Twitter(1200x600)图片。
next/ogChoosing an Approach
选择实现方式
- File-based route (): Best for static pages with known titles at build time. Export
app/opengraph-image.tsx,runtime,alt,size, and a defaultcontentTypefunction.Image - API route (): Best for dynamic content (blog posts, CMS). Accept
app/api/og/route.tsxand/orslugas query params. Reference in metadata viatitle.generateMetadata()
Use for both approaches.
export const runtime = "edge"- 基于文件的路由():最适合构建时标题已知的静态页面。导出
app/opengraph-image.tsx、runtime、alt、size以及默认的contentType函数。Image - API路由():最适合动态内容(博客文章、CMS内容)。接受
app/api/og/route.tsx和/或slug作为查询参数。通过title在元数据中引用。generateMetadata()
两种方式都需使用。
export const runtime = "edge"File Naming Convention
文件命名规范
| File | Purpose | Dimensions |
|---|---|---|
| Facebook, LinkedIn, iMessage | 1200x630 |
| Twitter/X cards | 1200x600 |
| Dynamic API route | 1200x630 |
Place file-based routes in the relevant route directory (e.g., for ).
app/about/opengraph-image.tsx/about| 文件 | 用途 | 尺寸 |
|---|---|---|
| Facebook、LinkedIn、iMessage | 1200x630 |
| Twitter/X卡片 | 1200x600 |
| 动态API路由 | 1200x630 |
将基于文件的路由放在对应路由目录下(例如,对应页面)。
app/about/opengraph-image.tsx/aboutLayout Pattern
布局模式
- Use with
flexDirection: "column"to separate content from brandingjustifyContent: "space-between" - Title and subtitle (e.g., author name) go top-left in a stacked flex column
- Title: large, bold/medium weight, dark color
- Subtitle: same size or smaller, lighter weight, muted color (e.g., )
#888 - Keep text left-aligned with and constrain width with
textWrap: "balance"maxWidth - Use for tight, editorial feel at large sizes
letterSpacing: "-0.02em" - Padding: on all sides works well at 1200x630
48px
- 使用搭配
flexDirection: "column"将内容与品牌标识分离justifyContent: "space-between" - 标题和副标题(如作者名)放在左上角的堆叠flex列中
- 标题:大字号、加粗/中等字重、深色
- 副标题:字号相同或更小、更轻字重、柔和颜色(例如)
#888 - 使用保持文本左对齐,并通过
textWrap: "balance"限制宽度maxWidth - 大字号文本使用以营造紧凑的编辑风格
letterSpacing: "-0.02em" - 内边距:1200x630尺寸下,四边设置内边距效果良好
48px
Avatar / Logo (Optional)
头像/Logo(可选)
If the project has an avatar or logo, place it in the bottom-right corner using a flex container with . Load images via + , convert to base64 data URI for the . Use for circular avatars. Cache loaded assets in a to avoid refetching.
justifyContent: "flex-end"fetcharrayBuffersrcborderRadius: "50%"Map如果项目有头像或Logo,使用的flex容器将其放在右下角。通过 + 加载图片,转换为base64数据URI作为。圆形头像使用。将加载的资源缓存到中避免重复请求。
justifyContent: "flex-end"fetcharrayBuffersrcborderRadius: "50%"MapCustom Fonts
自定义字体
Load files from using . Pass the to via the option. Cache the font buffer after first load. Match the in the fonts config to the actual font file weight.
.ttfpublic/fonts/new URL("../../../public/fonts/YourFont.ttf", import.meta.url)ArrayBufferImageResponsefontsweight从加载文件,使用。通过选项将传递给。首次加载后缓存字体缓冲区。确保字体配置中的与实际字体文件的字重匹配。
public/fonts/.ttfnew URL("../../../public/fonts/YourFont.ttf", import.meta.url)fontsArrayBufferImageResponseweightTitle Case
标题大小写规则
If titles come from a CMS, apply smart title case:
- Lowercase small words (a, an, the, and, but, for, in, of, etc.) unless first or last
- Always capitalize brand names correctly (WordPress, JavaScript, GitHub, macOS, etc.)
- Uppercase known acronyms (AI, API, CSS, HTML, UI, UX)
- Handle hyphenated words by capitalizing each part independently
如果标题来自CMS,应用智能标题大小写:
- 小写虚词(a、an、the、and、but、for、in、of等),除非位于句首或句尾
- 品牌名称始终正确大写(WordPress、JavaScript、GitHub、macOS等)
- 已知缩写全部大写(AI、API、CSS、HTML、UI、UX)
- 连字符连接的单词,每个部分独立大写
Metadata Integration
元数据集成
Reference the OG route in :
generateMetadata()tsx
export function generateMetadata({ params }) {
return {
openGraph: {
images: [`/api/og?slug=${params.slug}`],
},
};
}For static pages, pass the title directly: .
/api/og?title=About在中引用OG路由:
generateMetadata()tsx
export function generateMetadata({ params }) {
return {
openGraph: {
images: [`/api/og?slug=${params.slug}`],
},
};
}对于静态页面,直接传递标题:。
/api/og?title=AboutSatori Rules
Satori规则
These are hard requirements of the rendering engine (Satori):
next/og- Every element needs — this is the only layout mode
display: "flex" - Inline styles only — no CSS classes, no external stylesheets, no CSS variables
- All text must be in elements with explicit style props
- Use hex colors — no ,
rgb(), or CSS variableshsl() - No on older versions — test before relying on it; fallback to margin
gap
这些是渲染引擎(Satori)的硬性要求:
next/og- 每个元素都需要—— 这是唯一的布局模式
display: "flex" - 仅支持内联样式 —— 不支持CSS类、外部样式表、CSS变量
- 所有文本必须放在带有显式style属性的元素中
- 使用十六进制颜色 —— 不支持、
rgb()或CSS变量hsl() - 旧版本不支持—— 使用前先测试;可回退使用margin
gap
Common Issues
常见问题
| Issue | Solution |
|---|---|
| Text not rendering | Add |
| Layout broken | Ensure all containers have |
| Colors wrong | Use hex colors, not CSS variables |
| Font not loading | Check the relative path from route file to |
| Image not showing | Convert to base64 data URI, don't use relative paths |
| 问题 | 解决方案 |
|---|---|
| 文本未渲染 | 为文本容器添加 |
| 布局错乱 | 确保所有容器都设置了 |
| 颜色显示错误 | 使用十六进制颜色,而非CSS变量 |
| 字体未加载 | 检查路由文件到 |
| 图片不显示 | 转换为base64数据URI,不要使用相对路径 |
Testing
测试
Preview during development by visiting the route directly in the browser:
http://localhost:3000/api/og?title=Hello+WorldAfter building, verify routes register as dynamic ( prefix) in the build output.
f开发期间可直接在浏览器访问路由预览:
http://localhost:3000/api/og?title=Hello+World构建完成后,验证路由在构建输出中注册为动态路由(前缀为)。
f