For clear an better UI you can read this blog post on my personal blog: Creating Auto Dynamic OG Images for Your Next.js Application with Serverless Functions
If you have a blog or website, you may want to create open graph (OG) images to use when sharing your content on social media platforms. OG images are displayed when someone shares your content on social media, and they help to give context to the shared content and make it more visually appealing.
In this tutorial, we'll look at how to create dynamic OG images in a Next.js application using a serverless
function. We'll use the @vercel/og
package to create the OG image within the serverless
function.
Before we get started, you'll need to have a Next.js application set up. If you don't already have one, you can create a new Next.js project by running the following command:
npx create-next-app
Install the @vercel/og
package:
npm install @vercel/og
Now that we have the necessary packages installed, we can create the serverless
function that will generate the OG image. To do this, create a og.js
in the api folder of your Next.js project and import ImageResponse
class at the top of the file:
import { ImageResponse } from '@vercel/og';
Next, we'll set the runtime for the serverless function to "edge" in the config object:
export const config = {
runtime: 'edge',
};
This will ensure that the function is executed on the edge network, which is required for creating OG
images.
Now, let's define the main handler function for the serverless
function:
export default function handler(req) {
try {
const { searchParams } = new URL(req.url);
// code for generating the OG image goes here
} catch (e) {
return new Response(`Failed to generate the image`, {
status: 500,
});
}
}
This function takes a request object as an argument and returns an OG image response. If an error occurs while generating the image, it returns a response with a status of 500 and an error message.
Now let's start adding the code for generating the OG image. First, we'll parse the search parameters from the request URL:
const { searchParams } = new URL(req.url);
Then, we'll check if the title search parameter is present in the query string:
const hasTitle = searchParams.has('title');
If the title
parameter is present, we slice it to a maximum of 100 characters and assign it to the title variable, If the title
parameter is not present, we set the title variable to the default value of "DevToMars":
const title = hasTitle
? searchParams.get('title')?.slice(0, 100)
: 'DevToMars';
Next, we retrieve the mainTopics
search parameter from the query string and split it into an array using the split method:
const mainTopics = searchParams.get('mainTopics').split(",")
This allows us to pass multiple main topics as a comma-separated list in the query string.
Now that we have the title and mainTopics
variables, we can use them to render the OG image. To do this, we use the ImageResponse
class from the @vercel/og
package, which allows us to create an OG image from a React component.
We pass a simple div element with some inline styles applied to it to the ImageResponse
class as the React component . The styles specify the layout and appearance of the OG image:
return new ImageResponse(
(
<div
style={{
backgroundColor: 'black',
backgroundSize: '150px 150px',
height: '100%',
width: '100%',
display: 'flex',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'column',
flexWrap: 'nowrap',
padding: "65px",
}}
>
{/* The Body of the Image */}
</div>
As you can see, we are displaying the div as a flex because Next.js requires this for every element with more than one child. You can use Tailwindcss
for styling, but I don't recommend it because it is not stable and it is not fully supported for generating images with Next.js.
Our image will contain a title
that fills up 75%
of the image width with some padding and a margin-top
of 30px
, a logo with a brand name, and a list of main topic tags. :
...
<div style={{
fontSize: 60,
fontStyle: 'normal',
letterSpacing: '-0.025em',
color: 'white',
marginTop: 30,
padding: '0 100px',
lineHeight: 1.4,
whiteSpace: 'pre-wrap',
height: "75%",
fontWeight: 700,
textTransform: "capitalize"
}} className="w-10 capitalize">
{title}
</div>
<div style={{ display: "flex", flexDirection: "row", gap: "10px", alignItems: "center" }} >
<div style={{ width: "70px", height: "70px", display: "flex" }}>
<img
src="https://media.graphassets.com/gncWvSEqRFaBSUPZGoTP"
width={70}
height={70}
alt="devtomars blog"
/>
</div>
<div style={{
backgroundClip: "text",
color: "transparent",
backgroundImage: "linear-gradient(to right, #ec4899, #8b5cf6)",
fontWeight: 700,
fontSize: 30
}} >DevToMars</div>
<div style={{ display: "flex", flexDirection: "row", justifyContent: "flex-end", justifyItems: "center",width: "75%" }}>
{
mainTopics.map((topic, i) => (
<div key={i} style={{ color: "black", fontSize: 20, padding: "5px", margin: "3px", backgroundColor: "white", borderRadius: "8px" }}>{topic}</div>
))
}
</div>
</div>
...
Finally, we pass an option object to create an OG image with a width of 1200 pixels and a height of 630 pixels:
return new ImageResponse(
// JSX element here
{
width: 1200,
height: 630,
},
);
And that's it! You now have a serverless
function that can generate dynamic OG images for your Next.js application. To use the function, simply make a request to the function's URL with the desired title and mainTopics
query parameters. For example:
https://your-next-app.vercel.app/api/og?title=My Blog Post&mainTopics=nodejs,javascript,react
This will generate an OG image with the title "My Blog Post" and the main topics "nodejs", "javascript", and "react".
You can then use the generated OG image in your social media sharing tags, like so:
<meta property="og:image" content="https://your-next-app.vercel.app/api/og?title=My Blog Post&mainTopics=nodejs,javascript,react" />
That's it! You now know how to create dynamic OG images for your Next.js application using a serverless function. I hope this tutorial was helpful!
Top comments (0)