Astro integration to generate Social Images from Astro Content Collections with custom blurry background that can be loaded via frontmatter.
npm i @cyberkoalastudios/og-image-generator
- Create a new file in your
src/pages/
directory. For example,src/pages/custom-open-graph/[...route].ts
. - Use the
OGDynamicImageRoute
helper to creategetStaticPaths
andget
functions for you:
import {OGDynamicImageRoute} from '@cyberkoalastudios/og-image-generator';
import {getCollection} from "astro:content";
// (Optional) Example of filtration by current month and non draft posts.
const nonDraftFreshArticlesEntries = await getCollection('articles', ({ data }) => {
const currentDate = new Date();
const monthNumber = currentDate.getMonth();
if (data.pubDate?.getMonth() == monthNumber) {
return data.draft !== true;
}
});
export const {getStaticPaths, get} = OGDynamicImageRoute({
// Tell us the name of your dynamic route segment.
// In this case it’s `route`, because the file is named `[...route].ts`.
param: 'route',
// (Optional) CollectionEntries (array of content collection)
// If you want generate only filtered posts from collection
collection: nonDraftFreshArticlesEntries,
// A collection of pages to generate images for.
// This can be any map of paths to data, not necessarily a glob result.
pages: await import.meta.glob('/src/content/articles/**/*.md', {eager: true}),
// For each page, this callback will be used to customize the OpenGraph
// image. For example, if `pages` was passed a glob like above, you
// could read values from frontmatter.
getImageOptions: (path, page) => ({
title: page.frontmatter.title,
description: page.frontmatter.description,
logo: {
path: './src/favicon.png',
},
backgroundImage: {
url: page.frontmatter.image?.url,
alpha: 0.2,
blurStrength: 3,
},
// There are a bunch more options you can use here!
bgGradient: [[26, 26, 26], [24, 24, 24]],
/** Border config. Highlights a single edge of the image. */
border: {
/** RGB border color, e.g. `[0, 255, 0]`. */
color: [76, 0, 153],
/** Border width. Default: `0`. */
width: 15,
/** Side of the image to draw the border on. Inline start/end respects writing direction. */
side: "block-end",
},
font: {
title: {
families: ['Open Sans','Ubuntu','Istok Web','Source Sans Pro', 'PT Serif', 'Andika']
},
description: {
families: ['Open Sans','Ubuntu','Istok Web','Source Sans Pro', 'PT Serif', 'Andika']
}
},
}),
});
Example of post.md
:
---
title: My test post
author: LRN4
description: "CyberKoala LLC"
image:
url: "https://via.placeholder.com/1920x1080"
alt: "Image alt"
pubDate: 2023-06-01
tags: ["vr","education","tech"]
draft: false
---
# Rate this package
Some text
Your getImageOptions
callback should return an object configuring the image to render. Almost all options are optional.
export interface OGImageOptions {
/** Page title. */
title: string;
/** Short page description. */
description?: string;
/** Writing direction. Default: `'ltr'`. Set to `'rtl'` for Arabic, Hebrew, etc. */
dir?: 'rtl' | 'ltr';
/** Optional site logo. Displayed at the top of the card. */
logo?: {
/** Path to the logo image file, e.g. `'./src/logo.png'` */
path: string;
/**
* Size to display logo at.
* - `undefined` — Use original image file dimensions. (Default)
* - `[width]` — Resize to the specified width, height will be
* resized proportionally.
* - `[width, height]` — Resized to the specified width and height.
*/
size?: [width?: number, height?: number];
};
/** Optional background image. Displayed as cover of the card. */
backgroundImage?: {
size?: [width?: number, height?: number];
/** Path to the bg image file, e.g. `'./src/bg.png'` or `page.frontmatter.image?.url`*/
url: string;
};
/**
* Array of `[R, G, B]` colors to use in the background gradient,
* e.g. `[[255, 0, 0], [0, 0, 255]]` (red to blue).
* For a solid color, only include a single color, e.g. `[[0, 0, 0]]`
*/
bgGradient?: RGBColor[];
/** Border config. Highlights a single edge of the image. */
border?: {
/** RGB border color, e.g. `[0, 255, 0]`. */
color?: RGBColor;
/** Border width. Default: `0`. */
width?: number;
/** Side of the image to draw the border on. Inline start/end respects writing direction. */
side?: LogicalSide;
};
/** Amount of padding between the image edge and text. Default: `60`. */
padding?: number;
/** Font styles. */
font?: {
/** Font style for the page title. */
title?: FontConfig;
/** Font style for the page description. */
description?: FontConfig;
};
/** Array of font URLs to load and use when rendering text. */
fonts?: string[];
}
export interface FontConfig {
/** RGB text color. Default: `[255, 255, 255]` */
color?: RGBColor;
/** Font size. Title default is `70`, description default is `40`. */
size?: number;
/** Font weight. Make sure you provide a URL for the matching font weight. */
weight?: Exclude<keyof CanvasKit['FontWeight'], 'values'>;
/** Line height, a.k.a. leading. */
lineHeight?: number;
/**
* Font families to use to render this text. These must be loaded using the
* top-level `fonts` config option.
*
* Similar to CSS, this operates as a “font stack”. The first family in the
* list will be preferred with next entries used if a glyph isn’t in earlier
* families. Useful for providing fallbacks for different alphabets etc.
*
* Example: `['Noto Sans', 'Noto Sans Arabic']`
*/
families?: string[];
}
Great now you should be done!🎉 Deploy your site and test it out. Great site for testing this out is Open Graph previewer.
Useful examples of content collections and improvements via Json LD in Astro