Open Graph (OG) Images represent your content on the web when shared. They are those little preview images displayed next to your link on social media, messengers or your journal app.
If you're not keen to create an OG Image manually for each of your pages on your Eleventy site, there are mainly two approaches to generate them:
- Create a HTML template, style with CSS and take a screenshot with a headless browser
- Create a SVG template, render it to a bitmap
First approach is easy to style but hard to render. Managing a headless browser can be a hassle at times. Second approach might be a bit harder to style, depending on your level of SVG knowledge, but is much more consistent to render.
Combining the best of both worlds let me introduce eleventy-plugin-og-image
– it is a shameless plug of my very first open source project. It allows to create OG images from HTML (or any template language supported by Eleventy) and CSS. Instead of a headless browser, satori
transforms your HTML to SVG, allowing a simple rendering to bitmap afterward. This is the complete render flow:
┌──────────┐
│ Template │─────────┐
├──────────┤ │
│ Data │─────Eleventy─────┬─────┐
├──────────┤ │ │ │
│ Styles │─────────┘ ▼ ▼
└──────────┘ ┌──────┬─────┐
│ HTML │ CSS │
└──────┴─────┘
│ │
┌────────┐ ┌─────┐ │ │
│ Bitmap │◀─resvg-js─│ SVG │◀─satori┘
└────────┘ └─────┘
How to setup eleventy-plugin-og-image
First install the package:
bash
npm install eleventy-plugin-og-image --save-dev
Afterward we add the plugin to our .eleventy.js
. Note, this example configuration already uses ESM with @11ty/eleventy@3.0.0
. You need to load all fonts, which are used in your OG-image-templates:
js
import EleventyPluginOgImage from 'eleventy-plugin-og-image';/** @param { import('@11ty/eleventy/src/UserConfig').default } eleventyConfig */export default async function (eleventyConfig) {eleventyConfig.addPlugin(EleventyPluginOgImage, {satoriOptions: {fonts: [{name: 'Inter',data: fs.readFileSync('../path/to/font-file/inter.woff'),weight: 700,style: 'normal',},],},});}
Now we create an OG-image-template og-image.og.njk
. It is easiest to place the CSS in a <style>
tag directly in your template:
twig
<style>.root {width: 100%;height: 100%;display: flex;flex-direction: column;align-items: center;background: linear-gradient(135deg, #ef629f, #eecda3);}.title {color: white;font-size: 80px;margin: auto 0;}</style><div class="root"><h1 class="title">{{ title }}</h1></div>
The styles will be inlined as style=""
attributes by the plugin. You can use remote images, which will be fetched during rendering. This template expects to get a title
attribute provided as data.
Last call the ogImage
shortcode inside your <head>
of a page template or layout. The first argument of the shortcode is the filePath
of the OG-image-template (required), second argument is for data
(optional). This is how it looks in a example-page.njk
:
twig
{% ogImage "./og-image.og.njk", { title: "Hello World!" } %}
This will create a bitmap _site/og-images/s0m3h4sh.png
in your output path:
The ogImage
shortcode generates the following HTML into the compiled _site/example-page/index.html
to actually embed your OG image:
html
<meta property="og:image" content="/og-images/s0m3h4sh.png" />
For more configuration and usage options see the docs. A basic example is also included in the project or find a rather more complex example in the implementation of this blog. I'm happy to hear your feedback in the repository!