@vercel/og Alternative
Renderfy vs @vercel/og
Both render images with Satori, so let's get the honest part out of the way first: switching to Renderfy will not give you CSS grid in an OG image. What it gives you is PDF output, seven input types, no 500 KB asset budget, and renders from any runtime.
What is actually identical
@vercel/og uses Satori to turn JSX into SVG and Resvg to rasterise it to PNG. Renderfy's image engine uses the same two libraries. That means the following are true of both tools, and you should ignore any comparison page that says otherwise:
- →
display: griddoes not work. Layouts must be flexbox or absolutely positioned. - →Unsupported CSS properties are ignored silently rather than throwing — the image just comes out wrong.
- →There is no JavaScript execution and no live layout pass. Whatever you send is what gets measured.
If a Satori limitation is the thing blocking you, the fix is Renderfy's PDF path — a managed headless Chromium instance with full CSS including grid, CSS variables and @media print — or restructuring the layout in flexbox. Not a different image API.
Feature comparison
| Feature | @vercel/og | Renderfy |
|---|---|---|
| Image renderer | Satori + Resvg → PNG | Satori + Resvg → PNG, JPEG, WebP (same engine class) |
| CSS grid support (images) | No — display: grid is not supported | No — same Satori constraint applies |
| PDF output | None — ImageResponse only emits PNG | Yes — separate headless Chromium engine, full CSS |
| Asset size limit | 500 KB bundle (JSX, CSS, fonts, images combined) | 1 MB content payload; fonts loaded server-side, not bundled |
| Font formats | ttf, otf, woff only — you fetch the ArrayBuffer yourself | Pass a Google Font family name; resolved server-side |
| Input types | JSX only | Tailwind, HTML, Markdown, code, charts, diagrams, LaTeX math |
| Where it runs | A function on Vercel (Next.js App Router, or @vercel/og elsewhere) | Any runtime that can send an HTTP POST — any language |
| Compute cost | Runs inside your function — counts against your invocations and duration | Runs on our infrastructure — your function just awaits a fetch |
| Saved templates | Build your own — redeploy to change a layout | Built in — POST { template, data }, no redeploy |
| Batch rendering | One image per invocation | Up to 20 renders per request |
| Safe retries | Build your own | Idempotency-Key header, encrypted replay body (24h TTL) |
| Price | Free package; you pay for function compute | Credit-based from $9/mo — 1 credit per image, 3 per PDF |
Four things @vercel/og cannot do at all
- 1. Emit a PDF. ImageResponse produces a PNG. Invoices, reports, certificates and contracts all need a second tool.
- 2. Accept woff2 fonts. Only ttf, otf and woff are supported. The format your design system already ships is the one that fails.
- 3. Stay under 500 KB with a real brand kit. The budget covers JSX, CSS, fonts and images together. Two weights of a custom typeface plus a logo will often exceed it on their own.
- 4. Render anything that is not JSX. No Markdown, no Chart.js JSON, no Mermaid diagram, no syntax-highlighted code, no LaTeX.
When you should keep @vercel/og
It is free, it is already in your App Router install, and it adds CDN cache headers to computed images automatically — so a share card that never changes is generated once and served from the edge thereafter. If your cards are a title and a logo on a gradient, your fonts fit the budget, and you never need a PDF, there is no reason to add a dependency. Renderfy earns its place when one of the four blockers above becomes a ticket.
Side by side: a 1200×630 share card
@vercel/og
// app/api/og/route.tsx
import { ImageResponse } from 'next/og';
export async function GET() {
// Custom font: fetch the buffer yourself, and it
// counts against the 500 KB bundle budget.
const inter = await fetch(
new URL('./Inter-Bold.ttf', import.meta.url)
).then((r) => r.arrayBuffer());
return new ImageResponse(
(
<div style={{
display: 'flex', // grid is not supported
width: '100%', height: '100%',
alignItems: 'center', justifyContent: 'center',
background: '#09090b', color: '#fafafa',
fontSize: 64, fontFamily: 'Inter',
}}>
Hello
</div>
),
{
width: 1200,
height: 630,
fonts: [{ name: 'Inter', data: inter, style: 'normal' }],
}
);
}
// Output: PNG only. No PDF path.Renderfy
// app/api/og/route.ts
export async function GET() {
const res = await fetch(
"https://renderfy.io/api/v1/render",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RENDERFY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
type: "tailwind",
content: `<div class="flex h-full w-full items-center
justify-center bg-zinc-950">
<h1 class="text-6xl font-bold text-zinc-50">
Hello
</h1>
</div>`,
options: {
format: "png", // or "pdf"
dimensions: { width: 1200, height: 630 },
fonts: [{ family: "Inter", weights: [700] }],
},
}),
}
);
return new Response(await res.arrayBuffer(), {
headers: { "Content-Type": "image/png" },
});
}
// Font resolved server-side by family name.
// Nothing is added to your deployment bundle.Same flexbox constraints on the image path. The difference is that swapping format: "png" for "pdf" is a one-word change, and the font never touches your deployment bundle.
Frequently asked questions
Does Renderfy support CSS grid in OG images when @vercel/og does not?+
No, and any tool claiming otherwise for a Satori-based renderer is wrong. Renderfy renders images with Satori and Resvg, exactly like @vercel/og, so display: grid is unsupported in both. Use flexbox for image layouts. Where Renderfy does support grid is PDF output, which goes through a real headless Chromium instance with full CSS.
What is the 500 KB limit in @vercel/og?+
Vercel documents a maximum bundle size of 500 KB for OG image generation, and that budget includes your JSX, CSS, fonts, images and any other assets. Custom brand fonts are usually what blows it, because a single weight of a TTF can be 100-300 KB. Renderfy loads fonts server-side from a family name, so nothing font-related counts against your deployment.
Can @vercel/og generate a PDF?+
No. ImageResponse converts your JSX to a PNG via Satori and Resvg. There is no PDF path. If you need an invoice, report or certificate as a PDF, you need a separate tool — that is the single clearest reason teams add Renderfy alongside or instead of next/og.
Why do my custom fonts fail in @vercel/og but work on my site?+
Vercel supports only ttf, otf and woff font formats for OG generation. woff2 — the format most web font pipelines ship by default — is not supported, so the font silently falls back. You also have to fetch the font as an ArrayBuffer and pass it in the fonts option on every render.
Should I replace @vercel/og entirely?+
Usually not. If you are on Next.js, your OG cards are simple flexbox layouts, and your fonts fit the 500 KB budget, next/og is free and fast — keep it. Reach for Renderfy when you need PDF output, more than one input type, renders from a non-Next.js service, or layouts that a redeploy should not be required to change.
Does Renderfy work outside of Next.js?+
Yes. It is a plain REST endpoint, so any language or runtime that can make an HTTPS POST can use it — Node.js, Deno, Bun, Cloudflare Workers, Python, Go, Ruby, PHP. The @renderfy/sdk package is a zero-dependency TypeScript client for JavaScript runtimes.
Related
One endpoint for images and PDFs
100 free credits, no card required. Keep next/og for share cards if it works — add Renderfy where it stops.