Generate a separate image from each page’s route or content data, publish it at a stable absolute URL, and place that URL in the page’s Open Graph metadata. In Next.js App Router, the opengraph-image and twitter-image conventions let you use either a static file or a code route that returns an image. Choose static or dynamic generation based on how often your page data changes, then verify the rendered head and the image response before relying on social previews.
The metadata every shared page needs
The Open Graph protocol defines four basic properties for a page: og:title, og:type, og:image, and og:url. The image should represent the page being shared, not a generic site banner. If you publish og:image, also publish og:image:alt; the protocol treats this value as a description of what is visible in the image, rather than a promotional caption.
Add descriptive fields such as og:description, og:site_name, and og:locale when they are useful. Structured image properties can declare the MIME type, dimensions, and alternative text.
Framework-neutral HTML example
<head>
<meta property="og:title" content="Building a faster checkout">
<meta property="og:type" content="article">
<meta property="og:url" content="https://example.com/posts/faster-checkout">
<meta property="og:image" content="https://example.com/posts/faster-checkout/opengraph-image.png">
<meta property="og:image:alt" content="A checkout form beside a performance chart">
<meta property="og:image:type" content="image/png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:description" content="Practical changes that reduce checkout latency.">
<meta property="og:site_name" content="Example">
</head>
Use an absolute, publicly reachable image URL. A relative path, an image requiring authentication, or a route blocked to sharing crawlers can leave a blank preview even when the HTML appears correct in your browser.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Choose static files or generated routes
Static image files
A static opengraph-image.jpg (or another supported format) is appropriate for a fixed landing page or a section whose artwork rarely changes. It is simple and predictable, but every page that needs a distinct card requires another file and manual updates.
#1 Best Overall
Code-generated images
Use a code route when the card should include a post title, author, category, product name, or other route data. Next.js documents an ImageResponse API that renders JSX and a supported subset of CSS into an image. Do not assume every browser CSS feature works; keep layouts to the styling supported by the image renderer.
More specific route images take precedence over images higher in the app folder tree. A section-level image can therefore provide a fallback while an individual post supplies its own generated card.
Generate a card for every Next.js post
Create app/posts/[slug]/opengraph-image.tsx. The route parameter identifies the post; fetch the post record, then pass its fields into a reusable layout.
Free tools Windows power users keep installed
One-click scans. No signup required.
import { ImageResponse } from 'next/og'
import type { Metadata } from 'next'
type Props = { params: Promise<{ slug: string }> }
async function getPost(slug: string) {
const response = await fetch(`https://cms.example.com/api/posts/${slug}`)
if (!response.ok) throw new Error(`Post request failed: ${response.status}`)
return response.json() as Promise<{
title: string
author: string
category?: string
}>
}
export const alt = 'A generated article preview image'
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={{
background: '#111827', color: 'white', width: '100%', height: '100%',
display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
padding: '64px', fontFamily: 'Arial'
}}
>
<div style={{ fontSize: 28, color: '#93c5fd' }}>{post.category ?? 'Article'}</div>
<div style={{ fontSize: 64, lineHeight: 1.08, display: 'flex' }}>{post.title}</div>
<div style={{ fontSize: 28, color: '#d1d5db', display: 'flex' }}>By {post.author}</div>
</div>
),
{ ...size }
)
}
The documented Next.js example uses 1200 × 630 pixels. Treat that as a useful implementation example, not a universal requirement for every social platform. The exported alt, size, and contentType values allow Next.js to emit the corresponding image metadata.
Rank #2
Add a Twitter image route
Create a sibling twitter-image.tsx when you want a distinct card for X/Twitter. You can reuse the same component and data loader, or point the convention at a static file. Next.js documents a 5 MB maximum for a twitter-image file and an 8 MB maximum for an opengraph-image file; exceeding those limits fails the build under the documented convention. Confirm current platform rules separately before treating these as universal limits.
Static versus dynamic generation and caching
Next.js statically optimizes generated images by default, normally creating and caching them at build time. This gives predictable delivery and avoids doing work for every crawler request. Request-time APIs, uncached external data, or explicit dynamic configuration can switch generation to request time.
Use build-time generation when
- Titles and authors change only when you deploy.
- You want fast, cacheable responses with fewer runtime dependencies.
- Your content API is available during the build.
Use request-time generation when
- The image must reflect data that changes between deployments.
- The route can safely fetch uncached data for a crawler request.
- You have defined how stale images are refreshed and what happens if the data service is unavailable.
Do not promise immediate preview updates merely because the source page changed. Determine whether your deployment caches the image route, how revalidation works, and whether a social platform has cached an earlier image.
Make the image data reliable
Encode and constrain text
Titles can be unexpectedly long, contain line-breaking characters, or be empty because a CMS field is incomplete. Normalize whitespace, cap the number of rendered characters, and provide a fallback title. Design for two or three lines instead of allowing unbounded text to run outside the canvas.
Rank #3
Keep external dependencies deterministic
If you load a logo or font, ensure the image route can reach it in the generation environment. A failed font or remote asset request can produce a different layout or a failed response. Prefer assets bundled with the application or a dependable, publicly reachable origin.
Protect data and URLs
Do not put private post data, access tokens, or user-specific information into a publicly crawlable image. Validate the slug before using it in a downstream request, and return a controlled error or fallback card when a record is missing.
Validate the complete result
- Open the page’s rendered HTML source, not only the framework component, and confirm that
og:title,og:type,og:url, andog:imageare present. - Check that
og:imageis an absolute HTTPS URL and returns an image without authentication, redirects that your crawler cannot follow, or a restrictive firewall rule. - Confirm the response’s
Content-Type, dimensions, and file size match the values you intend to publish. - Inspect the actual bitmap for clipped text, insufficient contrast, missing logos, and an accurate
og:image:altdescription. - Test a URL containing a long title, non-ASCII characters, a missing category, and a deleted or unavailable post.
- After deployment, inspect the image route in production. A local success does not prove that the production build can reach your CMS, fonts, or assets.
Platform crawler behavior and preview caching vary. X-specific dimensions, crawler rules, and fallback behavior are not asserted here because the official X documentation available for this guidance redirected to a general overview.
Recommended Free Tools
Common failures and fixes
The preview uses an old image
Social services often cache fetched metadata and images. Verify that your page now emits the new absolute URL, then use the platform’s current URL-inspection or cache-refresh workflow where available. Changing the image URL (for example, with a versioned path) can help your own cache, but it does not guarantee an immediate refresh by every platform.
The image route returns a 500
Check the CMS response status, slug encoding, environment variables, and any remote font or logo request. Add a fallback card for missing records and log the underlying error without exposing private data in the image response.
Text is clipped or CSS is ignored
ImageResponse supports a subset of CSS rather than a full browser engine. Replace unsupported layout rules with simple flexbox styles, explicit dimensions, and controlled line lengths. Test the generated bitmap, not just the JSX.
Build fails on file size
For Next.js convention files, compare the output with the documented 5 MB Twitter-image and 8 MB Open Graph-image limits. Reduce embedded assets, simplify the design, or choose a more compact format while checking the current requirements of the platforms you target.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Nothing appears in the head
Confirm the file is in the correct route segment, uses a supported filename and format, and is not shadowed by an unexpected route. More specific route images override higher-level images, so inspect the final URL generated for the page.
Best Value
Or skip the browser setup
If you need a screenshot of a rendered URL rather than a framework image route, ScreenshotNeo provides a single-call website screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.
Use the API call below for a rendered page. The ScreenshotNeo documentation covers the available parameters, including PNG, JPEG, WebP, and PDF output.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
There is also an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Plans include 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account.
Python and Node.js alternatives
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
Operational checklist
- Generate a route-specific image from trusted page data.
- Publish an absolute, crawlable URL and matching alt text.
- Declare the four required Open Graph properties.
- Choose static/build-time or request-time generation deliberately.
- Check dimensions, content type, size, contrast, and long-title behavior.
- Monitor CMS, asset, and image-route failures in production.
Frequently Asked Questions
Can one image serve both Open Graph and Twitter metadata?
Yes. Point both conventions or both metadata fields at the same stable image when one design meets your needs; create a separate twitter-image route only when you need different artwork or constraints.
Where should the generated image URL be hosted?
Host it at an HTTPS URL that the relevant sharing crawler can fetch without login, private network access, or browser-only authentication.
Is 1200 × 630 mandatory?
No. It is the dimension used in a Next.js ImageResponse documentation example. Treat it as a practical starting point and verify the current requirements of each platform you target.
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.




