Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

In a Next.js App Router application, add an opengraph-image.tsx file to the route segment that owns the page, load that route’s data, and return an ImageResponse from next/og. Next.js then emits the Open Graph image metadata for that route. The example below generates a 1,200 × 630 PNG for each blog post, explains caching and CSS limits, and shows framework-independent options for other JavaScript deployments.

The recommended approach: Next.js App Router

Put the generator beside the page whose preview it represents. For a route such as app/blog/[slug]/page.tsx, create app/blog/[slug]/opengraph-image.tsx. Next.js recognizes this file convention, calls it with the route parameters, and adds the resulting image to the page metadata.

A complete route-specific generator

This example fetches a post by slug and draws a title, category, and site name. Replace the data function with your database or CMS call.

import { ImageResponse } from 'next/og'
import type { ReactElement } from 'react'

type Props = {
  params: Promise<{ slug: string }>
}

export const alt = 'Blog post preview'
export const size = { width: 1200, height: 630 }
export const contentType = 'image/png'

async function getPost(slug: string) {
  const response = await fetch(`https://example.com/api/posts/${encodeURIComponent(slug)}`)
  if (!response.ok) throw new Error('Post request failed')
  return response.json() as Promise<{
    title: string
    category?: string
  }>
}

export default async function OpenGraphImage({ params }: Props): Promise<Response> {
  const { slug } = await params
  const post = await getPost(slug)

  return new ImageResponse(
    (
      <div
        style={{
          width: '100%',
          height: '100%',
          display: 'flex',
          flexDirection: 'column',
          justifyContent: 'space-between',
          backgroundColor: '#101827',
          color: 'white',
          padding: '72px',
          fontFamily: 'Arial',
        }}
      >
        <div style={{ display: 'flex', fontSize: 30, color: '#93c5fd' }}>
          {post.category ?? 'Article'}
        </div>
        <div style={{ display: 'flex', fontSize: 64, lineHeight: 1.1, fontWeight: 700 }}>
          {post.title}
        </div>
        <div style={{ display: 'flex', fontSize: 28, color: '#cbd5e1' }}>
          example.com
        </div>
      </div>
    )
  )
}

The route parameters are supplied as a promise in the current file-convention API, so the function awaits params. ImageResponse satisfies the required Response return type. The exported alt, size, and contentType describe the generated asset and let Next.js create the corresponding metadata.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Elebase USB to USB C Adapter for iPhone 18 Pro Max,USBC Car Charger Adapter
  • Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
  • Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
  • Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
  • Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
  • 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.

Where the generated file appears

For app/blog/[slug]/opengraph-image.tsx, the image URL is associated with the matching blog route. A static file named opengraph-image.png, .jpg, or .gif can also be placed in a route segment; Next.js automatically adds tags for those literal files. The documented maximum for a static opengraph-image file is 8 MB, and the parallel twitter-image convention has a 5 MB maximum. Those are Next.js file-convention limits, not a promise that every social network accepts every size or format.

Designing the image that ImageResponse can render

Use flexbox, not browser-only layout features

ImageResponse uses @vercel/og, Satori, and resvg rather than a full browser. Next.js states: “Only flexbox and a subset of CSS properties are supported. Advanced layouts (e.g. display: grid) will not work.” Build the composition with explicit dimensions, flex containers, colors, spacing, borders, and text styles. Do not copy a complex component that depends on CSS Grid, external stylesheets, browser measurements, or client-side state.

Control long titles

Social crawlers need a predictable image. Limit or line-break unusually long titles before rendering, reserve space for the largest expected font, and provide a fallback when a category, author, or excerpt is missing. A simple string truncation policy is safer than allowing text to run outside the 1,200 × 630 canvas.

Fonts and images

The file-convention documentation also demonstrates loading a local font with Node’s fs/promises and passing its bytes in the ImageResponse options. Font data should be available in the deployed runtime; do not assume a remote webfont will load as it does in a browser. Images and fonts need explicit dimensions or buffers that the renderer can access. Test every asset path in the production runtime, especially on edge deployments.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Anker USB-C Hub, 5-in-1 USB Hub for Laptops, 4K HDMI Multiport Adapter
  • 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
  • 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
  • Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
  • 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
  • What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.

Build-time, cached, or request-time generation?

Generated images are statically optimized and cached by default. If the route fetches uncached data, uses request-time APIs, or opts into dynamic configuration, generation can happen at request time instead. Decide this from the content’s freshness requirements.

Content situation Suitable behavior Implementation concern
Titles and branding change only on deploy Static generation and cache Rebuild when the source content changes.
CMS content changes occasionally Cached output with deliberate revalidation Define how an update invalidates the image.
Prices, inventory, or user-specific data Request-time generation Expect more rendering work and verify that every request can access its data.
Uncached fetches or request APIs Dynamic behavior Do not assume a build-time result; configure and monitor the route intentionally.

A common mistake is updating the page data while leaving the old image in a cache. Treat image invalidation as part of the content pipeline: publish the post, invalidate or revalidate the image, then verify the image URL and the page’s og:image tag.

Metadata that points crawlers to the image

The opengraph-image convention handles the Open Graph image metadata for the route. You still need ordinary page metadata such as a title and description. If you construct metadata manually instead, ensure that the image URL is absolute and publicly reachable, and that your server returns the correct MIME type. Social crawlers generally do not execute your client-side JavaScript to discover an image, so the metadata must be present in the server response.

Adding a local font

When a brand font matters, load it on the server and provide its bytes to ImageResponse. The shape is:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
Sale
Anker USB C Hub, 7in1 Multi-Port USB Adapter, 4K@60Hz USBC to HDMI Splitter
  • Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
  • Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
  • Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
  • Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
  • What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
import { readFile } from 'node:fs/promises'
import { ImageResponse } from 'next/og'

const fontData = await readFile(
  new URL('../../assets/Inter-Bold.ttf', import.meta.url)
)

export const size = { width: 1200, height: 630 }
export const contentType = 'image/png'

export default function Image() {
  return new ImageResponse(
    <div style={{ display: 'flex', fontSize: 64 }}>Branded title</div>,
    {
      ...size,
      fonts: [{ name: 'Inter', data: fontData, weight: 700, style: 'normal' }],
    }
  )
}

Keep the font file within your deployment bundle and check the runtime’s support for filesystem access. If the font cannot be read, use a known available fallback rather than returning a broken image.

Using external data safely

  • Encode route values before placing them in a request URL.
  • Check response.ok and provide a controlled fallback for missing posts.
  • Keep secrets out of the generated JSX; the image is public.
  • Return a stable fallback image or a clear server error when the source record is gone.
  • Prevent untrusted text from becoming enormous by applying length limits before layout.

For large sites, generating every possible image during a build may be expensive. Generate only known routes, cache the rest, or use request-time rendering for rapidly changing records. The right choice depends on publishing frequency and the runtime’s cache controls, not on the image dimensions alone.

Framework-independent JavaScript options

Satori for JSX-to-SVG output

Satori accepts pure, stateless JSX-like elements and converts them to SVG. It can run in browsers, Web Workers, and Node.js 16 or later. Its layout engine is not a browser DOM, so the same flexbox-and-supported-properties discipline applies. Satori returns SVG; if your endpoint must return PNG, add an SVG-to-raster step such as the renderer supported by your deployment.

Some runtimes restrict dynamic WebAssembly loading. Satori documents a standalone build that accepts a separately loaded yoga.wasm file for that case. Check the target runtime’s WASM, font, and binary-data APIs before choosing this route.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Sale
UGREEN USB to USB C Adapter Combo 4-Pack, 10Gbps USB C Converter Space Gray
  • Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
  • Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
  • Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
  • Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
  • Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft

Cloudflare Pages integration

Cloudflare Pages documents @cloudflare/pages-plugin-vercel-og middleware. The plugin can extract an existing page’s og:title, pass it to a renderer component, and use autoInject.openGraph to add og:image, width, and height metadata. Its API can also create arbitrary images directly, with a documented 1,200 × 630 ImageResponse example. This is a Pages-specific integration; do not assume its middleware or runtime APIs are interchangeable with a Next.js route.

Approach Output Best fit Key trade-off
Next.js opengraph-image.tsx PNG through ImageResponse Next.js App Router sites Framework conventions and restricted CSS.
Satori directly SVG Custom Node, browser, or Worker services Requires another conversion step for PNG.
Cloudflare Pages plugin PNG through a Pages integration Cloudflare Pages deployments Hosting-specific middleware and APIs.

Testing and troubleshooting

The image is blank or the request fails

  • Unsupported CSS: replace Grid, complex positioning, and browser-only properties with explicit flex containers and dimensions.
  • Missing font or asset: verify the file is bundled and readable in production; temporarily remove the custom asset to isolate the failure.
  • Data request error: log the upstream status, check authentication and URL encoding, and render a fallback when the record is unavailable.
  • Wrong route parameters: confirm the generator is in the same segment as the page and await the current params promise.
  • Stale image: inspect cache and revalidation rules; a successful page update does not automatically prove that an already cached image changed.

The image looks different from the web page

That is expected when the design relies on browser CSS or client-side components. Rebuild the artwork from supported JSX and styles, specify font weights explicitly, and test at the final dimensions. Satori and ImageResponse do not promise pixel-identical browser layout.

The social card does not update

Confirm that the server-rendered HTML contains the intended absolute image URL and that the image endpoint is publicly accessible without client-side interaction. Then account for both your own cache and the social platform’s crawler cache; changing the source data alone is not an invalidation mechanism.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability, and cost decisions

  • Cache stable designs: static output avoids repeating the same render for every crawler.
  • Keep the JSX small: a flat composition is easier for the renderer and less likely to hit unsupported features.
  • Limit upstream work: fetch only the fields needed for the card and avoid cascading API calls.
  • Use deterministic fallbacks: a missing optional field should not turn a share preview into a 500 response.
  • Monitor failures: record route, upstream status, render duration, and cache outcome without logging private content.

No general performance benchmark establishes that one approach is fastest in every deployment. Measure your own build time, first render, cache hit rate, and image error rate under the runtime and traffic pattern you actually use.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
Anker USB C Hub, 5-in-1 USBC to HDMI Splitter with 4K Display
  • 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
  • Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
  • Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
  • HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
  • What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.

Or skip the browser setup

If you need screenshots of existing web pages rather than code-generated social cards, ScreenshotNeo provides a website screenshot API and MCP server. A single request returns PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result.

Use the API documentation at https://screenshotneo.com/docs/ for the full option set. The same service supports full-page and selector captures, dark mode, device presets, retina scale, PDF controls, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting, and an OpenAPI specification.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo includes an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Every feature is on every plan: 1,000 shots per month are free without a card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.

FAQ

Do I need both an Open Graph image and a Twitter image?

Not necessarily. Next.js supports separate opengraph-image and twitter-image conventions when you need different artwork or metadata for those consumers.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can an Open Graph generator return JPEG instead of PNG?

The documented Next.js example returns PNG. If your deployment needs another format, verify that the selected rendering API and downstream crawlers support it before changing the response type.

Can I put interactive React components in the image route?

No. Treat the generator as a server-side, pure composition. Client state, event handlers, and browser DOM APIs are not part of the rendering environment.

What should I do when a post has no image data?

Render a deterministic branded fallback from the same route. This keeps the metadata valid while allowing the page content to remain available.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.