Open Graph & Dynamic OG Images
og:image) metadata. Next.js supports two ways to provide it: a static image file using a naming convention, or a dynamically generated image built at request time from a special route file.Static OG image via file convention
opengraph-image (with an extension like .png, .jpg, or .gif) into a route segment, and Next.js automatically picks it up and adds the right og:image meta tags — no metadata export needed.File | Effect |
|---|---|
| Default OG image for the whole site (used when a route doesn't define its own) |
| A static OG image scoped to every post under that route (rare, since posts usually want unique images) |
| Same convention, specifically for the Twitter/X card image |
Dynamic OG images with next/og
opengraph-image.tsx file that exports a default function returning an ImageResponse. Next.js renders it to an actual image at request time using JSX and CSS, similar to writing a small component.app/blog/[slug]/opengraph-image.tsx
import { ImageResponse } from 'next/og'
import { getPost } from '@/libs/posts'
export const size = { width: 1200, height: 630 }
export const contentType = 'image/png'
export default async function OGImage({
params,
}: {
params: { slug: string }
}) {
const post = await getPost(params.slug)
return new ImageResponse(
(
<div
style={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
padding: '80px',
background: '#0f172a',
color: 'white',
fontSize: 64,
fontWeight: 700,
}}
>
{post?.title ?? 'Untitled Post'}
</div>
),
{ ...size }
)
}size and contentType are optional but recommended — they let Next.js set accurate og:image:width/og:image:height tags without rendering the image first. Standard OG images are typically 1200×630.What the framework generates for you
<meta property="og:image"> and (for the dynamic case) a route that serves the generated image at a predictable URL — you don't write any of that wiring by hand, and you don't need to also set an images field inside a static metadata object when using either file convention.next/og's ImageResponse supports a constrained subset of CSS (mostly flexbox-based layouts) since it renders via Satori rather than a full browser engine. Keep OG image JSX simple: flex containers, text, background colors/images, and basic typography.A static
opengraph-image.{png,jpg,gif}file in a route segment is picked up automatically with no metadata export needed.A
opengraph-image.tsxfile exporting a function that returnsImageResponsefromnext/oggenerates a per-request image from JSX and CSS.Export
sizeandcontentTypealongside the dynamic image function so Next.js can set accurate dimension meta tags.Next.js injects the
og:imagemeta tags and serving route automatically for both approaches.Dynamic OG images are cached like other routes, so repeat shares of the same page don't re-render the image each time.