Dynamic Open Graph images, without a screenshot service
Every shared link deserves its own preview card. Here is how to render them on demand from one design — no Puppeteer, no screenshot farm.
PixelDrive··6 min read
The Open Graph image is the most-viewed asset most teams never design. It is the card that shows up when a link is pasted into Slack, X, LinkedIn or iMessage — and for blogs, docs and product pages, there can be thousands of them, one per URL. Designing each by hand is impossible; falling back to a single generic image leaves clicks on the table.
The common fix is a headless browser that screenshots an HTML page. It works until it does not: cold starts, font loading races, memory spikes, and a render pipeline you now have to babysit. There is a calmer way — treat the OG image as a templated render behind a stable URL.
Design the card once, fill it per page
Build the OG card as a single template: a fixed 1200×630 layout with your logo, background and type locked in place, and two or three variable fields — title, author, maybe a category tag. Everything visual is decided once, in a design tool, not reconstructed from CSS on every request.
From then on a page only supplies data. The title of the post, the name of the doc, the price of the product — passed as URL parameters or JSON. The render is deterministic: the same inputs always produce the same pixels, so your previews never drift.
The URL is the API
Point each page’s og:image meta tag at a render URL that carries its data. Because the URL is stable and content-addressed, a CDN and the render cache can both hold it: the first crawl renders it in about a second, every crawl after is served from cache for free.
<meta property="og:image"
content="https://pixeldrive.pro/img/t/og_8c41f2?title=Dynamic+OG+images&author=PixelDrive&format=png">Why this beats a screenshot service
- No headless browser to run, scale or patch — rendering is a managed call.
- Deterministic output: identical inputs, identical image, every time.
- Cacheable by construction — repeat shares cost nothing and serve in milliseconds.
- Fonts and brand are baked into the template, so previews can’t render half-styled.
- Localise the same card by adding a language parameter — the title comes back translated.
Make it dynamic without a deploy
Because the design lives in a template rather than in your codebase, marketing can restyle every preview card on the site — new colour, new logo lockup, a seasonal frame — without a single deploy. The URLs your pages emit stay identical; only the rendered output changes.
That separation is the whole point: data comes from your app, design comes from the template, and the two meet at a cache-friendly URL.