UNPKG

eleventy-plugin-og-image

Version:

A plugin to create Open Graph Images from JSX for Eleventy.

197 lines (141 loc) 9.9 kB
# 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 `<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`: ![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 <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).