Generate Social Media Images Automatically
From day one of this blog I wanted to combine two of my passions: tech stuff and photography. All these photos I have shot myself in recent years and now they are representing my thoughts & findings about digital technology. I wrote about my approach to provide these images in my post Automatic Header Images in Hexo.
When I share one of my posts on social media I provide the appropriate image as a visual anchor to my writing. The technique behind this are the meta
tags in the HTML of my posts:
1 | <!-- Schema.org for Google --> |
There are several meta tags for different purposes regarding images. For more information see the links at the end of this post. To make a long story short: The sum of these approaches ensures that when an article is posted, the corresponding image is also displayed in the social media post.
But … it’s only the image, without a visual reference to the post itself. In this article I want to show you how to combine the photo with some meta information of the post automatically, to get a Social Media Image.
Starting point of my thoughts were two posts from Drew McLellan (Dynamic Social Sharing Images) and Ryan Filler (Automatic Social Share Images), to which I have already referred in my post Discoveries #11.
Drew and Ryan utilizes the Node.JS library Puppeteer, which runs a headless Chromium (or Chrome browser) over the DevTools protocol to process a web page … for example to take a screenshot:
1 | const puppeteer = require('puppeteer'); |
The idea is, to create a temporary HTML page with the photo and all necessary text for the social media image, take a screenshot of it and save it as PNG.
As I run my blog with Hexo, a Static Site Generator (SSG), all information about a post is defined in a Markdown (MD) file with some Frontmatter for the meta information.
Therefore, the Social Media Image Generator script in my mind had to do following tasks:
- Iterate recursively over all MD files in Hexo
_source/posts
folder - Read the MD’s Frontmatter (for information about photo, title, subtitle and more)
- Create a temporary HTML file with the aid of a template
- Run Puppeteer script over the temporary file to take a screenshot
- Store the PNG to a central folder
- Optimize the PNG
- Change the meta tags in the posts to reference the new image
The Frontmatter
I pimped the Frontmatter of the original Hexo configuration a bit, in order to provide an individual photo for each post:
1 |
|
Among other, there are the basic information, I wanted to have on my social media image: photograph.file
(as the image itself) and title
, subtitle
and categories
(for the text on the image).
The Script
The complete script, in two versions (CommonJS and ES Module) is available at GitHub.
tl;dr
My script became a JavaScript class
, separating the tasks in several methods and a constructor to get all necessary information as parameters. The class exports the main method generate()
for calling the script:
1 | const _currentPath = __dirname; |
I chose parameters, in order not to bind the script too tightly to my favourite SSG Hexo:
_postFolder
- Where are the post files stored?_photoFolder
- Where are the photos stored?_templateFile
- Where is the template file for the temporary HTML stored?_targetFolder
- Where should the generated PNG files be stored?
Get the posts
First task was to get all MD files out of the _postFolder
recursively:
1 | const fs = require("fs"); |
Get the template and the temporary folder
I chose Handlebars as the template engine to generate the temporary HTML file, because it is so easy to handle.
1 | <html> |
Handlebars is able to compile a template into a JavaScript variable, what makes it easy to reuse it. Good for performance and stability.
As I wanted to utilize the template to generate temporary HTML files, I needed a temporary folder, which can be deleted afterwards.
1 | const handlebars = require("handlebars"); |
Process the posts
Second step was to process all the posts found.
1 | const fs = require("fs"); |
Get the image
As I had the temporary HTML file now, I only had to open up a Puppeteer instance, load the file and take the screenshot:
1 | const puppeteer = require("puppeteer/cjs-entry"); |
Running the script
If you already have lots of post in MD files and appropriate photographs, you can create an execution script…
1 | const Generator = require("./social-media-image-generator.cjs").Generator; |
… and run it as follows:
1 | node "./lib/run-social-media-images.cjs" "../source/_posts" "../static/photos/normal" "../templates/social-media-image.handlebars" "../static/images/social-media" |
Hexo Integration
In case you are running your blog with Hexo also, you can hook on the ready
event to let it run on hexo generate
automatically:
1 | const log = require('hexo-log')({ |
It is important not to store the social-media-image-generator.cjs
in Hexo’s scripts
folder like the event script above, because Hexo will try to execute it automatically. You have to create a different folder like lib
to store and reference it from there.
The Result
Here is the result from my approach in Hexo, as I run hexo generate
for this blog post:

The very last thing I had to do, was to change the source of the image meta tag mentioned at the top, to reference to newly created social media image.
Here’s the new image in action at Twitter:
More Info
- CSS Tricks: The Essential Meta Tags for Social Media
- The Open Graph Protocol: The Open Graph Protocol
- Drew McLellan: Dynamic Social Sharing Images
- Ryan Filler: Automatic Social Share Images
- The GitHub Blog: A framework for building Open Graph images
You can interact with this article (applause, criticism, whatever) by mention it in one of your posts, which will also be shown here as a Webmention ... or you leave a good old comment with your GitHub account.
Webmentions
No Webmentions yet...
In case your blog software can't send Webmentions, you can use this form to submit me a mention of this article...
Comments