To generate a route-specific Open Graph image in the Next.js App Router, add an opengraph-image.tsx file to the route segment and return an ImageResponse imported from next/og. Next.js uses the file convention to add the image metadata to the page head. This is useful when a share card needs route data—such as a post title—instead of a hand-maintained image. For an image that never changes with application data, a static image file is simpler.
The current App Router guide and file-convention reference were updated February 27, 2026. The detailed API limits cited below come from the Next.js 15 reference, updated June 16, 2025, so check them against the version installed in your project.
As an Amazon Associate I earn from qualifying purchases.
Choose a static image or a generated image
Next.js supports both ordinary image files and code-generated images for Open Graph metadata. A static opengraph-image.jpg, .png, or .gif is appropriate when the same designed asset works for every page in that route segment. Use opengraph-image.js, .ts, or .tsx when the image must be rendered from JSX or include route-specific data.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →A more specific route-segment image takes precedence over an image in a higher-level segment. That lets a site provide a general share image and override it for a section or individual route. See the Next.js opengraph-image file convention and the Metadata and OG images guide.
#1 Best Overall
How do I generate dynamic Open Graph images in Next.js?
Create the metadata file in the route segment that should own the image. The default-exported function returns an ImageResponse; its JSX describes the image content, and the response options set the dimensions. In the current file-convention example, route parameters are promises, so the function awaits them before loading route data.
import { ImageResponse } from 'next/og'
export const alt = 'A concise description of the share image'
export const size = { width: 1200, height: 630 }
export const contentType = 'image/png'
export default async function Image({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params
const post = await getPost(slug)
return new ImageResponse(
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
{post.title}
</div>,
{ ...size }
)
}
getPost is application-specific; Next.js does not provide it. Replace it with the data access used by your application, and check the parameter signature against your installed Next.js version. The file-convention documentation shows promise-based params, while older framework releases may use a different signature.
Rank #2
What do the metadata exports control?
Export alt, size, and contentType from the image file to describe the generated asset. In the example, the declared size is 1200 × 630 pixels and the MIME type is image/png; these exports map to Open Graph image metadata, including alternative text, dimensions, and content type. The file-convention reference documents these exports and the allowed return types, which include a Blob, ArrayBuffer, typed array, DataView, readable stream, or Response. ImageResponse satisfies the documented return type.
How do I use ImageResponse from next/og?
ImageResponse renders JSX and CSS into a PNG using @vercel/og, Satori, and Resvg. Its styling support is deliberately narrower than a browser’s: flexbox and a subset of CSS are supported, but CSS Grid is not. Design the card with supported properties rather than assuming any browser layout will render correctly.
Rank #3
The Next.js 15 API reference documents a maximum bundle size of 500 KB, counting JSX, CSS, fonts, images, and other assets together. It supports TTF, OTF, and WOFF fonts; the reference recommends TTF or OTF for parsing speed. Fonts are supplied as data with a family name, weight, and style. The API options also document width and height (defaults of 1200 and 630), emoji selection, custom fonts, a debug option, and HTTP response settings such as status and headers. Consult the ImageResponse API reference for the exact options available in your release.
Account for caching and changing content
Generated images under the metadata file convention are statically optimized by default. The convention documentation qualifies this behavior: Dynamic APIs or uncached data can affect whether the route is static. If the image includes content that changes after a build, decide whether a statically optimized result fits its lifecycle and configure data access and route behavior accordingly. Do not assume that adding an asynchronous data lookup alone guarantees a fresh image on every request; follow the caching behavior of the data source and the installed Next.js version. The file-convention reference describes the convention’s caching behavior.
Rank #4
Check the import against your Next.js version
Use import { ImageResponse } from 'next/og' for the current documented pattern. The API version history records that ImageResponse moved from next/server to next/og in Next.js 14; it was available from next/server in v13.3, after its introduction in v13.0 via @vercel/og. The API reference and the Next.js 13.3 announcement provide the version history. Match both the import and route-parameter type to the version your app actually uses.
Quick Recap
Best Value
Validate the generated share card
- Confirm the file is in the route segment whose pages should use the image, and check whether a more specific image file overrides it.
- Verify that the rendered content uses supported CSS and that the total bundle remains within the API reference’s documented limit for your version.
- Check the declared dimensions, MIME type, and alternative text against the image the function returns.
- Test the result with the route’s real data and caching behavior, particularly if titles or other image content can change after deployment.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




