satori

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Satori — HTML/CSS to SVG for OG Images

Satori — 用于生成OG图片的HTML/CSS转SVG工具

You are an expert in Satori and
@vercel/og
for generating dynamic Open Graph images.
你是Satori和
@vercel/og
生成动态Open Graph图片方面的专家。

Overview

概述

Satori converts JSX-like HTML and CSS into SVG.
@vercel/og
wraps Satori with an
ImageResponse
class that renders the SVG to PNG, designed to run in Vercel Edge Functions and other edge runtimes.
Satori 可将类JSX的HTML和CSS转换为SVG。
@vercel/og
通过
ImageResponse
类对Satori进行封装,能够将SVG渲染为PNG,专为在Vercel Edge Functions及其他边缘运行时环境中运行而设计。

Installation

安装

bash
undefined
bash
undefined

For Next.js projects (recommended — includes Satori + PNG rendering)

适用于Next.js项目(推荐——包含Satori + PNG渲染功能)

npm install @vercel/og
npm install @vercel/og

Standalone Satori (SVG output only)

独立版Satori(仅输出SVG)

npm install satori
undefined
npm install satori
undefined

Next.js App Router — OG Image Route (Recommended)

Next.js App Router — OG图片路由(推荐)

Next.js has built-in OG image support via the
ImageResponse
re-exported from
next/og
:
tsx
// app/og/route.tsx  OR  app/opengraph-image.tsx
import { ImageResponse } from 'next/og'

export const runtime = 'edge'

export async function GET(request: Request) {
  return new ImageResponse(
    (
      <div
        style={{
          display: 'flex',
          fontSize: 60,
          color: 'white',
          background: 'linear-gradient(to bottom, #1a1a2e, #16213e)',
          width: '100%',
          height: '100%',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        Hello, OG Image!
      </div>
    ),
    { width: 1200, height: 630 }
  )
}
Next.js 通过从
next/og
导出的
ImageResponse
提供内置的OG图片支持:
tsx
// app/og/route.tsx 或 app/opengraph-image.tsx
import { ImageResponse } from 'next/og'

export const runtime = 'edge'

export async function GET(request: Request) {
  return new ImageResponse(
    (
      <div
        style={{
          display: 'flex',
          fontSize: 60,
          color: 'white',
          background: 'linear-gradient(to bottom, #1a1a2e, #16213e)',
          width: '100%',
          height: '100%',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        Hello, OG Image!
      </div>
    ),
    { width: 1200, height: 630 }
  )
}

Convention-Based OG Images (Next.js 13.3+)

基于约定的OG图片(Next.js 13.3+)

Place an
opengraph-image.tsx
or
twitter-image.tsx
file in any route segment:
tsx
// app/blog/[slug]/opengraph-image.tsx
import { ImageResponse } from 'next/og'

export const alt = 'Blog post image'
export const size = { width: 1200, height: 630 }
export const contentType = 'image/png'
export const runtime = 'edge'

export default async function Image({ params }: { params: { slug: string } }) {
  const post = await getPost(params.slug)

  return new ImageResponse(
    (
      <div
        style={{
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          justifyContent: 'center',
          width: '100%',
          height: '100%',
          background: '#000',
          color: '#fff',
          fontSize: 48,
        }}
      >
        <div>{post.title}</div>
      </div>
    ),
    { ...size }
  )
}
Next.js auto-generates the
<meta property="og:image">
tag for these files.
在任意路由段中放置
opengraph-image.tsx
twitter-image.tsx
文件:
tsx
// app/blog/[slug]/opengraph-image.tsx
import { ImageResponse } from 'next/og'

export const alt = 'Blog post image'
export const size = { width: 1200, height: 630 }
export const contentType = 'image/png'
export const runtime = 'edge'

export default async function Image({ params }: { params: { slug: string } }) {
  const post = await getPost(params.slug)

  return new ImageResponse(
    (
      <div
        style={{
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          justifyContent: 'center',
          width: '100%',
          height: '100%',
          background: '#000',
          color: '#fff',
          fontSize: 48,
        }}
      >
        <div>{post.title}</div>
      </div>
    ),
    { ...size }
  )
}
Next.js 会自动为这些文件生成
<meta property="og:image">
标签。

Standalone Satori (SVG Only)

独立版Satori(仅生成SVG)

ts
import satori from 'satori'
import { readFileSync } from 'fs'

const svg = await satori(
  <div style={{ display: 'flex', color: 'black', fontSize: 40 }}>
    Hello from Satori
  </div>,
  {
    width: 1200,
    height: 630,
    fonts: [
      {
        name: 'Inter',
        data: readFileSync('./fonts/Inter-Regular.ttf'),
        weight: 400,
        style: 'normal',
      },
    ],
  }
)
ts
import satori from 'satori'
import { readFileSync } from 'fs'

const svg = await satori(
  <div style={{ display: 'flex', color: 'black', fontSize: 40 }}>
    Hello from Satori
  </div>,
  {
    width: 1200,
    height: 630,
    fonts: [
      {
        name: 'Inter',
        data: readFileSync('./fonts/Inter-Regular.ttf'),
        weight: 400,
        style: 'normal',
      },
    ],
  }
)

CSS Support and Limitations

CSS支持情况与限制

Satori uses a subset of CSS with Flexbox layout (Yoga engine):
Supported:
  • display: flex
    (default — all elements are flex containers)
  • Flexbox properties:
    flexDirection
    ,
    alignItems
    ,
    justifyContent
    ,
    flexWrap
    ,
    gap
  • Box model:
    width
    ,
    height
    ,
    padding
    ,
    margin
    ,
    border
    ,
    borderRadius
  • Typography:
    fontSize
    ,
    fontWeight
    ,
    fontFamily
    ,
    lineHeight
    ,
    letterSpacing
    ,
    textAlign
  • Colors:
    color
    ,
    background
    ,
    backgroundColor
    ,
    opacity
  • Backgrounds:
    backgroundImage
    (linear/radial gradients),
    backgroundClip
  • Shadows:
    boxShadow
    ,
    textShadow
  • Transforms:
    transform
    (basic transforms)
  • Overflow:
    overflow: hidden
  • Position:
    absolute
    ,
    relative
  • White space:
    whiteSpace
    ,
    wordBreak
    ,
    textOverflow
Not supported:
  • display: grid
    — use nested flex containers instead
  • CSS animations or transitions
  • position: fixed
    or
    sticky
  • Pseudo-elements (
    ::before
    ,
    ::after
    )
  • Media queries
  • CSS variables
Satori 使用CSS的子集搭配Flexbox布局(基于Yoga引擎):
支持的特性:
  • display: flex
    (默认——所有元素均为flex容器)
  • Flexbox属性:
    flexDirection
    alignItems
    justifyContent
    flexWrap
    gap
  • 盒模型:
    width
    height
    padding
    margin
    border
    borderRadius
  • 排版:
    fontSize
    fontWeight
    fontFamily
    lineHeight
    letterSpacing
    textAlign
  • 颜色:
    color
    background
    backgroundColor
    opacity
  • 背景:
    backgroundImage
    (线性/径向渐变)、
    backgroundClip
  • 阴影:
    boxShadow
    textShadow
  • 变换:
    transform
    (基础变换)
  • 溢出:
    overflow: hidden
  • 定位:
    absolute
    relative
  • 空白处理:
    whiteSpace
    wordBreak
    textOverflow
不支持的特性:
  • display: grid
    ——改用嵌套flex容器替代
  • CSS动画或过渡效果
  • position: fixed
    sticky
  • 伪元素(
    ::before
    ::after
  • 媒体查询
  • CSS变量

Fonts

字体

Fonts must be loaded explicitly — there are no default system fonts:
tsx
// Load font in edge runtime
const font = fetch(new URL('./Inter-Bold.ttf', import.meta.url)).then(
  (res) => res.arrayBuffer()
)

export async function GET() {
  const fontData = await font

  return new ImageResponse(
    (<div style={{ fontFamily: 'Inter' }}>Hello</div>),
    {
      width: 1200,
      height: 630,
      fonts: [{ name: 'Inter', data: fontData, weight: 700, style: 'normal' }],
    }
  )
}
For Google Fonts, fetch directly from the CDN or bundle the
.ttf
file.
必须显式加载字体——没有默认的系统字体可用:
tsx
// 在边缘运行时中加载字体
const font = fetch(new URL('./Inter-Bold.ttf', import.meta.url)).then(
  (res) => res.arrayBuffer()
)

export async function GET() {
  const fontData = await font

  return new ImageResponse(
    (<div style={{ fontFamily: 'Inter' }}>Hello</div>),
    {
      width: 1200,
      height: 630,
      fonts: [{ name: 'Inter', data: fontData, weight: 700, style: 'normal' }],
    }
  )
}
对于Google字体,可直接从CDN获取或打包
.ttf
文件。

Dynamic Content from URL Parameters

从URL参数获取动态内容

tsx
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const title = searchParams.get('title') ?? 'Default Title'

  return new ImageResponse(
    (<div style={{ display: 'flex', fontSize: 60 }}>{title}</div>),
    { width: 1200, height: 630 }
  )
}
tsx
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const title = searchParams.get('title') ?? 'Default Title'

  return new ImageResponse(
    (<div style={{ display: 'flex', fontSize: 60 }}>{title}</div>),
    { width: 1200, height: 630 }
  )
}

Images in OG

OG图片中的图片资源

Use
<img>
with absolute URLs:
tsx
<img
  src="https://example.com/avatar.png"
  width={100}
  height={100}
  style={{ borderRadius: '50%' }}
/>
For local images, convert to base64 or use absolute deployment URLs.
使用
<img>
标签并指定绝对URL:
tsx
<img
  src="https://example.com/avatar.png"
  width={100}
  height={100}
  style={{ borderRadius: '50%' }}
/>
对于本地图片,可转换为base64格式或使用绝对部署URL。

Key Patterns

核心实践模式

  1. Use
    next/og
    in Next.js projects
    — it re-exports
    ImageResponse
    with built-in optimizations
  2. Always set
    runtime = 'edge'
    — Satori and
    @vercel/og
    are designed for edge runtimes
  3. Use
    display: 'flex'
    everywhere
    — Satori defaults to flex layout, no block or grid support
  4. Load fonts explicitly — no system fonts are available; bundle
    .ttf
    /
    .woff
    files or fetch from CDN
  5. Standard OG dimensions are 1200×630 — this is the most widely supported size
  6. Use convention files for automatic
    <meta>
    tags
    opengraph-image.tsx
    and
    twitter-image.tsx
  7. Inline styles only — Satori does not support external CSS or CSS-in-JS libraries
  1. 在Next.js项目中使用
    next/og
    ——它重新导出了
    ImageResponse
    并附带内置优化
  2. 始终设置
    runtime = 'edge'
    ——Satori和
    @vercel/og
    专为边缘运行时设计
  3. 全程使用
    display: 'flex'
    ——Satori默认采用flex布局,不支持block或grid布局
  4. 显式加载字体——无系统字体可用;打包
    .ttf
    /
    .woff
    文件或从CDN获取
  5. 标准OG图片尺寸为1200×630——这是支持最广泛的尺寸
  6. 使用约定文件自动生成
    <meta>
    标签
    ——
    opengraph-image.tsx
    twitter-image.tsx
  7. 仅使用内联样式——Satori不支持外部CSS或CSS-in-JS库

Official Resources

官方资源