DEV Community

Mack
Mack

Posted on

Build an Automated Social Card Generator in 15 Lines of Python

Every time you share a link on Twitter, Slack, or Discord, the preview image matters. A good one gets clicks. A missing one gets scrolled past.

Here's how to generate them automatically in 15 lines of Python.

The Problem

You write a blog post. You share it. The link preview shows... nothing. Or worse, a random cropped image from your page.

You could open Figma every time and design a card. But you won't. Nobody does.

The Solution

Use an API to render HTML as an image. You design the card once as HTML/CSS, then generate unique images for each post by swapping in the title and metadata.

import requests

def generate_card(title, author="My Blog", theme="dark"):
    html = f"""
    <div style="width:1200px;height:630px;display:flex;align-items:center;
    justify-content:center;background:{"#1a1a2e" if theme == "dark" else "#fff"};
    color:{"#fff" if theme == "dark" else "#1a1a2e"};font-family:system-ui;
    padding:60px;box-sizing:border-box;">
      <div>
        <h1 style="font-size:52px;margin:0 0 20px 0;">{title}</h1>
        <p style="font-size:24px;opacity:0.7;">by {author}</p>
      </div>
    </div>"""

    resp = requests.post("https://rendly-api.fly.dev/api/v1/images", 
        headers={"Authorization": "Bearer YOUR_API_KEY",
                 "Content-Type": "application/json"},
        json={"html": html, "width": 1200, "height": 630, "format": "png"})

    return resp.json()["image_url"]
Enter fullscreen mode Exit fullscreen mode

That's it. Call generate_card("My Post Title") and you get a PNG URL back.

Make It Better

The HTML is just a string. You can go wild:

  • Add gradients, patterns, or background images
  • Include your logo
  • Show reading time, date, tags
  • Use different layouts per category
# Gradient background version
html = f"""
<div style="width:1200px;height:630px;display:flex;align-items:center;
justify-content:center;
background:linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color:#fff;font-family:system-ui;padding:60px;box-sizing:border-box;">
  <div>
    <p style="font-size:18px;text-transform:uppercase;letter-spacing:3px;
    opacity:0.8;margin:0 0 20px 0;">✨ {category}</p>
    <h1 style="font-size:48px;margin:0 0 24px 0;line-height:1.1;">{title}</h1>
    <p style="font-size:20px;opacity:0.7;">{date} · {reading_time} min read</p>
  </div>
</div>"""
Enter fullscreen mode Exit fullscreen mode

Automate It

Hook this into your blog's build process:

import json, os

posts = json.load(open("posts.json"))
for post in posts:
    image_url = generate_card(post["title"], theme="dark")
    post["og_image"] = f"https://rendly-api.fly.dev{image_url}"
    print(f"✅ Generated card for: {post["title"]}")

# Update your posts with the new og:image URLs
json.dump(posts, open("posts.json", "w"), indent=2)
Enter fullscreen mode Exit fullscreen mode

Now every post gets a unique, styled preview image — automatically.

Try It Live

You can test this right now without signing up: Rendly Playground

Paste in your HTML, hit render, see the result. The free tier gives you 100 renders/month.


I built Rendly because I was tired of manually creating OG images. It's a simple API — send HTML, get an image back. Try the playground or grab a free API key.

Top comments (0)