We recently built a generator for Open Graph images that we use internally at ZEIT to provide rich content across our social media accounts. The generator harnesses the power of serverless, Puppeteer, and Now's built-in edge caching to provide high-quality content fast.

Our Motivation

We take pride in providing consistent content to our developer community at ZEIT, usually via this blog. Previously, our workflows involved coordinating with our design team in order to add accompanying Open Graph images to our content.
Since most of our social cards look somewhat homogenous, we decided to automate this process by eating our own dogfood and using our platform to meet this need. This takes a load off of our talented design team, and removes a dependency from our developer relations team allowing us to provide content more efficiently on the whole.

How it Works

Last month, we published a blog post on using Chrome with serverless. Our Open Graph image generator is one such example of this. The project processes user input, renders a card, and then takes a screenshot of it using Puppeteer, exactly as in the example.

User Interface

This application is entirely server-rendered, but does use a rendering engine that supports virtual DOM for UI updates. This is made possible using .dom which replicates concepts from popular UI libraries, but uses native JavaScript features to significantly reduce bundle size and associated tooling requirements.
Given that lambda size is an important metric on Now, .dom is a delightful tool of choice to render the User Interface of our Open Graph image generator, giving our lambas a tiny footprint, and allowing for an extremely cost-effective deployment.


In order to provide free, reproducible Open Graph images, we needed to use a font with a free and open source license. Elegant design is something that we strive for at ZEIT. After a considerable amount of research, we eventually decided on the Inter font family by Rasmus Andersson.
We appreciate this typeface because of the high degree of legibility it brings across a number of devices while maintaining a beautiful aesthetic and contextual alternatives: like a slash-filled zero when 0 needs differentiating from O.

Edge caching

Now makes use of caching servers to store your content closer to your users. This greatly reduces latency and causes content to reach a consumer as efficiently as possible, providing end-users with a pleasant experience.
In the case of our generator, every time a user generates an image, the image gets cached. Each subsequent user will receive the cached image directly from the caching server nearest to them until it expires. The lifetime of cached assets is configurable via route.headers in your now.json.
Alternatively, adding an appropriate Cache-Control header to a lambda's response also provides identical caching niceties and can be quite useful in getting content to your users swiftly.
The header enables use of Now's built-in edge caching. With this, our consumers are able to download our generated Open Graph images in a flash.


We enjoy improving developer experience and workflow automation. This is very much at the core of who we are at ZEIT. We hope you've enjoyed this brief window into how we improve our internal workflows and test our products by eating our own dogfood.
The source code for the project is fully public. We encourage forking the repository, creating your own, and deploying it with Now. As always, we are constantly open to feedback. Get in touch on Twitter and let us know your thoughts, feedback, questions, concerns, or praise.