构建时生成 OG 图像的提示
AI 代理提示:在 Astro 或 Next.js 中使用 Satori 和 sharp 在构建时为每个页面生成 Open Graph 图像,无需外部服务。
CursorClaude CodeCodexWindsurf AstroNext.jsTypeScript
向您的代理提供此提示,以使用 Satori 和 sharp 在构建时为每个页面生成唯一的 OG 图像 PNG — 避免运行时 OG 图像服务(如 Vercel OG)的延迟和成本。
主要提示
You are working in an existing Astro 5 static site with TypeScript.
Task: generate a static Open Graph PNG image for every blog post at build time.
Requirements:- Install `satori` and `sharp`.- Create `src/lib/generate-og.ts` that exports `generateOgImage({ title, description }: OgData): Promise<Buffer>`. - Use Satori to render a JSX template (800 x 420 px) with: site name top-left, post title (large, bold, white), description (smaller, gray), a solid dark background (#0f172a). - Convert the Satori SVG output to PNG using `sharp(Buffer.from(svg)).png().toBuffer()`. - Use only system-safe fonts or load `src/fonts/Inter-Bold.ttf` (create a note to add the file).- Create `src/pages/og/[slug].png.ts` as an Astro endpoint: - `getStaticPaths`: call `getCollection('blog')` and return a path per post. - `GET`: call `generateOgImage` with the post's title and description, set `Content-Type: image/png`, return the buffer.- In the blog post layout, set `<meta property="og:image" content={ogImageUrl} />` where `ogImageUrl` is constructed as `/og/${post.slug}.png`.- Do NOT use `@vercel/og`, `next/og`, or any cloud image generation service.- Do NOT use Canvas or puppeteer.
Stop and list all planned file changes before writing any code.实现说明
- Satori 接受类 JSX 对象(React 元素语法),但不使用 React 运行时。直接通过
satori的第一个参数传递纯对象树。 - 字体加载:Satori 需要至少一种字体。在构建时使用
fs.readFileSync加载.ttf文件 — 这在 Astro 静态构建中没问题。 - 生成的 PNG 会位于
astro build后的dist/og/文件夹中。检查其大小;使用纯色背景时,800x420 的 PNG 应小于 100 KB。 - 如果是 Next.js 而非 Astro:在
app/og/[slug]/route.ts中使用路由处理程序,并用 PNG 缓冲区调用NextResponse。
预期文件更改
src/lib/generate-og.ts (new)src/pages/og/[slug].png.ts (new — Astro endpoint)src/layouts/BlogPost.astro (edited — add og:image meta)src/fonts/Inter-Bold.ttf (add manually — not auto-generated)package.json (edited — add satori, sharp)验收标准
astro build为每篇博客文章在dist/og/下生成一个.png文件。- 每个 PNG 为 800 x 420 像素。
- 博客文章布局包含指向正确路径
/og/<slug>.png的og:image。 - 在浏览器中打开 OG 图像 URL 会显示带有文章标题的样式卡片。
测试命令
bun add satori sharpbun run buildls dist/og/file dist/og/my-first-post.png # should output "PNG image data, 800 x 420"curl -I http://localhost:4321/og/my-first-post.png | grep content-type常见 AI 错误
- 导入 React 并尝试使用
ReactDOMServer渲染 — Satori 不使用 React 运行时。 - 忘记加载字体,导致 Satori 抛出
"No font found for the first character"。 - 将
og:image设置为相对路径如./og/slug.png— 在生产环境中必须是绝对 URL。 - 使用
canvas包,该包需要原生绑定,与许多 CI 环境不兼容。
修复提示
Satori throws a font error or the PNG is blank. Fix in order:1. Add font loading: `const fontData = fs.readFileSync('src/fonts/Inter-Bold.ttf'); fonts: [{ name: 'Inter', data: fontData, weight: 700 }]` in the satori call.2. Make sure the JSX-like element passed to satori is a plain object, not a JSX expression — call `satori(element, options)` directly.3. For the og:image meta tag, use an absolute URL: `const base = import.meta.env.SITE; ogImageUrl = new URL(\`/og/\${slug}.png\`, base).toString();`Show only the corrected diff.