In Next.js App Router, create an opengraph-image.tsx file inside each dynamic route segment, load that route’s data, and return an ImageResponse that renders a reusable card design. The same pattern works for blog posts, products, and profiles; use a parent-level image for a shared default and a more-specific route image when a page needs its own.
How dynamic OG image routes work in Next.js
Next.js treats opengraph-image as a metadata file. Put it in a route segment and it supplies the Open Graph image for pages in that segment. A file in a more-specific segment takes precedence over one inherited from a parent segment. That lets you establish a site-wide default while generating tailored images from individual post, product, or profile data. See the Next.js metadata-file reference.
The Next.js guide’s blog example uses app/blog/[slug]/opengraph-image.tsx, obtains the post using its slug, and returns an image rendered from that data. The constructor allows JSX and CSS to produce dynamic images, as the Next.js documentation puts it: “The ImageResponse constructor allows you to generate dynamic images using JSX and CSS.” Its example returns a 1200 × 630 PNG.
Build a reusable image template for a blog post
This example assumes an application has a getPostBySlug data function. Replace that import and function with your own database or content-system lookup. The route’s params is awaited, matching current App Router conventions. A missing post returns a not-found response rather than generating a misleading card.
#1 Best Overall
// app/blog/[slug]/opengraph-image.tsx
import { ImageResponse } from 'next/og'
import { getPostBySlug } from '@/lib/posts'
export const alt = 'Blog post cover 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 getPostBySlug(slug)
if (!post) {
return new Response('Post not found', { status: 404 })
}
return new ImageResponse(
(
<div
style={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
padding: 72,
background: '#101827',
color: '#ffffff',
fontFamily: 'sans-serif',
}}
>
<div style={{ fontSize: 26, color: '#a5b4fc' }}>
{post.siteName}
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
<div style={{ fontSize: 64, fontWeight: 700, lineHeight: 1.1 }}>
{post.title}
</div>
<div style={{ fontSize: 28, color: '#cbd5e1' }}>
{post.authorName}
</div>
</div>
<div style={{ fontSize: 22, color: '#94a3b8' }}>
{post.category}
</div>
</div>
),
{ ...size },
)
}
Keep data lookup and template responsibilities separate: the route resolves the slug and retrieves fields, while the JSX defines the visual system. Add explicit fallbacks for optional fields, such as a missing author or category. Use the exported alt, size, and contentType metadata to describe the generated image and its dimensions and format.
Adapt the route-data pattern for products and profiles
For either content type, use a dynamic segment whose identifier resolves to one record, then feed selected fields into the same visual template. These are adaptations of the documented Next.js route-data pattern, not examples quoted from its guide.
Rank #2
Product route
For a route such as app/products/[slug]/opengraph-image.tsx, look up the product by slug. A useful card might show its name, a short descriptor, and brand. Decide deliberately whether price belongs on a share image: if prices vary by region or change frequently, stale cached images can mislead. Do not assume the image renderer will fetch and display an arbitrary remote product image without configuring that workflow.
User profile route
For app/users/[username]/opengraph-image.tsx, look up the profile by username and use fields such as display name, handle, and a short bio. Provide a stable fallback when a profile photo or optional bio is absent. Avoid placing sensitive or private profile fields in a publicly retrievable image.
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 →Rank #3
Use one template without making every card identical
Share a presentational component or helper for the common brand frame, typography, and spacing, while letting each route supply its own content and optional visual treatment. Keep selectors and layout rules simple enough for the image renderer’s CSS subset. Test long titles, missing photos, product variants, and special characters against the actual generated output.
ImageResponse constraints, format, and output size
ImageResponse uses @vercel/og, Satori, and Resvg to turn JSX and CSS into PNG. It supports common CSS features including flexbox, text wrapping, and custom fonts, but it is not a browser renderer with full CSS support. The Next.js guide identifies CSS Grid as an example of an advanced layout feature that is unsupported. Build cards with straightforward flex layouts and verify the rendered result rather than relying on browser-only styling assumptions.
Rank #4
The 1200 × 630 dimensions are the Next.js guide’s example, not a guarantee that every social platform will display every image identically. Next.js metadata image conventions also support JPG/JPEG, PNG, and GIF. Its documentation lists maximum file sizes of 8 MB for Open Graph images and 5 MB for Twitter images; treat these as Next.js documented limits, not universal platform guarantees. See the metadata-file reference.
Make data freshness and caching intentional
Generated metadata images are statically optimized by default. Next.js can make them dynamic when they use Dynamic APIs or uncached data. That behavior matters when a post title, product details, or profile data changes: a route that is served from a static or cached result may not immediately reflect an edit. The Next.js reference explains the default and dynamic conditions.
Best Value
- 1. Custom Nail art Tray: Show off your nails with our personalized nail art tray Photo Prop! This 4-inch disk is made of strong acrylic. It's great for anyone who loves nail art, works as a nail tech, or wants to promote their nail design. We laser engrave names and social media handles, then fill them with resin for a smooth look. Perfect for showing off your nails or promoting your nail business online.
- 2. Material: Crafted from 5mm thick, high-quality acrylic,it provides a comfortable and secure grip, making it easy to hold while displaying your nail art. The glossy, smooth acrylic surface offers a perfect backdrop for your designs.
- 3. Design: Sleek round acrylic disc with a cut-out notch for easy handling during photos.NOTE: Black will be prone to showing finger prints and dust/scratches easily.
- 4. Ideal for Social Media and Business Promotion: Consistent use of the nailfie disk builds a cohesive, professional brand image, setting you apart from the competition. Whether you're attracting new clients or showcasing your talent, the nail art display plate is essential for promoting your business online.
- 5. Perfect Gift for Nail Technicians: Personalized nail art tray disk is an ideal gift for any nail technician or artist.Whether for a friend, colleague, or even yourself, the nail art display plate is a gift that every nail professional will value and use frequently.
- For content that rarely changes, static generation can avoid repeated data work.
- For changing records, determine whether the lookup is cached and choose revalidation or dynamic behavior consistent with your data layer and freshness needs.
- For values that can change quickly, such as availability or price, avoid implying that a shared image is live unless its cache behavior actually guarantees that.
- Check the metadata image after changing route data; test the generated image endpoint as well as the page’s metadata output.
Cloudinary option for transformation-based workflows
If your project already uses Cloudinary or you prefer URL-based image transformations and delivery, Cloudinary documents helpers for both Next.js routers. For App Router metadata, it describes getCldOgImageUrl; for Pages Router, it documents CldOgImage. Its documented default output is 1200 × 627 pixels, a 1.91:1 ratio—not a universal social-platform rule. Refer to Cloudinary’s Next.js SDK Image Transformations and its Next.js SDK transformation and delivery documentation.
| Consideration | Next.js ImageResponse route | Cloudinary helpers |
|---|---|---|
| Integration | Framework-native route-segment metadata file in App Router. | getCldOgImageUrl for App Router metadata; CldOgImage for Pages Router. |
| Data flow | Route code loads the record and renders JSX from its fields. | Use the documented helpers within Cloudinary’s transformation and delivery workflow. |
| Layout needs | Suitable for branded cards that fit ImageResponse’s CSS subset. | Relevant when image transformations and delivery are already part of the stack. |
| Documented dimensions | Next.js guide example: 1200 × 630 PNG. | Cloudinary documented default: 1200 × 627, 1.91:1 ratio. |
Choose based on the framework route and data flow you want, the complexity of the visual layout, and whether Cloudinary already fits your transformation and delivery needs. The documentation cited here does not establish a general price, speed, or image-quality winner.
Or skip the browser setup
For a screenshot of a page rather than a designed card assembled from route data, ScreenshotNeo is a website screenshot API and MCP server. A single request returns an image or PDF; here is a cURL example using the documented endpoint. Replace the URL with the page you want to capture, and use your API key.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation. Cookie banners are accepted and removed before capture, along with known newsletter popups and chat widgets; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server lets AI agents use screenshot and PDF tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Sign up for free.
Recommended Free Tools
Frequently Asked Questions
Can I use an Open Graph image file for both a post and its individual route?
Yes. A route-segment image can serve that segment, and a more-specific image takes precedence when present.
Does ImageResponse render a full browser page?
No. It renders JSX and a supported subset of CSS into an image; it is not full browser CSS rendering.
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.

