Now with Dynamic Open Graph Images!
Inspired by GitHub’s pretty sweet post about their Open Graph images framework, I decided to try to build something similar for my site (at a smaller scale, obviously!). I wanted to build this for my blog ever since I saw the folks at Vercel do it.
I used Puppeteer to take a screenshot of a very simple HTML template, hooked it into my website’s deployment pipeline, and voilà: dynamic OG images!
There’s still some tweaks I wanna make to the template to make it nicer, but it’s looking clean!
I wrote generator code that gets executed as part of my next export
process, this is the full script:
import chromium from 'chrome-aws-lambda'
import format from 'date-fns/format'
import fs from 'fs'
import path from 'path'
import posts from './posts'
export async function generate ({ outDir }) {
const browser = await chromium.puppeteer.launch({
args: chromium.args,
executablePath: await chromium.executablePath,
headless: true
})
const page = await browser.newPage()
// Open the HTML template as a data URI
await page.goto(
`data:text/html;charset=UTF-8,${encodeURIComponent(TEMPLATE)}`,
{ waitUntil: 'networkidle0' }
)
// Wait until the document is fully rendered
await page.evaluateHandle('document.fonts.ready')
// Set the viewport size to match
await page.setViewport({
width: 1200,
height: 632,
// Netlify build machines do not have a
// retina display, apparently xD
deviceScaleFactor: process.env.NETLIFY ? 1 : 2
})
const ogImagesDir = path.resolve(outDir, OG_IMAGES_PATH)
// iterate over each post
for (const post of posts) {
const info = {
title: post.title,
date: format(post.date, 'dddd, MMMM Do, YYYY')
}
await page.evaluate((info) => {
const titleElement = document.querySelector('#title')
const dateElement = document.querySelector('#date')
titleElement.innerHTML = info.title
dateElement.innerHTML = info.date
}, info)
await page.screenshot({
path: `${ogImagesDir}/${post.id}.png`,
type: 'png',
clip: { x: 0, y: 0, width: 1200, height: 632 }
})
}
// Wrap it up
await browser.close()
}
This code heavily inspired by vercel/og-image’s code.