OpenGraph Images

Generate Social Preview Images at the Edge

OpenGraph Images

An `opengraph-image.tsx` file in `app/` generates dynamic OG images using JSX rendered to a PNG via `ImageResponse`.

4 min read Level 3/5 #nextjs#og#opengraph
What you'll learn
  • Add `opengraph-image.tsx`
  • Use `ImageResponse` from `next/og`
  • Combine with route params for per-page OG images

OG images are what social platforms show when someone shares your link. Generating them per page used to mean a headless browser; Next can do it with plain JSX rendered to a PNG on the Edge.

A Static OG Image

// app/opengraph-image.tsx
import { ImageResponse } from 'next/og'

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

export default function Image() {
  return new ImageResponse(
    (
      <div
        style={{
          fontSize: 80,
          background: 'white',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        My Site
      </div>
    ),
    size,
  )
}

Drop this file anywhere in app/. Next discovers it, generates the PNG, and links it from the matching page’s metadata automatically.

Per-Page OG With Params

// app/posts/[slug]/opengraph-image.tsx
import { ImageResponse } from 'next/og'

export const runtime = 'edge'
export const size = { width: 1200, height: 630 }

export default async function Image({ params }: { params: { slug: string } }) {
  const post = await db.post.findUnique({ where: { slug: params.slug } })
  return new ImageResponse(
    (
      <div style={{ fontSize: 60, padding: 80 }}>
        {post?.title ?? 'Post'}
      </div>
    ),
    size,
  )
}

ImageResponse understands a subset of CSS — flexbox, gradients, custom fonts, images. Twitter cards work the same way via a twitter-image.tsx sibling file.

Sitemap & robots.txt →