eleventy-plugin-og-image
Version:
A plugin to create Open Graph Images from JSX for Eleventy.
197 lines (141 loc) • 9.9 kB
Markdown
# Eleventy Plugin OG Image [](https://www.npmjs.com/package/eleventy-plugin-og-image)
This plugin helps to create Open Graph images in [Eleventy](https://www.11ty.dev/) using HTML[^1] within any supported template language and CSS[^2] via [satori](https://github.com/vercel/satori). No headless browser will be harmed 😉.
## Usage
Install the package:
```shell
npm install eleventy-plugin-og-image --save-dev
```
### ESM
It's preferred to use this plugin within ESM Eleventy projects. Read more about ESM vs CommonJS on the [Eleventy documentation](https://www.11ty.dev/docs/cjs-esm/).
```js
import EleventyPluginOgImage from 'eleventy-plugin-og-image';
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',
},
],
},
});
}
```
### CommonJS
> [!NOTE]
> This plugin is written in ESM, therefore `require` is not possible. If the .eleventy.js config uses CommonJS, switch to async and create a dynamic import as shown below.
```js
module.exports = async function (eleventyConfig) {
const EleventyPluginOgImage = (await import('eleventy-plugin-og-image')).default;
eleventyConfig.addPlugin(EleventyPluginOgImage, {
// See above for example config
});
};
```
### Add a Template
Create an OG-image-template anywhere in the input directory. Use only the supported HTML elements[^1] and CSS properties[^2]. CSS in `<style>` tags will be inlined, remote images fetched. [Shortcode scoped data](https://www.11ty.dev/docs/shortcodes/#scoped-data-in-shortcodes) from the parent template is available. Additionally, some options will be available in the `eleventyPluginOgImage` key. This is an example `og-image.og.njk`:
```njk
<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>
```
Call the `ogImage` shortcode inside the `<head>` in a template or layout. The first argument is the `filePath` of the OG-image-template (required, relative to the Eleventy input directory). The second argument is for `data` (optional). Usage example in Nunjucks, e.g. `example-page.njk`:
```njk
{% ogImage "./og-image.og.njk", { title: "Hello World!" } %}
```
### Result
Generated OG image `_site/og-images/s0m3h4sh.png`:

HTML output generated by the shortcode into `_site/example-page/index.html` (can be modified via the `shortcodeOutput` option):
```html
<meta property="og:image" content="/og-images/s0m3h4sh.png" />
```
For applied usage see the [example](./example).
> [!TIP]
> The template language of the page and OG-image-template can be mixed or matched.
## Configuration
The following options can be passed when adding the plugin:
| Property | Type | Default | |
| --------------------- | -------------------------------------------------------------------------------------------------------- |-------------------------------------------|--------------------------------------------------------------------------------------------|
| `inputFileGlob` | `glob` | `**/*.og.*` | This must match the OG-image-templates to prevent HTML compilation. |
| `hashLength` | `number` | `8` | |
| `outputFileExtension` | [sharp output file formats](https://sharp.pixelplumbing.com/api-output#toformat) | `png` | |
| `outputDir` | `string` | `og-images` | Directory into which OG images will be emitted. Relative to eleventy `output`. |
| `previewMode` | `auto \| boolean` | `auto` | Enable/disable preview mode. |
| `previewDir` | `string` | `${outputDir}/preview` | Directory used for preview during `watch` or `serve`. Relative to eleventy `output`. |
| `urlPath` | `string` | `${outputDir}` | URL-prefix which will be used in returned meta-tags. |
| `outputFileSlug` | `function` | [See source](src/utils/mergeOptions.js) | Generation of the output file slug, must be url safe and exclude the file extension. |
| `shortcodeOutput` | `function` | [See source](src/utils/mergeOptions.js) | Change the HTML returned by the shortcode in pages. |
| `satoriOptions` | [satori options](https://github.com/search?q=repo:vercel/satori+%22export+type+SatoriOptions%22&type=code) | `{ width: 1200, height: 630, fonts: [] }` | If an OG-image-template contains text, it's **required** to load a font ([example](#esm)). |
| `sharpOptions` | [sharp output options](https://sharp.pixelplumbing.com/api-output#toformat) | `undefined` | Options must be corresponding to chosen `outputFileExtension`. |
| `OgImage` | `class CustomOgImage extends OgImage` | [`OgImage`](src/OgImage.js) | [Extend the `OgImage`](#extending-ogimage-class) class for maximum customization. |
## Preview Mode
The previewMode is intended to ease the styling of OG images. When `previewMode` is set to `auto` (default) the OG images are also copied into the `previewDir` during development with `watch` or `serve`. The files are named by the url slug of the pages they are generated from. Next to it there is a HTML placed which shows the generated HTML, SVG and output image. The `previewDir` will be deleted during a production build. When not actively working on OG images, performance can be improved by disabling `previewMode`.
## Caching
For better performance OG images are cached based on a hash from generated HTML and output options. If the file already exists, further transformations are skipped.
## Advanced Usage
### Extending OgImage Class
It's possible to extend and overwrite any of the functions from the [`OgImage`](src/OgImage.js) class. The custom class is passed as the `OgImage` parameter to the plugin.
```js
import EleventyPluginOgImage from 'eleventy-plugin-og-image';
import { OgImage } from 'eleventy-plugin-og-image/og-image';
export class CustomOgImage extends BaseOgImage {
async shortcodeOutput() {
return this.outputUrl();
}
}
/** @param {import('@11ty/eleventy/src/UserConfig').default} eleventyConfig */
export default async function (eleventyConfig) {
eleventyConfig.addPlugin(EleventyPluginOgImage, {
OgImage: CustomOgImage,
});
}
```
### Custom Shortcode
A custom shortcode can be created by using the `OgImage` class.
```js
import { OgImage } from 'eleventy-plugin-og-image/og-image';
const image = await new OgImage({ inputPath, data, options, templateConfig }).render();
```
### Capture Output URL
The plugins shortcode create a `meta` tag per default, modify the `shortcodeOutput` option or class function to directly return the `outputUrl`:
```js
eleventyConfig.addPlugin(EleventyPluginOgImage, {
async shortcodeOutput(ogImage) {
return ogImage.outputUrl();
},
});
```
Furthermore, it's possible to capture the `outputUrl` to a variable, e.g. in Nunjucks:
```njk
{% setAsync "ogOutputUrl" -%}
{% ogImage "./og-image.og.njk", { title: "Hello World!" } %}
{%- endsetAsync %}
```
And use it anywhere afterward with `{{ ogOutputUrl }}`.
## Acknowledgements & Attributions
This plugin is deeply inspired by [@vercel/og](https://vercel.com/docs/concepts/functions/edge-functions/og-image-generation).
Furthermore, it would not be possible without:
- [satori](https://github.com/vercel/satori)
- [resvg](https://github.com/RazrFalcon/resvg/)/[resvg-js](https://github.com/yisibl/resvg-js)
- [sharp](https://github.com/lovell/sharp)
[^1]: Only a subset of HTML elements is [supported by satori](https://github.com/vercel/satori#html-elements).
[^2]: Only a subset of CSS properties are supported by [yoga-layout](https://github.com/facebook/yoga), which is [used by satori](https://github.com/vercel/satori#css).