@reunmedia/astro-og-images v0.2.0
Astro OG Images
Yet another Astro integration to generate Open Graph images. More lightweight than most alternatives.
Only static build and dev mode are currently supported, but since dev mode uses on-demand rendering, a custom SSR implementation is possible.
Getting started
Install package
Usng astro add:
pnpm astro add @reunmedia/astro-og-imagesManually:
pnpm add @reunmedia/astro-og-imagesConfigure integration
// astro.config.mjs
import { defineConfig } from "astro/config";
import ogImages from "@reunmedia/astro-og-images";
import { readFile } from "fs/promises";
export default defineConfig({
// OpenGraph images require a valid site configuration
site: "https://example.com",
integrations: [
ogImages({
// At least one font is required
fonts: [
{
name: "Roboto",
data: await readFile(
"./node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff",
),
},
],
}),
],
});See IntegrationOptions.ts for more
configuration options.
Usage
See Playground for a complete Astro example project.
Create a template
// src/ogImageTemplates/myTemplate.ts
import { html } from "@reunmedia/astro-og-images";
export default function myTemplate(text: string) {
return html`
<div style=${{ display: "flex" }}>
<p>${text}</p>
</div>
`;
}See Playground templates for additional examples.
Astro OG Images uses htm for templating by
default to avoid requiring React as a dependency, but you may use
JSX as well.
Add image OpenGraph property
---
import { ogImage } from "@reunmedia/astro-og-images";
import myTemplate from "../ogImageTemplates/myTemplate";
// ogImage returns absolute URL to rendered image
const image = await ogImage(myTemplate("Hello World!"));
---
<html lang="en">
<head>
<meta property="og:image" content={ogImage} />
</head>
...
</html>Since ogImage() simply returns an absolute URL, you can use the images for
other purposes such as oEmbed.
Preview images during development
In development mode, ogImage() returns the full rendered image as a base64
encoded data URL. This allows you to preview the images during development using
various OpenGraph preview tools. You can even create your own image preview
using <img> tag:
---
import { ogImage } from "@reunmedia/astro-og-images";
import myTemplate from "../ogImageTemplates/myTemplate";
const image = await ogImage(myTemplate("Hello World!"));
---
<img style="max-width: 100%;" src={image} />Previewing template as HTML
If you're not using React or Preact and want to preview template HTML during development, you can do so by following these steps:
- Install dependencies to render template to HTML
pnpm add -D preact preact-render-to-string htm- Add custom compiler parameter to your template
// src/ogImageTemplates/myTemplate.ts
import { html } from "@reunmedia/astro-og-images";
import type { Compiler } from "@reunmedia/astro-og-images";
export default function myTemplate(text: string): ReturnType<typeof html>;
export default function myTemplate<T>(text: string, compiler: Compiler<T>): T;
export default function myTemplate<T>(text: string, compiler?: Compiler<T>) {
return (compiler || html)/* html */ `
<div style=${{ display: "flex" }}>
<p>${text}</p>
</div>
`;
}If you don't want to add the compiler parameter, you can alternatively just
temporarily change the html compiler in the template:
// src/ogImageTemplates/myTemplate.ts
// import { html } from "@reunmedia/astro-og-images";
import { html } from "htm/preact";- Compile template using
htm/preactcompiler, render template usingpreact-render-to-stringand pass it toOgTemplatePreview.astrocomponent. It's best to use a blank page to prevent global CSS from affecting the template.
---
// src/pages/og-preview.astro
import { html } from "htm/preact";
import { render } from "preact-render-to-string";
import { OgTemplatePreview } from "@reunmedia/astro-og-images/components";
import myTemplate from "../ogImageTemplates/myTemplate";
const preactTemplate = myTemplate("Hello World!", html);
const templateHtml = render(preactTemplate);
---
<body style={{ margin: 0 }}>
<OgTemplatePreview templateHtml={templateHtml} />
</body>You should also always preview the rendered image, because some HTML may be rendered differently by Satori.
Motivation
There are multiple OpenGraph image integrations for Astro already. Here's why this one exists:
- Uses sharp instead of resvg-js to render Satori SVG to PNG. Astro already uses sharp for image processing, so it makes sense to use the same package for OpenGraph images as well.
- Doesn't require (but supports) React. If you don't use React (or Preact),
pulling a complete framework as a dependency just for OpenGraph images seems
ovekill. Since Satori also supports
"React-elements-like objects"
in addition to JSX, we use htm with a
custom renderer instead. JSX is supported by simply passing a
JSX template to
ogImage(). - Doesn't rewrite output HTML and you get the URL before build is done. Other
integrations work by manipulating
og:imagetags in the built HTML files. This makes it impossible to use the same (or different) image withoEmbedfor example. Since this library gives you the resulting URL beforehand, you can even do things like display the image in<img>tag. - Allows you to preview OG images during development. This feature is not unique to this library, but our implementation provides more flexibility.