Social media preview images for static website
In this article, we’ll generate social media preview images for a static website in Ruby. In the end, we’ll be able to expose them in og:image
and twitter:image
meta tags.
We’ll add them to a blog generated by nanoc
framework. But the idea translates to other static site generators like Jekyll or even dynamic frameworks like Rails.
Here’s what we’ll have to do:
- generate an image,
- add it to
nanoc
compilation and - update the layout.
Generate image
We’ll take a background image and dynamically add a text on top of it. For that, we will use rmagick
gem. And then the Magick::Draw#annotate
method.
The dimensions of the background image should be 1200x630px and under 8MB according to the spec.
Lastly, we want to make sure that the text fits and if it’s longer it wraps properly.
require "rmagick"
class OpenGraphImage
def initialize(title, output_path)
@title = title
@output_path = output_path
end
def generate
image = Magick::Image.read("background.jpg").first
create = Magick::Draw.new
create.annotate(image, 0, 0, 3, 0, word_wrap(@title)) do |txt|
txt.font = 'SF-Pro-Display-Bold.otf'
txt.pointsize = 65
txt.font_weight = Magick::BoldWeight
txt.fill = 'white'
txt.gravity = Magick::CenterGravity
end
image.write("jpg:" + @output_path)
end
private
def word_wrap(line)
return line if line.length <= 26
line.gsub(/(.{1,26})(\s+|$)/, "\\1\n").strip
end
end
Add to nanoc compilation
Nanoc uses filters to manipulate files, so let’s create one that uses our OpenGraphImage
class. We are converting markdown files to images so the type of the filter is text: :binary
.
For the text, we’re using the article’s title.
class GenerateOpenGraphImage < Nanoc::Filter
identifier :generate_open_graph_image
type text: :binary
def run(content, params = {})
OpenGraphImage.new(item[:title], output_filename).generate
end
end
Then in our Rules
file, we’ll add another compilation rule. We can’t have two rules processing the same file unless we add a rep
to it. Since we’re generating jpegs let’s use rep:jpg
.
compile "/articles/**/*.md", rep: :jpg do
filter :generate_open_graph_image
write "/og/#{item.identifier.without_ext}.jpg"
end
Update layout
And the last thing missing is adding the new image paths to the head meta tags of the default layout.
<meta property="twitter:image" content="https://example.com<%= "/og/#{item.identifier.without_ext}.jpg" %>" />
<meta property="og:image" content="https://example.com<%= "/og/#{item.identifier.without_ext}.jpg" %>">
And we’re done. For each article, we are automatically generating the social media preview images.
A useful tool for debugging these previews are Facebook’s Sharing Debugger and Open Graph Preview.