Generating Cover Images for Hugo Blog Posts

Previously, if you shared a post on this site to a social networking site(Twitter, Facebook, etc) or chat software that crawls content for preview, it would usually show the title and introduction of the post, but it felt a bit bare and boring. If we can add a sharing picture, it should look more beautiful, but for me it is very tedious to find a picture that is not very relevant only for this purpose. So I thought about whether there is a way to automatically generate one? The answer is yes. I will explain the details later on, but you can take a look at the following picture first which was generated for this article you are reading on, and if you share this article to any social media website, the cover image below will appear.

cover

Examples

Actually, this feature is not rare, for example, some technical community sites have similar features, such as dev.to , Qiita and Zenn . If you share articles from these sites to social networks, a lovely cover image will be automatically generated with the title, author and other meta information of the article. For example, the following card is automatically generated by dev.to.

dev.to demo

Existing Tools

In order to avoid reinventing the wheel myself, I did some research, and there are some handy websites that can generate such cards, such as

The former is a more general solution that can be customized directly via URL parameters, while the latter automatically generates cover images for projects on GitHub.

Vercel’s tool looks perfect isn’t it? Except it doesn’t support CJK characters.

tcardgen

Since the above online solutions didn’t work for me, I then searched for offline tools, and I did find one by luck, the project is called tcardgen , coincidentally this developer also uses Hugo as a blog generator, the concept of the tool is not complicated, first of all, we need to prepare a template image, then the program reads the meta-information from the Front Matter part of the article, finally draws on the template image according to the specified font and the defined position, color, and other meta information. I slightly modified the code and the default template image provided by the author of that project to fit my own use case. Then I got this article’s cover image I posted at the beginning.

Below is how I run the command:

./tcardgen/tcardgen -f tcardgen/font -o ./content/posts/给博客文章自动生成分享图/cover..en.png -t tcardgen/template.png content/posts/给博客文章自动生成分享图/index.en.md

By the way, the font I used in the image was an open source font I picked from GitHub, called LXGW WenKai .

Open Graph

We are almost done, at least for the part of generating part. but how to get social networks or other software to recognize our cover images? it still needs a little extra work. fortunately, it’s not that complicated, just add Open Graph and Twitter Card related meta tags to the head of the HTML.

<meta property="og:image" content="http://blog.gimo.me/posts/auto-generating-cover-for-post/cover.png" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="http://blog.gimo.me/posts/auto-generating-cover-for-post/cover.png" />

Hugo Internal Templates

In fact, Hugo already ships internal templates to support Open Graph and Twitter Card, simply by introducing two lines into the theme’s template.

{{ template "_internal/opengraph.html" . }}
{{ template "_internal/twitter_cards.html" . }}

For those who are interested, you can directly read Hugo’s source code to figure out what happened behind the scenes. In short, the first 6 URLs from the images array defined in Front Matter are used for image metadata. If page bundles are used and the images array is empty or undefined, images with filenames matching feature or cover,thumbnail are used for image metadata. So in my case, I just simply name it cover.png

Final

Since I’ve successfully generated a cover image for a single post, why not apply for all others? I then just planned to write a small script to generate covers for all previous posts, acutally, I finished the task by using iPython shell to write a simple loop with a few built-in modules like glob and subprocess. All the changes are included in the commit: feat(cover): add cover for all posts · masakichi/[email protected] .

comments powered by Disqus