In the Next.js App Router, put an opengraph-image.tsx file in the route segment and render an image from that route’s data with ImageResponse. A reusable template can then produce a distinct social-sharing image for each blog post, product, or profile. The image is generated by the route, so the important design decisions are how you load its data, handle missing or unusually long content, and keep the result fresh when that data changes.
How dynamic OG images work in Next.js
Next.js recognizes metadata image files such as opengraph-image.tsx inside the App Router. The file can return an ImageResponse built from JSX and CSS. As the Next.js documentation puts it, “The ImageResponse constructor allows you to generate dynamic images using JSX and CSS.” The framework uses the image as Open Graph metadata for the route.
As an Amazon Associate I earn from qualifying purchases.
Place the file in a dynamic route segment, load the record identified by that route’s parameter, and pass its fields into a visual template. For example, app/blog/[slug]/opengraph-image.tsx can load the post associated with slug. A product route can use a product ID or slug in the same way, and a profile route can use a username. Those product and profile examples are applications of the route-data pattern, rather than examples specifically documented in the Next.js guide.
A more specific image in a child route segment takes precedence over an image defined in a parent segment. That lets you set a site-wide default and override it only for routes that need a dedicated design. Next.js documents a 1200 × 630 pixel PNG in its ImageResponse example; treat it as that documented example, not a guarantee about every social platform’s display or cropping.
#1 Best Overall
Choose the right rendering approach
Use ImageResponse for a framework-native template
This is a good fit when the design is straightforward, the data already lives in your application, and you want each route to own its metadata image. ImageResponse uses @vercel/og, Satori, and Resvg to turn JSX and CSS into a PNG. Its CSS support is a subset of browser CSS: flexbox and common styling patterns are useful, but do not assume a browser layout will render identically. The Next.js guide identifies CSS Grid as an example of an unsupported advanced layout feature.
You can use custom fonts and text wrapping, but keep the template resilient to long titles, missing images, and unusual characters. A simple layout with deliberate limits is generally easier to reason about than a browser-like composition with complex positioning.
Use Cloudinary when transformation workflows already fit your stack
Cloudinary documents getCldOgImageUrl for App Router metadata and CldOgImage for Pages Router. Its documented default output is 1200 × 627 pixels, a 1.91:1 ratio. That is Cloudinary’s stated default, not a universal social-platform requirement. Consider this route if your project already uses Cloudinary or you prefer defining and delivering images through its transformation workflow.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
The trade-off is not an established price, speed, or quality ranking. Instead, compare how each option fits your router, where your route data is available, how complex the design must be, and whether you want framework-rendered JSX or a managed transformation and delivery workflow.
Rank #2
Build a reusable App Router image template
This example uses a blog post with a title and category. Replace getPost with the data-access function used by your application; it returns the post for a slug or null if no post exists. The same pattern works for a product or profile by changing the data fields and template content.
import { ImageResponse } from 'next/og'
export const alt = 'Blog post social image'
export const size = { width: 1200, height: 630 }
export const contentType = 'image/png'
// Replace this example with your app's database or CMS lookup.
async function getPost(slug: string) {
const posts: Record<string, { title: string; category: string }> = {
'dynamic-og-images': {
title: 'How to Generate Dynamic OG Images',
category: 'Development',
},
}
return posts[slug] ?? null
}
export default async function Image({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
const post = await getPost(slug)
const title = post?.title ?? 'Article not found'
const category = post?.category ?? 'Blog'
return new ImageResponse(
(
<div
style={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
padding: '72px',
background: '#101827',
color: '#ffffff',
fontFamily: 'sans-serif',
}}
>
<div style={{ display: 'flex', fontSize: 28, color: '#9fb4d0' }}>
EXAMPLE SITE
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
<div style={{ display: 'flex', fontSize: 24, color: '#80d6c3' }}>
{category}
</div>
<div
style={{
display: 'flex',
fontSize: 64,
fontWeight: 700,
lineHeight: 1.1,
overflow: 'hidden',
}}
>
{title}
</div>
</div>
<div style={{ display: 'flex', fontSize: 22, color: '#9fb4d0' }}>
example.com
</div>
</div>
),
{ ...size },
)
}
Save it at app/blog/[slug]/opengraph-image.tsx. Next.js associates the generated image with that route’s metadata convention; you do not need to build a separate endpoint for every post. This example awaits params, as used by current App Router route examples. If your installed Next.js version types route parameters differently, use the parameter signature documented for that version.
Adapt the route data for products and profiles
- Products: load the product by route slug or ID. Useful fields might include its name, product category, and a short descriptor. Set explicit fallbacks for unavailable or unpublished records rather than assuming every route has a complete product object.
- Profiles: load by username and render the display name, role, or other public profile details. Treat the photo as optional: provide a designed fallback instead of allowing an absent image to break the response.
- Blog posts: load by slug and use the title and a category or site label. Long titles need a layout that remains legible when they wrap.
Keep the lookup focused on fields needed to render the image. If a route requires authenticated or personalized content, decide whether the generated image should expose that content before using it as public metadata.
Recommended Free Tools
Handle placement, formats, and freshness
Set route-level precedence intentionally
An image file in a route segment applies to that segment, and a more specific image in a child segment takes precedence over a parent segment’s image. A parent-level image can therefore serve as a default, while a dynamic route’s own file can generate per-record cards.
Rank #3
Know the documented image constraints
Next.js metadata image conventions support JPG/JPEG, PNG, and GIF. The Next.js metadata-files documentation lists maximum file sizes of 8 MB for Open Graph images and 5 MB for Twitter images. These are documented Next.js limits, not assurances that every receiving service accepts the same format or size.
Plan for caching and updates
Next.js generated images are statically optimized by default unless Dynamic APIs or uncached data make them dynamic. That can be desirable for stable content, but it matters when titles, product details, or profile information change: a cached image may not immediately reflect an updated record. Decide whether image data is stable enough to cache, and use the caching and revalidation behavior appropriate to the data-fetching path in your application. Do not assume that making a route parameter dynamic alone guarantees every downstream cache will refresh when a record changes.
Test the rendered card, not just the JSX
Before relying on the template across a site, inspect the actual generated image for representative records. In particular, check long titles, missing profile photos, product variants with different amounts of text, and names containing accents or other special characters. Confirm that the composition remains readable at the documented dimensions and that missing data produces a deliberate fallback.
Free tools Windows power users keep installed
One-click scans. No signup required.
Also check the route’s metadata output and generated image after changing source data. Since caching behavior depends on whether the image is statically optimized or uses dynamic or uncached data, testing a single initial render is not enough to validate freshness.
Rank #4
Or skip the browser setup
If you want a separate way to capture a rendered route while reviewing its appearance, ScreenshotNeo is a website screenshot API; it does not replace the Next.js metadata-image implementation above. Its API returns a screenshot or PDF from a URL. The following cURL request captures a page; it is useful as a page-capture step, not as code that generates the route’s OG image.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/blog/dynamic-og-images -o shot.webp
See the ScreenshotNeo API documentation for request options. ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are not billed. It also offers an MCP server for AI agents to take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Learn more at ScreenshotNeo, or sign up for the free plan.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Common implementation problems
The image shows fallback text for a valid route
Check that the route parameter matches the key your data lookup expects, and confirm the lookup returns the fields used by the JSX. A missing record in the example intentionally renders fallback text; replace that behavior with the not-found or unpublished-record handling appropriate to your application.
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 problemsThe image layout differs from the browser page
ImageResponse renders through Satori and Resvg rather than a full browser engine, and supports only a CSS subset. Simplify unsupported layout patterns, favor flexbox, and verify the result by inspecting the generated image.
An updated record still has an old image
Review whether the generated image is statically optimized or relies on dynamic APIs or uncached data. Then check the caching and revalidation settings on the route’s data path. The desired behavior depends on how often that record changes.
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.
A title or name is clipped
Test realistic longest values, allow text to wrap, and adjust font size or spacing so the design has room for variation. Avoid assuming every record will fit the dimensions demonstrated by a short sample title.
Frequently Asked Questions
Can I use one design for blog posts, products, and profiles?
Yes. Keep the visual template reusable and map each route’s data into it, with route-specific fields and fallbacks where needed.
Does a generated Open Graph image have to be 1200 × 630 pixels?
No universal platform requirement is established here. That is the dimension in the Next.js ImageResponse example; Cloudinary documents a different default of 1200 × 627 pixels.
Can I generate OG images in the Pages Router?
Cloudinary documents its Pages Router helper, CldOgImage. The route-segment opengraph-image.tsx approach described here is for the Next.js App Router.
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.




