Tutorial5 Jul 2025·6 min read

How to automatically generate OG images for every blog post

Most blogs share a single OG image across every post. Someone shares your article on Twitter, and the preview shows your homepage image. Or a generic "Blog" graphic. Or nothing at all.

The problem is obvious once you see it: every article looks identical in a feed. There's no signal about what the article is about.

A unique OG image per post — showing the article title, author, and category — makes your content look intentional. It also significantly increases clicks, because people know what they're clicking on.

Here's how to set it up automatically so you're not manually creating an image for every post you publish.

Option 1: Opengraphly URL parameters (no-code)

Opengraphly lets you design a template once and pass dynamic values via URL parameters. You don't need to write any code.

The template URL looks like this:

https://opengraphly.com/render/[your-template-id]?title=Your+Post+Title&author=Nathan

In your blog platform, you set the og:image tag to this URL pattern, substituting the post title and author dynamically from each post's metadata.

In Webflow: Use CMS fields with dynamic binding to construct the URL. Set the OG image field in your blog post template collection to the Opengraphly URL with CMS field references.

In Framer: Framer's CMS supports dynamic OG URLs. In the CMS settings for your blog collection, set the OG image to the Opengraphly URL pattern with {title} replaced by the CMS field binding.

In WordPress: Using Yoast or Rank Math, you can set the OG image to a dynamic URL. Alternatively, a small snippet in your theme's functions.php can override the og:image meta tag to output the dynamic URL.

In Notion + Super: Super (super.so) supports custom OG image URLs per page. Set the URL template in your Super settings.

The Opengraphly template handles all the rendering — font, layout, branding, background. You just pass in the variable content.

Option 2: Vercel OG (Next.js)

If your blog is built with Next.js, Vercel's next/og library generates images server-side from a React component. No external service, no API costs.

Each blog post gets a unique OG image generated on the fly using its own metadata.

// app/blog/[slug]/opengraph-image.tsx
import { ImageResponse } from 'next/og'
 
export const runtime = 'edge'
export const size = { width: 1200, height: 630 }
export const contentType = 'image/png'
 
export default async function OGImage({ params }: { params: { slug: string } }) {
  const post = await getPostBySlug(params.slug)
 
  return new ImageResponse(
    <div
      style={{
        background: '#F9F8F6',
        width: '100%',
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-end',
        padding: '64px',
      }}
    >
      <div style={{ fontSize: 16, color: '#6B6B70', marginBottom: 16, textTransform: 'uppercase', letterSpacing: 3 }}>
        {post.category}
      </div>
      <div style={{ fontSize: 64, fontWeight: 700, color: '#1C1C1E', lineHeight: 1.1, maxWidth: 900 }}>
        {post.title}
      </div>
      <div style={{ marginTop: 40, fontSize: 20, color: '#6B6B70' }}>
        {post.author} · {post.readTime} read
      </div>
    </div>
  )
}

Next.js automatically serves this at /blog/[slug]/opengraph-image and sets the og:image tag for you.

The tradeoff: The layout is defined in JSX. If a designer or marketer wants to change the template, it requires a code change and deployment. That's fine for development-led teams. It's a bottleneck for everyone else.

Option 3: Cloudinary transformations

If you're already using Cloudinary for image hosting, their URL API can overlay text onto a base image.

https://res.cloudinary.com/your-cloud/image/upload/
  l_text:Arial_60:Your Post Title Here,
  co_rgb:1C1C1E,
  g_south_west,x_64,y_64/
  your-og-base-image.jpg

The URL parameters define the text, font, colour, and position. You construct this URL dynamically in your template for each post.

The tradeoff: Cloudinary URL syntax is complex and hard to maintain. Changes to the layout require manually editing URL parameter strings. There's no visual preview. It works, but debugging takes time.

Which option is right for you

Your situationBest option
No-code blog (Webflow, Framer, Notion)Opengraphly URL parameters
Next.js blog, developer-ledVercel OG (next/og)
Already on Cloudinary, simple overlaysCloudinary text transformations
Next.js blog, non-dev team updates templatesOpengraphly (visual editor, no redeploy)

What your template should include

Whatever method you use, the per-post OG image should show:

  • Post title — large, readable at thumbnail scale
  • Your logo or site name — so people know whose content this is
  • Category or topic label — helps people understand the content type at a glance
  • Author name — optional, but adds credibility for personal brands

Keep the layout simple. At 400px wide (how most people see it), you have room for one bold headline and a couple of supporting details. That's it.

Fix it today

Your next shared link should look this good.

Design your OG image once. Paste the URL once. Done forever. Takes about four minutes.

Get started free