Dynamically Generated OG Images in NextJS
Open Graph (OG) images provide visual representations for content when it’s shared on social media platforms. It adds extra visual appeal to a posted link, helps with branding and can entice more clicks.
Today I’m going to show you how we can generate these dynamically in NextJS 13. This means that every time we post a blog for example, we don’t have to make the image ourselves, it can be done for us. It also allows us to easily change the style later if wanted.
Example
Section titled ExampleFor my site I have this setup. If I share a link to twitter for one of my posts, it looks like this.
Generating the Image
Section titled Generating the Image1. Create the API route
Section titled 1. Create the API routeThe first thing we need to do is create our API route. This will be called each time a platform request the OG image and will return it.
For the app router, create the following file /app/api/og/route.tsx
Within this file we are going to import the ImageResponse
which makes this all work.
We are also going to need to tell NextJS that this api route will use the “edge” runtime.
If you are using the pages router, you will need to install and import this from @vercel/og
.
2. Return an Image
Section titled 2. Return an ImageNow that we have our route, how do we make and return an image.
To do this we simply need to define an async function called GET, and return a simple image for now.
Now if you navigate to https://localhost:3000/api/og
you should see a simple image with the text hello in it.
3. Pull in dynamic data
Section titled 3. Pull in dynamic dataTo be able to use things such as the blog title, we will want to send some search params to the route to tell it what to render. So if I request the link /api/og?title="Hello"
, we can render the text Hello.
To do this, we will need to get the requested URL, and check if the searchParams has a title defined.
This example checks for the titles existence, if it isn’t provided use a default one, if it is ensure its not longer than 100 chars (you don’t need this bit if you don’t want it)
Now if we go to the url https://localhost:3000/api/og?title=Hello%20World
, we will see the words Hello World in our image. Now lets style this!
4. Styling
Section titled 4. StylingTo style this image, we can use inline styles as you would in react by adding the style prop, or we can use Tailwind.
In order to use tailwind, we don’t use className
as you may be used to. Instead you want to pass the prop tw
to your elements instead.
Now we have a nice OG image styled to suit our needs, but it doesn’t have a nice font, lets change that!
5. Custom fonts
Section titled 5. Custom fontsIn order to use a custom font, we are going to want to have the font we want to use saved as a file. For example, I have added the font Inter-bold.ttf
in the following folder /assets/fonts
To use this font, we need to do something that will look a little odd. We want to send a fetch request to this file, and then turn the response into an array buffer.
With the array buffer, we will want to add it to the ImageResponse configuration in a section called fonts, giving it a name and a style (normal or italic)
Now if you go to your route, you should see your custom font loaded into the image as well. Next we will look at some options you have for using emojis.
6. Using emojis
Section titled 6. Using emojisWhen you use an emoji, it will be rendered based on the device you are using. For example this 👋 will look different per device, depending on their emoji set.
When we make our image, we want to be able to tell the route what emoji set to use, as we wont know the device of the viewer.
To do this we can add a config option emoji
and set it to an emoji provider. The available providers are: twemoji, blobmoji, noto, openmoji, fluent and fluentFlat
7. Using local or external images
Section titled 7. Using local or external imagesSimilar to custom fonts, we have to load these by fetching and then getting an array buffer.
Then to use it, we can simply use a standard html image tag where we want it
Using the Image
Section titled Using the ImageTo use the image, you have 2 options. Static metadata, or dynamic metadata. You will most likely want dynamic as this is the main purpose of an OG route.
In the route that you want the OG image to be for, so for my example its the blog post page, located at /app/blog/[...slug]/page.tsx
In here, I have a function called generateMetadata
. You can view the documentation on this here.
What the above is doing is taking in the visited page param, in my case this is just the post slug. Fetching the post based on that slug, and then building the OG image url with the search parameters we can use.
Now whenever this page’s link is posted, it will fetch the image from that URL.