How to automate OG Images with Netlify Edge Functions
Automating the creation of custom open graph (OG) images opens up interesting business use cases from personalized conference tickets to shareable user profiles to easy blog post images. Fundamentally automated OG images unlock personalized information sharing at scale and make it easier to have great SEO. You can manually create 10 images, maybe a couple hundred images, but if you have thousands or millions of images then this is the way to go.
Probably one of the most well known examples of this is the generated OG images for GitHub repositories. GitHub generates an open graph social media image with some basic information about the repository: stars, contributors, forks, etc. The information is meaningful and helps users make a decision about whether they want to click on a link or not.
In this blog post I am going to show how to do this using Netlify edge functions but Vercel also has a great solution for generated OG images too.
- Use an existing project or initialize a fresh repository of whatever frontend framework you prefer (this demo uses Astro but it will work with NextJS, Remix, SvelteKit and others).
- Make sure you have a current version of the Netlify CLI by running
npm install netlify-cli -g.
- Create a blank edge function at
/netlify/edge-functions/og-image.tsfile. This will be where all of the magic happens!
- Create a
netlify.tomlfile in the root of your project with the following code. The path is where your edge function will be publicly available.
netlify devto start up your project using the Netlify development server which will let us test and preview the edge function. The first time you do this you should see some prompts about configuring your code editor for edge functions.
Making a basic image
Open up your
og-image.ts edge function and paste in the following code:
localhost:4321/api/og-image and check our the beautiful hello world! Nothing special happening here, yet.
The magic of automated open graph images is that they can be generated at run time based on whatever URL search parameters are provided. User name, blog post title, address, product rating, price, etc. You can get as creative as you want here because it happens at run time, not build time.
This information is passed to our image generation API using URL search params. A really simple example is something like this:
The important bits to notice are everything that comes after the
? mark where we pass the title as a search parameter to the edge function. Our edge function can then decode these search params and use them in our image as variables.
Here is an example building on what we had before to include a dynamic title in the image:
The HTML and CSS are rendered to an image using the Satori rendering engine. Satori gives you a limited subset of CSS and HTML to work with focusing on properties that affect visual appearance like color, borders, shadows, etc. The big win is that Satori lets you customize fonts, inserts SVGs, and even basic images.
The key here is that you need to work within the limitations of what is possible both with the rendering engine and also edge functions. At the time of writing CPU execution time is limited to 50ms for an edge function. Inlined SVGs give you a lot of creative freedom to keep the response times fast on the edge function while still adding visual pop.
Satori uses only flexbox for layout, meaning you can’t use CSS grid at this time for element position.
Let’s add a simple rocket ship SVG into our example:
Setting your open graph meta tags
Now that you have your open graph images automated you need to dynamically set your open graph meta tags. There are lots of ways you could accomplish this but probably the happiest path is using a layout component which accepts a prop for the image URL.
If you are using Astro you could do something like this:
Then inside of your layout component you use that prop to set all the appropriate meta tags inside the head.
This can get a bit more complicated as you have alt tags to think about for the image, fallback images if the prop isn’t present, and framework specific ways of managing SEO. If you feel like browsing through some raw code you can read through how I am doing this on my own site here: https://github.com/ehowey/erichoweydev.
Deploy, deploy, deploy
If you have been following along you should be able to deploy your project and view your new edge function via the raw URL which will be
https://www.mysite.com/api/og-image. Don’t forget to do some testing to make sure it is generating images and setting all the proper meta tags!
What you do next is up to you! Have fun and happy coding!