Dynamically generated social media images.
This package creates dynamic images sized for social media tags (particularly Twitter and Facebook) based on your available pages. Use one of the predefined color themes, or define your own style, template, or both to customize the layout.
Configure the CLI script to run after your Eleventy build, and by default images will be created in _site/previews/
as png images. Use the CLI options to define a custom outputDir
and/or a custom imageDir
.
The images are only created in your output directory since the process runs after the Eleventy build is complete.
The window size used for the screenshot is 600px wide by 315px tall (which is then saved at 2x resolution) which you can use to test your template and styles if you choose to create them custom.
🧪 If you find a problem please add an issue. This has been tested on local builds and within Netlify, but needs broader tests by the community. Thanks to the contributors!
First, install the package:
npm install @11tyrocks/eleventy-plugin-social-images
There are three steps to using this package:
- Setup the command line script and add it to your Eleventy build
- Generate a JSON file containing data for each page you want social images
- Include a reference to the image in your templates
If you're using a host with continuous integration (like Netlify) you will also need to amend the build script you provide to your host to add the following and ensure Chrome headless is successfully launched for use by Puppeteer in the pipeline:
AWS_LAMBDA_FUNCTION_NAME=trickpuppeteer npm run build
Technically, this package offers a plugin component, but most of the functionality is added by calling the command line script.
The minimum setup for the cli script is:
eleventy-social-images --siteName 'Your Site Name'
It's recommended to add this after building Eleventy for production to reduce strain on your system when in serve
mode, for example by adding the following in your package.json
:
"scripts": {
"social-images": "eleventy-social-images --siteName 'Your Site Name'",
"start": "eleventy --serve",
"build": "eleventy ; npm run social-images"
}
The Eleventy plugin itself is only providing an optional filter to help format titles within the required JSON file.
The filter is called addNbsp
and it inserts a non-breaking space - nbsp;
- between the last two words in the title to prevent a single word dangling on the last line (called an "orphan" by typographers).
See the next section for how to add the plugin.
To create the required page data JSON, here is a starting template that loops through the all
collection and includes the two expected keys: title
and imgName
.
Important: Be sure to add the full path of your pages.json
file to either .gitignore
or .eleventyignore
to prevent an infinite loop when Eleventy is in --serve
mode.
- This should be created as a Nunjucks template, ex.
pagesjson.njk
so that it is recognized by Eleventy for processing. - Place this either at the root of your input directory, or in a custom directory in your input folder (ex.
_generate
). - Note the unique frontmatter, which essentially mean "do not include this in the normal site output".
- If you have customized your input directory via your Eleventy config, you may want to change the
permalink
value because it is relative to your project root, not the directory where it is placed. - The example uses the
addNbsp
filter which is optional - see the next section for how to include the plugin and gain access to that filter. - When the
addNbsp
filter is used, you must also includesafe
to allow thenbsp;
to be successfully included. slug
is a built-in Eleventy filter that will for example transform 'Hello World' into 'hello-world'
---
permalink: "./pages.json"
permalinkBypassOutputDir: true
eleventyExcludeFromCollections: true
---
[
{%- for pages in collections.all %}
{
"title":"{{ pages.data.title | addNbsp | safe }}",
"imgName":"{{ pages.data.title | slug }}"
}{% if loop.last == false %},{% endif -%}
{% endfor %}
]
You may modify what is used as the values based on your own naming convention and permalink structure. You may need to scope it to a particular collection vs. all
. Check out the 11ty docs on collections >
Added in v0.3.0 - include additional variables to pass into a custom template, such as:
[
{%- for pages in collections.all %}
{
"title":"{{ pages.data.title | addNbsp | safe }}",
"imgName":"{{ pages.data.title | slug }}",
"variables": {
"postdate": "{{ pages.data.postdate }}"
{%- if pages.data.description %},
"description": "{{ pages.data.description }}"
{% endif %}
}
}{% if loop.last == false %},{% endif -%}
{% endfor %}
]
Use in your template by adding data attributes to elements that should contain the variable value. For example <p data-postdate></p>
where you want the postdate
to appear.
Unavailable variables will simply produce empty elements. If you find the empty elements are impacting your template styles, remove them via CSS with the :empty
selector, ex p:empty { display: none }
.
Kudos to Thomas Michael Semmler for initiating the variables
functionality!
As noted previously, the plugin enables the addNbsp
filter.
Install the plugin in your 11ty project:
Then, include it in your .eleventy.js
config file:
const socialImages = require("@11tyrocks/eleventy-plugin-social-images");
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(socialImages);
};
The final step is up to you, which is placing the social media tags for you preferred services in the <head>
of your Eleventy templates.
Here are Nunjuck examples of including the image for both Twitter and Facebook - both of which require additional tags for full social share functionality. Check out my 11ty Netlify Starter for full tags for these services.
{%- set pageSocialImg %}{{ meta.url }}/previews/{{ title | slug }}.png{% endset
-%}
<meta property="og:image" content="{{pageSocialImg}}" />
<meta name="twitter:image" content="{{pageSocialImg}}" />
Note that the compiled image URL needs to be a full, absolute URL in order to work correctly for the social services. In this example, taken from my 11ty Netlify Jumpstart, meta.url
is defined in _data/meta.js
, such as:
module.exports = {
url: process.env.URL || "http://localhost:8080",
};
Where the env.URL
is provided by Netlify at build time. Your host may offer a similar option, or you may choose to hardcode your live URL into the tag.
Option | Type | Default |
---|---|---|
siteName | string | 11ty Rocks! |
outputDir | string | _site |
imageDir | string | previews |
dataFile | string | pages.json |
templatePath | string | |
stylesPath | string | |
theme | enum: 'blue' | 'green' | 'minimal' | 'sunset' | 'pop' | blue |
width | number | 600 |
height | number | 315 |
deviceScaleFactor | number | 2 |
The defaults are setup to assume Eleventy build defaults. So, the images will be created in _site/previews/
as png images, and expect your pages.json
to live at the project root.
If you have set a custom output
directory, then also update outputDir
, ex: --outputDir public
.
Preview the predefined themes >
To select, from one of the predefined themes, pass --theme [themename]
where themename
is one of the following:
- blue (default)
- green
- minimal
- sunset
- pop
By default, this plugin will create social images that are 600px wide and 315px tall. To choose different dimensions, pass --width
and --height
arguments, as in --width 1280 --height 720
.
The default device scale factor (or device pixel ratio) is 2, emulating high-dots-per-inch/Retina displays. To change the device scale factor, you can pass ---deviceScaleFactor
, as in --deviceScaleFactor 1
.
To define another name for your images to live, pass the directory name without the output path, ex: --imageDir img
.
Reminder: The images are only created in your output directory since the process runs after the Eleventy build is complete.
To use your own stylesheet, create a CSS file anywhere in your project. Then, pass the path like --stylesPath social/style.css
.
Your stylesheet will then be used instead of the default one.
Note on web fonts: For best results ensuring the web font loads for the screenshot, use the CSS @import
option within your stylesheet.
To use your own template, create an html file in your project. You may want to exclude it from Eleventy to prevent it being built as a page by adding it to .eleventyignore
or placing it outside of your customized input directory.
Then, pass the path like --templatePath social/template.html
.
Your template will then be used instead of the default one.
Refer back to custom template variables for how to enable additional template data.
You must include an h1
to be used as the hook to replace the title of the content. The rest of the template is up to you!
Include the following so that the stylesheet can be injected into the template:
<style>
{{ style }}
</style>
If you are not customizing the entire stylesheet but would like to alter part of it, such as the h1
size, you can add that singular style after {{ style }}
to override the defaults thanks to the CSS cascade.
To use a custom template but keep using a predefined theme, add a class
value on <body>
with your preferred theme value.
You can pass both a custom template and stylesheet by defining both CLI options, ex. --templatePath social/template.html --stylesPath social/style.css
.
Since this full example includes style, the only option missing is theme
since it would have no additional effect.
eleventy-social-images --siteName 'My Cool Site' --outputDir public --dataFile src/_generate/pages.json --imageDir imgs --templatePath social/template.html --stylesPath social/style.css --width 1280 --height 720 --deviceScaleFactor 1
If you use WSL, you'll need a browser. Install chrome in WSL by doing:
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo apt -y install ./google-chrome-stable_current_amd64.deb
You can confirm this worked by doing google-chrome --version
.
Hi - I'm Stephanie Eckles (@5t3ph), creator of 11ty.Rocks and the other resources compiled there.
If you enjoy my work and use my projects, please consider buying me a coffee.
This plugin is an adaptation for my solution originally detailed in this blog post and included in my 11ty Netlify Jumpstart. It's in active use on my 11ty-based sites:
The included gradient themes inspired by uiGradients
- @tomquinonero for adding WSL support
- @BenDMyers for updating to allow custom user dimensions
- @nachtfunke for adding template variables for better customization