← Blog
Guide

OG Image Generation in 2026: The Complete Guide

April 2026 · 10 min read

Open Graph images (OG images) are the preview cards that appear when you share a URL on Twitter, LinkedIn, Slack, or Discord. A good OG image doubles click-through rates. A missing or generic one gets ignored. In 2026, there are five main approaches to generating them automatically — each with different trade-offs.

Why OG Images Matter More Than Ever

Social platforms now render OG images in more contexts than ever: link previews in DMs, cards in search results, embeds in productivity tools. With AI-generated content flooding feeds, a distinctive visual identity helps real content stand out. Developers and marketers who automate OG image generation for every page see measurable lift in social traffic — typically 40-80% more clicks compared to pages with no OG image.

Approach 1: Vercel OG (satori + resvg)

Vercel's @vercel/og package uses Satori to convert JSX into SVG, then resvg to render the SVG as a PNG. It runs in Edge Runtime and is extremely fast (under 100ms). The limitation is that it only supports a subset of CSS — no complex gradients, no arbitrary fonts without explicit loading, and layout is constrained to flexbox only.

// app/api/og/route.tsx (Next.js App Router)
import { ImageResponse } from 'next/og';

export const runtime = 'edge';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const title = searchParams.get('title') || 'My Page';

  return new ImageResponse(
    (
      <div style={{ display: 'flex', background: '#f0f9ff', width: '100%', height: '100%', padding: 60 }}>
        <h1 style={{ fontSize: 64, color: '#111' }}>{title}</h1>
      </div>
    ),
    { width: 1200, height: 630 }
  );
}

Best for: Next.js apps that want zero external dependencies and simple card layouts. Not great for complex designs or pixel-perfect brand consistency.

Approach 2: Canvas / Sharp on Node.js

Using the canvas npm package or Sharp with SVG templates gives you full design control on a Node.js server. You can draw arbitrary shapes, load any font, composite images, and produce exactly the design you want. The downside: canvas requires native binaries (node-canvas), which can be painful to deploy to serverless environments. Sharp is easier to deploy but requires SVG template management.

import sharp from 'sharp';

async function generateOG(title: string): Promise<Buffer> {
  const svg = `<svg width="1200" height="630" xmlns="http://www.w3.org/2000/svg">
    <rect width="1200" height="630" fill="#0f172a"/>
    <text x="60" y="300" font-family="sans-serif" font-size="64" fill="white">${title}</text>
  </svg>`;
  return sharp(Buffer.from(svg)).png().toBuffer();
}

Best for: complex designs that need pixel-perfect control and are deployed on long-running servers (not serverless).

Approach 3: Puppeteer / Playwright Screenshot

The classic approach: build a beautiful HTML template for your OG card, navigate to it with Puppeteer or Playwright, and screenshot it. This gives you full CSS/font/animation support and lets your design team own the template in HTML rather than code. The problem is infrastructure: running a browser is expensive, slow (cold starts), and hard to scale in serverless environments.

// The old way — expensive and painful
import puppeteer from 'puppeteer';

async function generateOG(url: string) {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.setViewport({ width: 1200, height: 630 });
  await page.goto(url, { waitUntil: 'networkidle0' });
  const buffer = await page.screenshot({ type: 'png' });
  await browser.close();
  return buffer;
}

Best for: local development or self-hosted servers with plenty of RAM. Not recommended for serverless or edge deployments.

Approach 4: Screenshot API (SnapAPI)

The modern alternative to running your own Puppeteer: use a screenshot API that handles the browser infrastructure for you. Build your OG template in plain HTML/CSS, host it on your domain, and call the API with the URL. You get full browser rendering (fonts, gradients, animations, any CSS) with none of the infrastructure headaches.

// Works from Next.js, Astro, Cloudflare Workers, Lambda, anywhere
async function generateOG(templateUrl: string): Promise<Buffer> {
  const params = new URLSearchParams({
    access_key: process.env.SNAPAPI_KEY!,
    url: templateUrl,
    format: 'png',
    width: '1200',
    height: '630',
  });
  const res = await fetch('https://api.snapapi.pics/v1/screenshot?' + params);
  return Buffer.from(await res.arrayBuffer());
}

Cache the result in KV, S3, or your CDN and you pay for generation only once per unique image. Best for: teams that want design flexibility without browser infrastructure. Works in any runtime including edge.

Approach 5: Pre-generated Static OG Images

For content-heavy sites where most pages don't change frequently, pre-generating OG images at build time is the most efficient approach. At build time, iterate over your content, call a screenshot API or canvas pipeline for each, and store the results as static files. Serve them directly from your CDN — zero runtime cost, maximum performance.

// astro.config.mjs — build hook
hooks: {
  'astro:build:done': async ({ pages }) => {
    for (const page of pages) {
      const url = 'https://yoursite.com' + page.pathname;
      const res = await fetch('https://api.snapapi.pics/v1/screenshot?access_key=KEY&url=' + encodeURIComponent(url) + '&width=1200&height=630&format=png');
      // Save to /dist/og/...
    }
  }
}

Comparison Table

ApproachDesign FlexibilityRuntimeCostComplexity
Vercel OGLimited (flex only)Edge/NodeFreeLow
Canvas/SharpFullNode onlyLowHigh
PuppeteerFullNode/DockerMediumVery High
Screenshot APIFullAnyLow ($0–$79/mo)Low
Static pre-genFullBuild onlyLowestMedium

Recommended Architecture for 2026

For most production apps, the sweet spot is a hybrid approach: use SnapAPI for dynamic OG images (user-generated content, personalized pages, real-time data), pre-generate static OG images for evergreen content at build time, and use Vercel OG only for ultra-simple text-only cards that don't need design flexibility.

Cache all generated OG images aggressively — 24 hours minimum, 7 days for stable content. Social crawlers only fetch OG images once per URL unless you explicitly request re-crawling. This means even on the free SnapAPI tier (200 captures/month), you can serve OG images for thousands of unique pages if they're cached properly.

Getting Started with SnapAPI for OG Images

Sign up at snapapi.pics — free tier, no credit card. Build an HTML template at /og-template on your site, call the API with the template URL and your dynamic parameters, cache the result. You'll have production-ready OG images for every page in under an hour.

OG Image Best Practices for 2026

Beyond the technical implementation, there are several design and operational best practices that separate high-performing OG images from generic ones.

Size and Format

The canonical OG image size is 1200x630 pixels. This aspect ratio (roughly 1.91:1) displays correctly on Twitter, LinkedIn, Facebook, and most Slack/Discord link unfurlers. Use PNG for images with text or sharp edges. Use WebP for photography-heavy cards where file size matters. Aim for under 300KB — many crawlers have download size limits and will skip large images.

Typography Rules

Keep the primary text large (60px+) and limit copy to 10 words or fewer on the card. Social platforms display OG images at varying sizes, often small thumbnails first. Your text must be legible at 400px wide. Avoid light gray text on white backgrounds — high contrast is essential. Use your brand's primary font and load it explicitly in your HTML template rather than relying on system fonts, which vary by OS.

Personalization Patterns

Dynamic OG images that include user names, company logos, or custom data drive significantly higher CTR than static images. Implement a URL-based template system: your OG image endpoint accepts query parameters like title, author, date, and category, and your HTML template renders them into the card design. SnapAPI screenshots the template URL and returns the personalized image. This approach is used by companies like Vercel, Linear, and Notion for their shared content previews.

Caching Strategy

Cache at multiple layers: CDN (CloudFront, Cloudflare) for serving, KV or Redis for generation results, and browser cache headers for the final image URL. Set Cache-Control: public, max-age=86400 as a minimum. For content that changes frequently (live sports scores, stock prices), reduce to 300-600 seconds. For evergreen content (blog posts, documentation), cache for 7-30 days. Social crawlers usually only fetch each URL once and cache aggressively on their end too.

Testing OG Images

Always test OG images before launch using these tools: Twitter Card Validator (cards-dev.twitter.com/validator), LinkedIn Post Inspector (linkedin.com/post-inspector), Facebook Sharing Debugger (developers.facebook.com/tools/debug). These tools show exactly how your card will render and will alert you to missing tags or format issues. Use OpenGraph.xyz for a quick preview without logging into any platform.

Meta Tag Setup

The minimum required meta tags for a complete OG implementation are: og:title, og:description, og:image, og:url, and twitter:card (set to summary_large_image for a wide card format). For the image tag, use an absolute URL including the protocol. If you're generating images dynamically, ensure the URL is stable and cacheable — avoid timestamps or random tokens in the image URL itself.

<meta property="og:title" content="Your Page Title" />
<meta property="og:description" content="Brief description under 200 chars" />
<meta property="og:image" content="https://yoursite.com/og/page-slug.png" />
<meta property="og:url" content="https://yoursite.com/page-slug" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="https://yoursite.com/og/page-slug.png" />

Getting Started

The fastest path to production OG images in 2026: build an HTML template route at /og-template on your site, integrate SnapAPI (free tier at snapapi.pics, 200 captures/month, no credit card), call the API with your template URL plus dynamic query params, cache the result in your CDN. Total implementation time: under an hour. The ROI in social traffic — measurable within the first week.