Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
In a Next.js App Router project, create an image route with ImageResponse from next/og, render a 1200 × 630-pixel card, deploy it, and set the resulting absolute URL as the page’s og:image. Vercel’s guide, last updated December 19, 2025, documents this approach for Next.js 12.2.3 or newer and Node.js 22 or newer. The code below shows a working starting point, followed by a dynamic version, metadata wiring, deployment checks, and the rendering limits to plan around. Vercel’s Open Graph image generation guide is the primary reference.
Generate a basic Open Graph image with Next.js
Use the App Router’s next/og integration to make a route that returns an image response. In a project using the App Router, the OG package is already included; you do not need to add @vercel/og separately for this example.
1. Add the route
Create app/api/og/route.tsx and add this handler:
import { ImageResponse } from 'next/og'
export async function GET() {
return new ImageResponse(
<div
style={{
display: 'flex',
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
background: 'white',
color: 'black',
fontSize: 64,
}}
>
Article title
</div>,
{ width: 1200, height: 630 },
)
}
The result is an image response at the route, typically reachable at /api/og. The explicit dimensions match Vercel’s recommended Open Graph canvas size, 1200 × 630 pixels. The @vercel/og API reference documents a 1200-by-630 default and PNG content type; setting dimensions explicitly makes the intended canvas clear in your handler.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 112. Test the route locally
Start the Next.js development server and open http://localhost:3000/api/og in a browser. You should see the generated card as an image. If the route returns an error rather than an image, check the terminal output and the rendering constraints below before wiring it into metadata.
#1 Best Overall
Make the image dynamic from a title
A parameterized API route suits cards whose content changes by request, such as a title-specific article card. Read the URL’s title parameter in the handler and insert it into JSX. The following example also imposes an application-level length cap and a fallback. Vercel’s example slices a title to 100 characters; that is example logic, not a universal platform limit.
import { ImageResponse } from 'next/og'
export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const rawTitle = searchParams.get('title') ?? 'Read the latest'
const title = rawTitle.slice(0, 100)
return new ImageResponse(
<div
style={{
display: 'flex',
width: '100%',
height: '100%',
flexDirection: 'column',
justifyContent: 'center',
padding: 72,
background: '#111827',
color: '#fff',
fontSize: 64,
fontWeight: 700,
}}
>
{title}
</div>,
{ width: 1200, height: 630 },
)
}
For production, do not assume a character limit alone makes untrusted input safe or visually suitable. Validate and constrain values according to your own route’s needs, and design for the possibility of long words, non-Latin text, or titles that occupy multiple lines. Query-string URLs must also be encoded correctly when placed into HTML metadata or constructed by a caller.
Rank #2
Connect the route to page metadata
The image route does not automatically make a social preview discoverable. The page’s metadata needs an og:image tag containing the route’s absolute, publicly reachable URL. After deployment, add or generate metadata for each relevant page. For example, the HTML emitted for a page should contain a tag like this, with your actual deployed host:
Free tools Windows power users keep installed
One-click scans. No signup required.
<meta property="og:image" content="https://example.com/api/og?title=Article%20title" />
In a Next.js application, the App Router metadata API can provide this value. Keep the image URL synchronized with the page’s actual title and canonical public route; a locally working relative path is not enough for a social crawler that fetches the deployed page from outside your machine.
Choose a route pattern
Vercel documents both parameterized API routes and Next.js convention-based files such as app/about/opengraph-image.jsx. Use the pattern that matches how the content varies rather than treating one as universally superior.
| Pattern | Good fit | What to expose in metadata |
|---|---|---|
| Parameterized API route | Many cards share a layout but receive different page data, such as a title passed as a query parameter. | The absolute deployed API route, including the encoded parameters needed for that card. |
opengraph-image route file |
A page or route group benefits from Next.js’s file convention for its OG image. | The publicly reachable image URL associated with that page, as emitted by the application. |
See Vercel’s OG image generation examples for both styles. A dedicated convention can keep page-specific assets close to their route; a parameterized handler can centralize a reusable card design. The right trade-off depends on whether content is static, generated from page data, or supplied through request parameters.
Rank #4
Design within the renderer’s limits
Vercel’s documented renderer uses Satori and Resvg to turn HTML/CSS into a PNG. It is not a full browser layout engine, so a design that relies on arbitrary browser CSS may fail or render differently than expected.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
- Layout: Flexbox and absolute positioning are supported; CSS Grid is not.
- CSS: Only a subset of properties is supported. Start with straightforward layout and styling, then consult the current Vercel guide for any property your design depends on.
- Fonts: TTF, OTF, and WOFF files are supported. Vercel recommends TTF or OTF for parsing speed.
- Bundle size: The documented maximum is 500 KB across JSX, CSS, fonts, images, and other assets. If the bundle exceeds it, reduce assets or fetch assets at runtime as appropriate.
- Assets: Vercel documents local file access through
fs.readFileand remote assets throughfetch. Ensure remote resources are reachable by the deployed function and handle unavailable assets in your route.
For a custom font or logo, check its size and format before adding it, and test the deployed route rather than relying only on a local preview. These constraints make simple, self-contained cards easier to maintain than designs assembled from large sets of assets or browser-only styling.
Best Value
Check runtime compatibility and deployment
The Vercel guide’s stated setup requirements are Node.js 22 or newer and Next.js 12.2.3 or newer. It says generation is supported on Node.js and notes the applicable route/runtime combinations for the return new Response(...) handler shape: Pages Router with Edge, App Router with Node.js, and App Router with Edge. That syntax is not supported for Pages Router with Node.js in the documented vercel/og combination. The sample in this article uses App Router and ImageResponse; if you use another router or response style, verify it against your framework configuration and the current guide.
- Confirm the project uses the App Router and meets the guide’s documented Next.js and Node.js versions.
- Run the image route locally and confirm it returns a visible card.
- Deploy the project to obtain a publicly reachable image URL.
- Set the page’s
og:imageto that absolute URL and check that the route can be fetched without a login or local-only network access. - Allow social crawlers to request the route in
robots.txt. Vercel’s example for this route shape isAllow: /api/og/*. - Use Vercel’s Open Graph preview tooling to inspect metadata before production.
Vercel’s API reference documents cache-control defaults of public, immutable, no-transform, max-age=31536000. That is a long-lived immutable policy at the documented API level, so changing the content while keeping a stable image URL can leave a previously generated or cached version in circulation. Consider versioning the image URL when content changes. The reference describes defaults; behavior can also depend on the deployment and external caching layers.
Troubleshoot common failures
| Symptom | Likely cause | What to check |
|---|---|---|
| The route errors during rendering. | Unsupported CSS, an unsupported asset/font format, a missing asset, or the bundle exceeding the documented limit. | Reduce the example to basic JSX and flex styles, inspect the function error, verify font formats, and reduce or fetch oversized assets at runtime. |
| The generated card looks different from the intended browser design. | The renderer supports a CSS subset rather than full browser layout, or the card depends on unsupported Grid. | Replace Grid with flex or absolute positioning and simplify styling to documented supported properties. |
| A crawler shows no image although the route works locally. | The metadata may use a relative or local URL, the deployed route may not be publicly reachable, or robots rules may block it. | Inspect the deployed page’s og:image, fetch its absolute URL publicly, and allow the OG route in robots.txt. |
| The preview still shows an old card. | The documented API cache default is immutable and long-lived, and a stable URL may be reused for changed content. | Use a distinct URL for changed image content and inspect the deployed metadata and preview again. |
| The handler fails with a particular router/runtime setup. | The documented support differs by Pages Router versus App Router and Node.js versus Edge. | Check the route/runtime matrix in Vercel’s current guide; the documented Response syntax does not cover Pages Router with Node.js for this combination. |
Or skip the browser setup
ScreenshotNeo does not generate an Open Graph card from your page data; it can capture the rendered page or deployed image route so you can inspect the result without configuring a browser automation script. For example, capture the generated image endpoint as a screenshot:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/api/og -o shot.webp
See the ScreenshotNeo API documentation for request options. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots, and the free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Learn about ScreenshotNeo, then sign up free for 1,000 screenshots a month with no card.
Frequently asked questions
Does a successful image route guarantee that every social platform will show the same preview?
No. The route and metadata checks confirm your implementation is fetchable and correctly wired; they do not establish identical rendering behavior across social platforms.
Should I add @vercel/og to an App Router project?
For the documented App Router pattern, use ImageResponse from next/og; Vercel says the necessary OG package is already included there.
Quick Recap
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.

