Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsiTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
To add an Open Graph (OG) image in a Next.js App Router project, place an opengraph-image.jpg, .jpeg, .png, or .gif file in the route segment that should own it. For route-specific or data-driven artwork, create an opengraph-image.tsx (or .js) file that returns an ImageResponse from next/og. Next.js then emits the corresponding og:image metadata automatically. The practical choice is simple: use a static file for authored, stable artwork; use a generated route when the title, author, price, or other page data must appear in the image.
This guide covers the App Router conventions documented for Next.js 16 (documentation updated February 27, 2026), including the promise-based image parameters introduced in that release.
How do I add an OG image in Next.js?
Next.js maps an image file convention to the route segment containing the file. A file in app/opengraph-image.png can serve as the site default, while app/blog/opengraph-image.jpg applies to the blog segment. A still deeper file wins over an ancestor image, so a route can override the site default without changing every page.
The metadata-file reference lists JPG/JPEG, PNG, and GIF for static Open Graph images. The maximum static OG file size is 8 MB; exceeding it causes the build to fail. The 1200 × 630 pixel dimensions shown in the current documentation are a useful design target and documented example, not a universal requirement imposed by every social network. See the official opengraph-image reference.
#1 Best Overall
Static file procedure
- Create or open the App Router segment, such as
app/,app/blog/, orapp/blog/[slug]/. - Add
opengraph-image.jpg,opengraph-image.jpeg,opengraph-image.png, oropengraph-image.gifto that directory. - Keep the file at or below 8 MB. Confirm that the artwork remains legible when displayed as a small social-card thumbnail.
- Build or run the application and inspect the page source for an
og:imagetag. Next.js supplies the image type, width, and height metadata when it can read those values from the file.
An optional sibling text file named opengraph-image.alt.txt supplies alternative text for the image. This is useful for metadata consumers that expose a description, although it does not replace meaningful text in the page itself.
Default image with route overrides
For a common pattern, put a general image at app/opengraph-image.png, then add a more specific file such as app/products/opengraph-image.jpg. Product pages under that segment use the product image; unrelated pages inherit the default. The App Router getting-started guide demonstrates this ancestor/descendant precedence: Metadata and OG images.
How do I generate a dynamic OG image in Next.js?
Create an opengraph-image.tsx, .ts, or .js route file and return an ImageResponse. The current documentation calls ImageResponse from next/og the easiest way to generate an image. It converts a JSX-like element and supported CSS through the @vercel/og, Satori, and Resvg pipeline into a PNG. A generated route can read route parameters and external data, making it suitable for article titles, user names, inventory values, or other page-specific content.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Working generated route for a static segment
Place this file at app/blog/opengraph-image.tsx:
import { ImageResponse } from 'next/og'
export const alt = 'A blog article preview'
export const size = { width: 1200, height: 630 }
export const contentType = 'image/png'
export default function Image() {
return new ImageResponse(
<div
style={{
background: '#111827',
color: 'white',
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
padding: '80px',
fontSize: 64,
}}
>
Your blog title
</div>
)
}
The separate alt, size, and contentType exports describe the generated asset to Next.js. The example uses 1200 × 630 and image/png, matching the current reference example. Verify available options against the Next.js version installed in your project; the API reference currently available for ImageResponse is the version 15 page at nextjs.org/docs/15/app/api-reference/functions/image-response.
Route parameters in Next.js 16
For app/blog/[slug]/opengraph-image.tsx, current documentation types params as a promise. Await it before loading route-specific content:
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
import { ImageResponse } from 'next/og'
type Props = {
params: Promise<{ slug: string }>
}
export const size = { width: 1200, height: 630 }
export const contentType = 'image/png'
export default async function Image({ params }: Props) {
const { slug } = await params
const post = await getPost(slug)
return new ImageResponse(
<div
style={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
background: 'white',
color: 'black',
padding: '72px',
}}
>
<div style={{ fontSize: 30 }}>{post.category}</div>
<div style={{ fontSize: sixty }}>{post.title}</div>
</div>
)
}
async function getPost(slug: string) {
// Replace with your database or CMS request.
return { category: 'Engineering', title: slug }
}
Replace the accidental placeholder value in a real implementation with a number (for example, 60):
<div style={{ fontSize: 60 }}>{post.title}</div>
Next.js 16 changed both the params passed to image generation and the id passed by generateImageMetadata to promises. If an older project gives you a plain object, follow that installed release’s types rather than copying a newer signature blindly.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →CSS and rendering limits
ImageResponse supports flexbox and only a subset of CSS. Advanced layouts such as CSS Grid do not work in the documented renderer. Prefer nested flex containers, explicit dimensions, simple colors, borders, and spacing. Test long titles, missing data, and non-Latin text because a layout that looks correct for one string can overflow when content changes. External fonts and images must be made available to the renderer in a way supported by your deployed environment; do not assume browser-only APIs are present.
Choosing static versus generated images
| Decision factor | Static file | Generated route |
|---|---|---|
| Content | One authored design reused by a segment | Unique title, author, price, or other data per route |
| Maintenance | Edit an image asset | Edit code and its data/template inputs |
| Data access | No data lookup | Can use route params and external data |
| Layout freedom | Any design your image editor can export | Only ImageResponse’s supported HTML/CSS subset |
| Failure risk | Oversized or unsupported file can fail the build | Runtime data, fonts, or unsupported CSS can break rendering |
| Output behavior | File is evaluated as metadata for the segment | Route is optimized and cached by default unless dynamic APIs, uncached data, or route configuration change that behavior |
There is no documented performance benchmark that makes one approach universally faster. Choose static when the image does not need page data. Choose generated when personalization or automation is worth the additional rendering and data dependencies.
Adding explicit metadata instead of the file convention
The file convention is usually the least error-prone option, but you can also return image metadata from a page’s metadata or generateMetadata export. The openGraph.images field accepts image URLs and can include dimensions and alt text:
Rank #3
import type { Metadata } from 'next'
export const metadata: Metadata = {
openGraph: {
images: [
{
url: 'https://example.com/social-card.png',
width: 1200,
height: 630,
alt: 'Example social card',
},
],
},
}
Use explicit metadata when the image is hosted elsewhere or when metadata is assembled alongside other page values. The metadata and generateMetadata APIs are supported only in Server Components; see the current generateMetadata reference. Avoid defining competing values accidentally: decide whether the segment’s convention file or explicit metadata should be authoritative.
Generating multiple OG variants with generateImageMetadata
When one segment needs several image variants, export generateImageMetadata. Each returned object requires an id; alt, size, and contentType are optional. The id is supplied to the image-generating function. The API was introduced in v13.3, and the current version history records the Next.js 16 promise change.
import { ImageResponse } from 'next/og'
export async function generateImageMetadata() {
return [
{ id: 'light', alt: 'Light social card' },
{ id: 'dark', alt: 'Dark social card' },
]
}
export default async function Image({
id,
}: {
id: Promise<string>
}) {
const variant = await id
const background = variant === 'dark' ? '#111827' : '#f9fafb'
const color = variant === 'dark' ? 'white' : '#111827'
return new ImageResponse(
<div style={{ display: 'flex', width: '100%', height: '100%', background, color }}>
{variant} variant
</div>
)
}
Check the generateImageMetadata reference for the exact signature used by your installed release.
Metadata, caching, and deployment checks
- Inspect generated HTML: confirm the final page contains an absolute
og:imageURL, not a development-only path. - Check response headers and status: a generated route must return an image response, not an exception page or HTML error.
- Account for caching: generated metadata routes are statically optimized and cached by default. Dynamic APIs, uncached fetches, or route configuration can opt the route into different behavior. If an image must change immediately after a database update, review the caching rules for that data request and your installed Next.js release.
- Keep files within limits: static OG images have an 8 MB limit. A
twitter-imagefile has a separate documented 5 MB limit; do not apply that number to Open Graph files. - Test production: social crawlers may request the image without your browser session, so verify authentication, redirects, cookies, and host allowlists do not block it.
Troubleshooting common failures
The build fails with an oversized image
Cause: the static file exceeds 8 MB. Re-export at a lower quality, reduce dimensions, remove unnecessary metadata, or switch to a generated route. Confirm the resulting file size before rebuilding.
The image route returns an error
Cause: unsupported CSS, a browser-only API, an unhandled data error, or a malformed JSX tree. Start with a plain flexbox container and hard-coded text, then add data and styling one piece at a time. Check server logs for the first thrown exception.
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
A dynamic title is missing
Cause: the route parameter was not awaited in a Next.js 16-style generator, or the data lookup returned no record. Type params and id as promises where the current docs require it, await them, and render a safe fallback for missing content.
Grid or familiar browser CSS does not render
Cause: ImageResponse implements a restricted CSS subset. Replace Grid, complex positioning, filters, and unsupported features with nested flex containers and explicit sizes.
The social platform shows an old card
Cause: the platform or an intermediary cached the image. Confirm the URL and response first, then use that platform’s documented card refresh mechanism. If your own route is cached, review static optimization and data-cache configuration rather than adding random delays.
Metadata exists but no preview appears
Cause: an inaccessible or relative URL, a redirect the crawler cannot follow, robots or authentication blocking the request, or invalid image bytes. Use an absolute public URL, fetch it without a logged-in browser, and verify the content type matches the generated output.
Previewing and validating the rendered page
You can validate the final page with browser developer tools or a crawler-friendly HTTP request. For repeatable checks across many URLs, ScreenshotNeo can capture the rendered page or an image preview. ScreenshotNeo is a website screenshot API and MCP server; its clean-shot pipeline accepts consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture. Only clean shots are billed, while bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are reported and cost nothing.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
Call ScreenshotNeo after deploying your page to inspect the OG presentation:
Best Value
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Replace the example URL with your page URL. The same endpoint supports PNG, JPEG, WebP, and PDF output; its response includes X-Page-Verdict and X-Billed headers so you can tell whether a clean shot was produced and billed. Documentation and the full option list are at ScreenshotNeo docs.
ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. It supports full-page capture, device presets, custom viewport and retina scale, waiting for selectors or network idle, custom CSS and JavaScript, hidden selectors, cookies and headers, request blocking, caching TTLs, signed links, webhooks, bulk capture, and usage reporting.
Recommended Free Tools
A free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan. Create a free ScreenshotNeo account.
Practical launch checklist
- Choose a static file or generator based on whether each route needs unique data.
- Use a 1200 × 630 design as the documented example, while checking the requirements of the platforms your audience uses.
- Keep static files below 8 MB and use one of the documented extensions.
- Export
size,contentType, andaltfor generated routes when appropriate. - Use flexbox and supported CSS only in ImageResponse.
- Await Next.js 16
paramsand variantidpromises. - Test production URLs without authentication and inspect the emitted metadata.
- Review caching when image content depends on changing external data.
Frequently Asked Questions
Can I use an SVG as an opengraph-image file?
The current static file convention lists JPG, JPEG, PNG, and GIF. Use one of those formats or return a supported generated response instead.
Does an OG image replace the page title or description?
No. It supplies the social image. Define the page’s title and description separately through metadata or generateMetadata.
Where should a shared default image live?
Place it in the highest App Router segment that should inherit it, commonly app/opengraph-image.png, then add files in deeper segments when those routes need overrides.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Why should I verify my installed Next.js version?
The current documentation records Next.js 16 promise-based params and variant ids, while API references can differ by release. Your project’s installed version determines the exact types and caching behavior.
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.

