Automate Social Media Preview Images for Your Blog (No Design Skills Needed)

# webdev# seo# html# tutorial
Automate Social Media Preview Images for Your Blog (No Design Skills Needed)Mack

How to auto-generate OG images for every blog post using HTML templates and an API. Works with any framework.

Every time you share a link on Twitter, Slack, Discord, or LinkedIn, the platform fetches your og:image meta tag and displays a preview. If you don't have one, your link looks like this:

Your Blog Post Title
yourdomain.com

Boring. Forgettable. Zero clicks.

But if you generate a custom OG image for every post:

🖼️ A beautiful card with your title, author name, date, and brand colors

Way more clicks. Here's how to automate it.

The Strategy

  1. Create an HTML/CSS template for your OG images
  2. For each blog post, fill in the variables (title, author, date)
  3. Render the HTML to a PNG via an API
  4. Set the og:image meta tag to the generated image URL

No Figma. No Canva. No manual work per post.

Step 1: The HTML Template

OG images should be 1200×630 pixels. Here's a starter template:

<div style="
  width: 1200px; height: 630px;
  display: flex; flex-direction: column;
  justify-content: center; padding: 60px 80px;
  background: linear-gradient(135deg, #0f0f13 0%, #1a1a2e 100%);
  font-family: 'Inter', sans-serif; color: white;
">
  <div style="font-size: 48px; font-weight: 800; line-height: 1.2; margin-bottom: 24px;">
    {{title}}
  </div>
  <div style="font-size: 20px; color: #888; margin-bottom: auto;">
    {{author}} · {{date}} · {{read_time}} read
  </div>
  <div style="font-size: 24px; font-weight: 700; color: #00d68f;">
    yourblog.com
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Step 2: Render It

Use an HTML-to-image API to convert this template into a PNG:

curl -X POST https://rendly-api.fly.dev/api/v1/images \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<div style=\"width:1200px;height:630px;display:flex;flex-direction:column;justify-content:center;padding:60px 80px;background:linear-gradient(135deg,#0f0f13,#1a1a2e);font-family:Inter,sans-serif;color:white;\"><div style=\"font-size:48px;font-weight:800;line-height:1.2;margin-bottom:24px;\">How I Built a SaaS in a Weekend</div><div style=\"font-size:20px;color:#888;margin-bottom:auto;\">Mack · Feb 15, 2026 · 5 min read</div><div style=\"font-size:24px;font-weight:700;color:#00d68f;\">rendly-api.fly.dev</div></div>",
    "viewport": {"width": 1200, "height": 630},
    "format": "png"
  }'
Enter fullscreen mode Exit fullscreen mode

Step 3: Set the Meta Tag

In your HTML <head>:

<meta property="og:image" content="https://rendly-api.fly.dev/api/v1/renders/YOUR_RENDER_ID/image" />
<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

Framework Integration

Next.js

Generate at build time in getStaticProps:

export async function getStaticProps({ params }) {
  const post = getPostBySlug(params.slug);

  const res = await fetch('https://rendly-api.fly.dev/api/v1/images', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.RENDLY_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      html: ogTemplate(post.title, post.author, post.date),
      viewport: { width: 1200, height: 630 }
    })
  });

  const { image_url } = await res.json();
  return { props: { post, ogImage: image_url } };
}
Enter fullscreen mode Exit fullscreen mode

Rails

Generate in your controller or as a helper:

class PostsController < ApplicationController
  def show
    @post = Post.find(params[:id])
    @og_image = generate_og_image(@post)
  end

  private

  def generate_og_image(post)
    conn = Faraday.new(url: 'https://rendly-api.fly.dev')
    res = conn.post('/api/v1/images') do |req|
      req.headers['Authorization'] = "Bearer #{ENV['RENDLY_API_KEY']}"
      req.headers['Content-Type'] = 'application/json'
      req.body = {
        html: render_to_string(partial: 'posts/og_template', locals: { post: post }),
        viewport: { width: 1200, height: 630 }
      }.to_json
    end
    JSON.parse(res.body)['image_url']
  end
end
Enter fullscreen mode Exit fullscreen mode

Pro Tips

  1. Cache aggressively — OG images rarely change. Generate once, cache forever.
  2. Use web fonts — Pass google_fonts: ["Inter", "Fira Code"] to load them.
  3. Test with social debuggersFacebook Sharing Debugger, Twitter Card Validator
  4. Keep text big — Preview images are often shown small. 48px+ for titles.
  5. Brand consistency — Use the same template across all posts for recognition.

The Lazy Version

If you don't want to code anything, use Rendly's built-in templates:

curl -X POST https://rendly-api.fly.dev/api/v1/templates/og-blog-post/render \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "variables": {
      "title": "My Amazing Blog Post",
      "author": "Your Name",
      "date": "Feb 15, 2026"
    }
  }'
Enter fullscreen mode Exit fullscreen mode

10 built-in templates, zero design work.


Rendly is a free screenshot and OG image API. 100 renders/month free, no credit card required.