DEV Community

Narender singh
Narender singh

Posted on

How to Generate Open Graph Images Dynamically (No Puppeteer)

You know what's annoying? Spinning up a headless browser just to generate a social preview image.

Puppeteer works. Sure. But it's slow, memory-hungry, and a nightmare to deploy on serverless. I spent way too long fighting Chrome binaries on Vercel before I gave up and looked for something better.

Turns out there's a simpler way.

The Problem With Puppeteer-Based OG Images

Here's the typical flow:

  1. Spin up a headless Chrome instance
  2. Render an HTML page with your dynamic content
  3. Screenshot it
  4. Serve that screenshot as your OG image

It works on your local machine. Then you deploy it and everything breaks. Chrome needs specific system libraries. Cold starts take 5-10 seconds. Memory usage spikes. And if you're on a free tier anywhere, good luck.

I've burned entire weekends on this.

Enter OGPix

OGPix takes a completely different approach. Instead of running a browser, it generates images through an API. You send parameters, you get back an image URL. That's it.

No Chrome. No Puppeteer. No deployment headaches.

How It Works — Step by Step

1. Pick a Template or Build Your Own

OGPix comes with pre-built templates for blog posts, product pages, and documentation. But you can also customize everything.

2. Generate via URL Parameters

The simplest approach — just construct a URL:

https://ogpix-pi.vercel.app/api/og?title=My+Blog+Post&description=A+quick+tutorial&theme=dark
Enter fullscreen mode Exit fullscreen mode

Drop that into your meta tags:

<meta property="og:image" content="https://ogpix-pi.vercel.app/api/og?title=My+Blog+Post&description=A+quick+tutorial&theme=dark" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta name="twitter:card" content="summary_large_image" />
Enter fullscreen mode Exit fullscreen mode

3. Use It in Next.js

If you're on Next.js, add it to your layout or page head:

export const metadata = {
  openGraph: {
    images: [
      {
        url: \`https://ogpix-pi.vercel.app/api/og?title=\${encodeURIComponent(post.title)}\`,
        width: 1200,
        height: 630,
      },
    ],
  },
};
Enter fullscreen mode Exit fullscreen mode

4. Dynamic Routes? No Problem

For blog posts or any dynamic content, just swap in the variables:

function getOGImage(title, author) {
  const params = new URLSearchParams({
    title,
    author,
    theme: 'gradient',
  });
  return \`https://ogpix-pi.vercel.app/api/og?\${params.toString()}\`;
}
Enter fullscreen mode Exit fullscreen mode

Why This Beats Puppeteer

  • Speed: Images generate in milliseconds, not seconds
  • No dependencies: Zero system libraries to install
  • Serverless-friendly: Works everywhere, including edge functions
  • Caching: URLs are deterministic, so CDN caching just works
  • Free: No paid tiers for basic usage

The Results

I switched three of my projects from Puppeteer to OGPix. Deploy times dropped. No more random failures in CI. And the images actually look better because I'm not fighting CSS rendering inconsistencies across headless browsers.

If you're still wrestling with Puppeteer for OG images, stop. There's a better way now.

Check it out at ogpix-pi.vercel.app.

Top comments (0)