🚫 Problem
Having to manually 😴 create unique images for Social Media (Open Graph) for your new blog posts.
✅ Solution
Let's use Node.js to engineer a script to take care of this for us 😎
❤️ Generated image
This is the final result, a dynamically generated image:

🤔 How does this work?
A part from playing with the file system (fs) module from Node.js, the actual image creation will be done using canvas:
https://www.npmjs.com/package/canvas
I assume you're comfortable adding NPM packages to your package.json
file.
Require all functions needed from canvas
We'll start our index.js
file by requiring this, as well as the file system module:
const fs = require('fs');
const {
createCanvas,
loadImage,
registerFont,
} = require('canvas');
Code language: JavaScript (javascript)
Creating a canvas
To define the area we will be working with, define it like so:
const imageCanvas = createCanvas(1200, 630);
const context = imageCanvas.getContext('2d');
Code language: JavaScript (javascript)
Loading a custom font (optional)
In case the system you're creating the images in does not have the fonts you want, simply include the .ttf
files and register the custom font like so:
registerFont('comicsans.ttf', { family: 'Comic Sans' })
Code language: JavaScript (javascript)
Read more on the registerFont function.
Adding a background color to the canvas
You'll notice the width
and height
match the canvas size we defined earlier.
context.fillStyle = '#343a40';
context.fillRect(0, 0, 1200, 630);
Code language: JavaScript (javascript)
Adding text to the canvas
Use these 3 properties to define properties of the text, and then add the text in the position you want relative to the canvas.
context.fillStyle = '#fff';
context.font = 'bold 30pt Menlo';
context.fillText('ricard.dev', 580, 520);
Code language: JavaScript (javascript)
Writing to disk
The final step is to simply write a file with the canvas as PNG format:
fs.writeFileSync(
`./images/myImage.png`,
imageCanvas.toBuffer('image/png'),
);
Code language: JavaScript (javascript)
At this point you would be done 👏. You now know how to create images with text with canvas from within Node. You don't have to continue if you don't use WordPress. Just jump to the end to grab the final code.
What improvements can be done?
- Use a
database.txt
file to list all the images you want to create (this can be found in the final code). - Create this on the fly. You could even serve the image on the fly rather than storing it to disk (not covered in this blog post).
WordPress (optional)
If you're using WordPress here are small snippets you'll be needing:
Generate the database
List of post and their ID's:
$path = preg_replace('/wp-content.*$/','',__DIR__);
include($path.'wp-load.php');
$args = array(
'numberposts' => -1
);
$posts = get_posts( $args );
echo "<pre>";
if ( $posts ) {
foreach ( $posts as $post ) {
print_r($post->ID . "|" . $post->post_title . "\n");
}
}
echo "</pre>";
Code language: PHP (php)
It will output something like this:
9099|How to list recently edited pages in Hugo
9072|Moving from Docusaurus to Hugo
Code language: plaintext (plaintext)
Loop the database
From the database you just created, it would only make sense to loop it while creating the images.
const databaseContent = fs.readFileSync('./database.txt', { encoding: 'utf8', flag: 'r' });
const lines = databaseContent.split(/\r?\n/)
lines.forEach((line) => {
const content = line.split('|');
const id = content[0];
const text = content[1];
// Do stuff with the canvas
// Add text, colors, etc
// ...
});
Code language: JavaScript (javascript)
Overwrite Yoast SEO plugin output
By default the plugin will get the actual featured image from the post, you want to customize that output. Should you have placed the script inside your theme, you will also want this in your functions.php
file
function wp_open_graph_overwrite_YOAST( $url ) {
if (!is_singular('post')) {
return $url;
}
// Check if the file exists on disk
$image = '/image-generator/images/' . get_the_ID() . ".png";
$imageURL = get_stylesheet_directory_uri() . $image;
$imagePath = get_stylesheet_directory() . $image;
if (file_exists($imagePath)) {
return $imageURL;
}
return $url;
}
add_filter( 'wpseo_opengraph_image', 'wp_open_graph_overwrite_YOAST' );
Code language: PHP (php)
👨💻 Grab the complete code
Check out the GitHub repository: