Earlier this year, I was thinking a lot about preview images, both for personal websites and elsewhere on the web. I was inspired by GitHub and Product Hunt's meta images that are customised per repository and project, respectively. I was also inspired by the work that Zach Leatherman had done for screenshots on his personal website, for which he built a service that you can use to generate meta images that were a screenshot of a personal website.
I was curious about how I could generate screenshots for my personal website. I knew this would involve headless browsers, a technology wherein a browser renders a page programmatically without a user-facing representation available. I had not yet used headless browsers, so I thought this would be an excellent opportunity to build my knowledge.
Using express.js, I built a web application that accepts a URL and the height and width of the desired image. This application renders the provided URL in Puppeteer, a tool for rendering web pages in a headless browser. I use controls made available by the Puppeteer API to take a screenshot of the page at the desired resolution, and then save that image to a file. The image is then served to the user. If an image has already been generated, that image is served to the user instead of retrieving it again. There is a URL parameter you can pass to clear the cache so that if you change a page you can remove the saved version and generate a new one.
To use the screenshot service, I have the following line of code on pages across websites I run:
<meta property="og:image" content="https://screenshots.jamesg.blog/?url=https://jamesg.blog/">
This code sets the Open Graph meta image for my web page to point to the screenshot service.
When you load my home page in an application that supports showing Open Graph meta images (i.e. Discord), you will see a screenshot of the page to which the link points:
Generating and serving a screenshot for the first time can take a few seconds, so this image doesn't show up instantly for which an image has not already been generated.
My screenshot service is available as an open source project on GitHub. You can set a list of domains that you want to whitelist so that the service can only generate screenshots for your web properties. For example, I allow the service to generate screenshots on any
jamesg.blog website and
breakfastand.coffee, my site for sharing breakfast eateries and coffee shop recommendations.
While open source services out there already exist for this, I learned a lot during this project and was able to build up more knowledge of working with express.js, a technnology that I have since used more. I hope this project is useful to you!
(There is an encoding issue where emojis don't show up properly in the headless browser. I need to dig into this!)
Comment on this post
Respond to this post by sending a Webmention.
Have a comment? Email me at firstname.lastname@example.org.