How to Generate Open Graph Images Automatically for Your Blog
When someone shares your blog post on Twitter, LinkedIn, or Slack, what do they see? If you don't have a custom Open Graph (OG) image, they get a generic preview with just your site title. That's a missed opportunity to make your content stand out.
Most content creators solve this manually: use Figma, create 10 variations, export them, name them carefully, upload them to the right folder. It's tedious. And when you publish 2-3 posts a week, manual OG images become a bottleneck.
Here's how to generate unique, branded OG images automatically — one API call per blog post.
The Problem: Manual OG Images Don't Scale
Right now, you probably:
- Manually design OG images in Figma or Canva
- Spend 5-10 minutes per image
- Sometimes skip OG images entirely on low-priority posts
- End up with inconsistent branding across social shares
Result: Your posts look boring on Twitter. Click-through rates suffer.
The Solution: Generate OG Images from HTML
Here's the simplest approach: create an HTML template with your post title and metadata, then convert it to an image on publish.
const fetch = require('node-fetch');
async function generateOGImage(title, author, category) {
const response = await fetch('https://api.pagebolt.com/v1/og', {
method: 'POST',
headers: {
'Authorization': `Bearer YOUR_API_KEY`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
template: 'blog',
title: title,
subtitle: author,
category: category
})
});
return await response.buffer();
}
That's it. 3 lines. No design work. No waiting for exports.
Real-World Example: Blog Post Publishing
Let's say you're using a static site generator (Next.js, Hugo, Astro) to publish blog posts. When you create a new post, you want to auto-generate an OG image.
Here's a Node.js script that hooks into your build process:
const fetch = require('node-fetch');
const fs = require('fs');
const path = require('path');
const matter = require('gray-matter');
async function generateOGImagesForBlog() {
// Read all markdown files in posts directory
const postsDir = './posts';
const files = fs.readdirSync(postsDir).filter(f => f.endsWith('.md'));
for (const file of files) {
const content = fs.readFileSync(path.join(postsDir, file), 'utf-8');
const { data } = matter(content);
// Skip if OG image already exists
const ogImagePath = path.join('./public/og-images', `${data.slug}.png`);
if (fs.existsSync(ogImagePath)) {
console.log(`✓ OG image exists for ${data.slug}, skipping`);
continue;
}
try {
console.log(`Generating OG image for ${data.title}...`);
const response = await fetch('https://api.pagebolt.com/v1/og', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PAGEBOLT_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: data.title,
subtitle: `by ${data.author}`,
category: data.category,
// Custom branding
backgroundColor: '#1a1a2e',
textColor: '#00d4ff',
logoUrl: 'https://yoursite.com/logo.png'
})
});
if (!response.ok) {
console.error(`Failed to generate OG image: ${response.statusText}`);
continue;
}
const buffer = await response.buffer();
// Ensure directory exists
const dir = path.dirname(ogImagePath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
fs.writeFileSync(ogImagePath, buffer);
console.log(`✓ Saved OG image to ${ogImagePath}`);
} catch (error) {
console.error(`Error generating OG image for ${data.slug}:`, error.message);
}
}
console.log('✓ OG image generation complete');
}
// Run on build
generateOGImagesForBlog().catch(console.error);
Add this to your package.json build script:
{
"scripts": {
"prebuild": "node generate-og-images.js",
"build": "next build"
}
}
Now every time you deploy, OG images are generated automatically for new posts.
Customizing Your OG Images
PageBolt supports custom styling for your OG images:
const response = await fetch('https://api.pagebolt.com/v1/og', {
method: 'POST',
headers: {
'Authorization': `Bearer YOUR_API_KEY`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'How to Generate PDFs Without Puppeteer',
subtitle: 'Technical Tutorial',
category: 'Development',
// Branding options
backgroundColor: '#ffffff',
textColor: '#000000',
accentColor: '#3b82f6',
logoUrl: 'https://yoursite.com/logo.png',
fontFamily: 'Inter',
// Layout options
layout: 'minimal', // or 'card', 'gradient'
padding: 60
})
});
Why This Beats Manual Design
Manual approach:
- Design in Figma: 5-10 minutes per image
- Export and optimize: 2 minutes per image
- Upload and link in frontmatter: 1 minute per image
- Total: 8-13 minutes × posts/week = 1+ hour/week
Automated approach:
- Write blog post (already doing this)
- Run build script: 10 seconds for 10 posts
- OG images auto-generate and deploy
- Total: 10 seconds/week
For a blog publishing 4 posts/week, automated OG images save ~30 minutes/week. That's 26+ hours/year.
Batch Generate OG Images for Existing Blog
Already have 50 posts without OG images? PageBolt can batch-generate them:
async function batchGenerateOGImages() {
const posts = await getAllBlogPosts(); // Your function
const results = [];
// Process 10 at a time to avoid rate limits
for (let i = 0; i < posts.length; i += 10) {
const batch = posts.slice(i, i + 10);
const promises = batch.map(post =>
generateOGImage(post.title, post.author, post.category)
.then(buffer => ({
slug: post.slug,
buffer: buffer,
status: 'success'
}))
.catch(error => ({
slug: post.slug,
status: 'error',
error: error.message
}))
);
results.push(...await Promise.all(promises));
console.log(`Processed ${i + 10}/${posts.length} posts`);
}
// Save all OG images
results.forEach(result => {
if (result.status === 'success') {
const path = `./public/og-images/${result.slug}.png`;
fs.writeFileSync(path, result.buffer);
}
});
return results;
}
Getting Started
- Sign up free at pagebolt.dev/pricing — 100 OG images/month
- Get your API key from the dashboard
- Create an HTML template or use the built-in blog template
- Integrate
generateOGImage()into your blog build process - Deploy → OG images auto-generate for every post
Your blog posts will now have unique, branded social previews — automatically.
Start free: pagebolt.dev/pricing. 100 OG images/month, no credit card required.
Top comments (0)