An open API service indexing awesome lists of open source software.

https://github.com/kiwikilian/eleventy-plugin-og-image

Create Open Graph images in Eleventy using your templates, data and CSS. Fast and reproducible, without a headless browser.
https://github.com/kiwikilian/eleventy-plugin-og-image

eleventy eleventy-plugin

Last synced: 8 months ago
JSON representation

Create Open Graph images in Eleventy using your templates, data and CSS. Fast and reproducible, without a headless browser.

Awesome Lists containing this project

README

          

# Eleventy Plugin OG Image [![npm](https://img.shields.io/npm/v/eleventy-plugin-og-image?color=blue)](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 `` 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;
}


{{ title }}



```

Call the `ogImage` shortcode inside the `` 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`:

![Generated OG image](./assets/og-image.png)

HTML output generated by the shortcode into `_site/example-page/index.html` (can be modified via the `shortcodeOutput` option):

```html

```

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).