Use an HTML/CSS design as the input to an image route, return a 1200 × 630 PNG, and point your page’s og:image metadata at that public URL. A practical implementation is Vercel’s @vercel/og, which uses Satori and Resvg to convert supported HTML and CSS into PNG. After deployment, inspect the raw metadata and preview so crawlers can fetch the image.
What an HTML Open Graph image pipeline does
The Open Graph Protocol lets a web page become a rich object in a social graph. Your page remains ordinary HTML; the social card is a separate image generated from a reusable design. The flow is:
- Create a component containing the card’s text, colors, layout, and assets.
- Expose an image endpoint that renders that component and returns PNG bytes.
- Put the endpoint’s absolute URL in the page head as
og:image. - Deploy both the page and endpoint, then verify what crawlers receive.
Vercel’s documented @vercel/og route is a constrained renderer rather than a full browser. It supports HTML-like JSX, flexbox and absolute positioning, but not CSS Grid. If your existing design depends on arbitrary browser behavior, use a browser screenshot pipeline instead.
Choose a rendering approach
| Approach | Best fit | Important trade-off |
|---|---|---|
@vercel/og (Satori + Resvg) |
Cards that can be expressed with supported JSX and CSS | Predictable image endpoint, but only a supported CSS subset; Grid and many browser features require redesign. |
| Browser screenshot pipeline | Pixel fidelity with an existing HTML page, complex CSS, or browser-only scripts | Requires browser automation, hosting, fonts and page-load handling; the supplied sources establish the architecture but not a current performance winner. |
Do not treat either architecture as universally faster or better. Decide first whether your design needs a real browser.
#1 Best Overall
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
Prerequisites and size target
- For the documented package-install workflow, Vercel lists Node.js 22 or newer. For Next.js implementations, it lists Next.js 12.2.3 or newer. These requirements can change, so check the current documentation when you upgrade.
- In a Next.js App Router project, the guide says the package is already included. Otherwise install it with
pnpm i @vercel/og. - Vercel recommends 1200 × 630 pixels for an OG image. The API reference lists width and height defaults of 1200 and 630 and PNG output.
- The guide lists a 500 KB maximum bundle, counting JSX, CSS, fonts, images and other assets.
Build the image endpoint in Next.js
1. Create the route
In an App Router project, create app/api/og/route.tsx. This example reads a title from the query string, keeps the layout to supported flexbox properties, and returns a 1200 × 630 PNG.
import { ImageResponse } from 'next/og'
export const runtime = 'edge'
export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const title = searchParams.get('title') || 'My article'
return new ImageResponse(
(
<div
style={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
background: '#101828',
color: '#ffffff',
padding: '72px',
fontFamily: 'Arial',
}}
>
<div style={{ display: 'flex', color: '#98a2b3', fontSize: 28 }}>
itechguides.com
</div>
<div style={{ display: 'flex', fontSize: 64, fontWeight: 700, lineHeight: 1.1 }}>
{title}
</div>
<div style={{ display: 'flex', fontSize: 26, color: '#d0d5dd' }}>
Practical guides for developers
</div>
</div>
),
{ width: 1200, height: 630 }
)
}
Install the package when your project does not already include it:
pnpm i @vercel/og
Visit /api/og?title=Generate%20Open%20Graph%20Images locally. A successful response is an image, not an HTML page. Keep query values bounded and escaped by React; do not inject raw markup into the component.
2. Add metadata to the page
The metadata belongs to the page that will be shared, not only to the image route. In an App Router page, return an absolute URL from generateMetadata (or use a static metadata object when the URL is fixed).
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →import type { Metadata } from 'next'
type Props = { params: { slug: string } }
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const title = 'How to Generate Open Graph Images with HTML'
const origin = 'https://example.com'
const image = `${origin}/api/og?title=${encodeURIComponent(title)}`
return {
title,
openGraph: {
title,
type: 'article',
url: `${origin}/guides/${params.slug}`,
description: 'Generate a social preview image from HTML and CSS.',
images: [{ url: image, width: 1200, height: 630, alt: title }],
},
}
}
If you write the head tag yourself, the essential form is:
<meta property="og:image" content="https://example.com/api/og?title=Generate%20Open%20Graph%20Images" />
Use an absolute, publicly reachable URL. Include the page’s title, type, canonical URL and description as appropriate for your site; og:image identifies the image representing that object.
Design within the renderer’s constraints
Layout and CSS
- Use flexbox or absolute positioning for reliable placement.
- Do not use CSS Grid; redesign the composition with nested flex containers or positioned elements.
- Set explicit dimensions, padding, line heights and colors. A social card has no responsive viewport to rescue an ambiguous layout.
- Test long titles, missing fields and non-Latin text. Apply a maximum number of lines or choose a smaller font when content is variable.
Fonts and assets
The guide lists TTF, OTF and WOFF custom fonts, with TTF and OTF preferred for parsing speed. Include only the weights and glyph coverage you need. Fonts, images, JSX and CSS all count toward the 500 KB bundle limit. A remote asset that is unavailable at render time can produce a missing logo or a failed image, so prefer bundled, small assets and verify the deployed route.
Dimensions and output
Use 1200 × 630 unless a consuming service gives you a different requirement. The API reference documents PNG output and those dimensions as defaults; specifying them explicitly makes the contract clear. If you need another size, pass supported width and height values and test the resulting crop in each destination.
Recommended Free Tools
Make the route crawler-accessible
Social providers must fetch both the page and the image endpoint. Vercel’s guide recommends allowing the OG API route in robots.txt. This is a crawler-access consideration, not a guarantee that every network or platform will render a preview.
User-agent: *
Allow: /api/og
Check authentication, firewall rules, geographic restrictions, required cookies and rate limits. A route that works in your browser but returns a login page to an anonymous crawler will not produce the intended card.
Rank #3
Deploy and verify the result
- Deploy the page and image route to a stable HTTPS domain.
- Request the image URL directly. Confirm an image content type, the intended dimensions and a non-error body.
- Fetch the deployed page as plain HTML and inspect its raw
<head>. Confirmog:imageis absolute and points to the deployed route, not localhost. - Use Vercel’s Open Graph inspection feature to view metadata and preview renders for Twitter, Slack, Facebook and LinkedIn.
- If a platform still shows an old card, allow for its metadata cache and re-run its supported refresh/debug process. Fetching and caching behavior varies by platform.
Verify the deployed output rather than relying on a client-side head update: crawlers may not execute your application JavaScript.
Common failures and fixes
The endpoint returns an error or blank image
Check the deployment logs, then remove unsupported CSS (especially Grid), oversized assets and unavailable remote fonts. Confirm the route exports the expected HTTP method and that the runtime supports the package.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →The image URL appears in source but no preview is shown
Request the absolute URL without credentials. Check DNS, HTTPS certificates, redirects, firewall rules and robots.txt. Ensure the response is an image and that the page’s raw head—not only a browser inspector after hydration—contains the tag.
Text is clipped or overlaps
Reproduce with the longest real title. Reduce font size, increase line height, constrain text width, or position elements explicitly. Replace Grid-based styling with nested flex containers.
A logo or font is missing
Confirm the file is included in the deployment and within the bundle budget. Use a supported TTF, OTF or WOFF font and verify its glyphs cover the languages you publish.
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
Changes are not visible on social sites
The image route and social platform may cache independently. Change the image URL when you intentionally invalidate a card (for example, with a versioned query value), while keeping your canonical page URL stable.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWhen a browser screenshot is the better tool
Choose a real browser when you must reuse production HTML exactly, execute client-side JavaScript, support CSS Grid or browser-specific font shaping, or capture a page that depends on layout calculations unavailable to the constrained renderer. The cost is additional browser startup, resource blocking, waiting and hosting work. Keep the capture page deterministic: set a fixed viewport, wait for fonts and images, disable animations, and provide a fallback for failed assets. There is no current controlled comparison in the cited material that establishes a universal speed or quality winner.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. It can capture a deployed HTML card or any public page with one request, without you operating a browser fleet. Before capture it accepts cookie/consent banners 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 status. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.
Every plan includes the feature set: full-page and selector capture, dark mode, device presets or custom viewports, retina scale, PDF controls, custom CSS and JavaScript, clicks, waits, request/resource blocking, headers, cookies, user agent, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Parameter names used by other screenshot APIs also work.
Plans are Free (1,000 shots per month, no card), Starter ($5 for 3,000), Growth ($15 for 15,000), Pro ($39 for 60,000), Scale ($99 for 250,000) and Business ($249 for 1,000,000); yearly billing gives two months free. Paid plans start at $5.
One-call examples
See the ScreenshotNeo documentation for request details. cURL:
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
Python:
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)
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}`);
Replace the target URL with your deployed OG design or page. Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.
Final pre-share checklist
- The image route returns a valid PNG at the intended dimensions.
- The page’s raw HTML contains an absolute
og:imageURL. - The route is reachable anonymously over HTTPS and allowed for crawlers.
- Fonts and assets are supported, available and within the bundle limit.
- Long, short and translated titles render without clipping.
- A deployed preview has been checked in Vercel’s inspector and at least one target social platform.
Frequently Asked Questions
Can I use a relative URL for og:image?
No. Use the complete HTTPS URL that a crawler can request from outside your application.
Does @vercel/og render arbitrary web pages?
No. It renders a supported JSX and CSS subset through Satori and Resvg; a full browser is appropriate for unsupported browser behavior.
Free tools Windows power users keep installed
One-click scans. No signup required.
Is 1200 × 630 mandatory everywhere?
No. It is Vercel’s documented recommendation and the API’s default dimensions, not a universal platform rule.
Why should robots.txt mention the image route?
Allowing the route helps crawlers fetch it; it cannot guarantee that a social platform will ignore its own access rules or cache.
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.

