When I recently rebuilt my website and blog from scratch, I also created a little web service that lets me dynamically generate social media preview images (or og images, open graph images) that contain the title of the respective post or page in a big font:
Thanks to Puppeteer, this service was super-easy to build. Here is what I did:
I first created a little website that displays whatever text it gets passed as the text
query parameter in a big font. The text is
put inside a div
that's 1200x630 in size:
The code for that site looks something like this:
// GET https://og.maxschmitt.me/og-image?text={url-encoded-text}app.get('/og-image', (req, res, next) => {const { text } = req.queryres.render('og-image.html', { text })})
Next, I created another site that takes a screenshot of the HTML page above and returns it as a png-image. This dynamic image page is what I include in my meta tags to point to the social media preview images:
<metaname="twitter:title"content="Writing a static site generator with MDX & Webpack - Max Schmitt"/><metaproperty="og:image"content="https://og.maxschmitt.me/Writing%20a%20static%20site%20generator%20with%20MDX%20%26%20Webpack.png"/><metaname="twitter:image"content="https://og.maxschmitt.me/Writing%20a%20static%20site%20generator%20with%20MDX%20%26%20Webpack.png"/><meta name="twitter:card" content="summary_large_image" />
The code to take the screenshot is very simple:
// GET https://og.maxschmitt.me/{url-encoded-text}.pngapp.get('/:text.png', async (req, res, next) => {try {const { text } = req.paramsconst image = await getOGImageForText(text)res.send(image)} catch (err) {next(err)}})async getOGImageForText(text) {const urlencodedText = encodeURIComponent(text)const browser = await puppeteer.launch();const page = await browser.newPage()await page.goto(`http://localhost:${process.env.PORT}/og-image?text=${urlencodedText}`)const ogImageElement = await page.$('#og-image')const image = await ogImageElement.screenshot()await page.close()return image}
Check out the full source code on GitHub.
The og image service is hosted on my Dokku instance.
If you plan on doing something similar, make sure to check the Puppeteer docs on how to run Puppeteer inside Docker.
If you're interested in getting started with Dokku, check out my in-depth tutorial on how to deploy apps and websites with Dokku.
Hi, I’m Max! I'm a fullstack JavaScript developer living in Berlin.
When I’m not working on one of my personal projects, writing blog posts or making YouTube videos, I help my clients bring their ideas to life as a freelance web developer.
If you need help on a project, please reach out and let's work together.
To stay updated with new blog posts, follow me on Twitter or subscribe to my RSS feed.