astro-og-canvas
This package provides utlities to generate OpenGraph images for the pages on your Astro site.
Installation
npm i astro-og-canvas
Using pnpm
? pnpm
users will also need to install canvaskit-wasm
as a direct dependency:
pnpm i canvaskit-wasm
Version compatibility
Usage
Creating an OpenGraph image endpoint
-
Create a new file in your src/pages/
directory. For example, src/pages/open-graph/[...route].ts
.
-
Use the OGImageRoute
helper to create getStaticPaths
and GET
functions for you:
import { OGImageRoute } from 'astro-og-canvas';
export const { getStaticPaths, GET } = OGImageRoute({
param: 'route',
pages: {
'example': {
title: 'Example Page',
description: 'Description of this page shown in smaller text',
}
},
getImageOptions: (path, page) => ({
title: page.title,
description: page.description,
logo: {
path: './src/astro-docs-logo.png',
},
}),
});
Generating pages
from a content collection
If you want to generate images for every file in a content collection, use getCollection()
to load your content entries and convert the entries array to an object.
The following example assumes a content collection schema with title
and description
keys in the frontmatter.
import { getCollection } from 'astro:content';
import { OGImageRoute } from 'astro-og-canvas';
const collectionEntries = await getCollection('my-collection');
const pages = Object.fromEntries(collectionEntries.map(({ slug, data }) => [slug, data]));
export const { getStaticPaths, GET } = OGImageRoute({
param: 'route',
pages: pages,
getImageOptions: (path, page) => ({
title: page.title,
description: page.description,
}),
});
Generating pages
from Markdown files
If you have a folder of Markdown files with title
and description
fields in their frontmatter, use import.meta.glob()
to load and pass these to the pages
option of OGImageRoute
.
In the following example, every Markdown file in the project’s src/pages/
directory is loaded and will have an image generated for them:
import { OGImageRoute } from 'astro-og-canvas';
export const { getStaticPaths, GET } = OGImageRoute({
param: 'route',
pages: await import.meta.glob('/src/pages/**/*.md', { eager: true }),
getImageOptions: (path, page) => ({
title: page.frontmatter.title,
description: page.frontmatter.description,
}),
});
Generating pages
from other data sources
pages
can be any object you want. Its keys are used to generate the final route, but other than this, how you use it is up to you, so you can generate images from any data you like.
Pokémon API example
The following example fetches some data about Pokémon using the PokéAPI and then uses that to generate images:
import { OGImageRoute } from 'astro-og-canvas';
const { results } = await fetch('https://pokeapi.co/api/v2/pokemon/').then((res) => res.json());
const pokemon = {};
for (const { url } of results) {
const details = await fetch(url).then((res) => res.json());
pokemon[details.name] = details;
}
export const { getStaticPaths, GET } = OGImageRoute({
pages: pokemon,
getImageOptions: (path, page) => ({
title: page.name,
description: `Pokémon #${page.order}`,
}),
});
Image Options
Your getImageOptions
callback should return an object configuring the image to render. Almost all options are optional.
export interface OGImageOptions {
title: string;
description?: string;
dir?: 'rtl' | 'ltr';
logo?: {
path: string;
size?: [width?: number, height?: number];
};
bgGradient?: RGBColor[];
border?: {
color?: RGBColor;
width?: number;
side?: LogicalSide;
};
bgImage?: {
path: string;
fit?: 'cover' | 'contain' | 'none' | 'fill';
position?: LogicalPosition | [LogicalPosition, LogicalPosition];
};
padding?: number;
font?: {
title?: FontConfig;
description?: FontConfig;
};
fonts?: string[];
cacheDir?: string | false;
}
FontConfig
export interface FontConfig {
color?: RGBColor;
size?: number;
weight?: Exclude<keyof CanvasKit['FontWeight'], 'values'>;
lineHeight?: number;
families?: string[];
}
License
MIT