frederikvonsperling
index / generating-open-graph-images-in-next-js-from-a-react-component

Generating Open Graph images in Next.js from a React Component

updated Frederik von Sperling#nextjs#seo

01What is a generated Open Graph image?#

As you would expect, generated Open Graph Images in Next.js is a feature that allows users to generate a social image from a React component. This feature is really useful when doing a blog like this, as bad screenshots for the posts would just have been a waste of bytes and using AI generated images isn’t the way I wanted to go.

Generated Open Graph image containing the title "Generating Open Graph images in Next.js from a React Component"
A generated Open Graph image

02How to generate Open Graph images in Next.js?#

Using Next.js ImageResponse Constructor in a special file used for file-based metadata you can generate an Open Graph image.

To make a generated Open Graph image, create a opengraph-image.tsx file and make the default export a function returning a new instance of the ImageResponse constructor.

opengraph-image.tsxtsx
import { ImageResponse } from "next/og";

export default function OpenGraphImage() {
return new ImageResponse(<p>I am a Opengraph Image</p>);
}

03Dynamic content for the Open Graph Image#

In my case I needed custom Open Graph images for each posts, so I needed to fetch the meta data for each post. As with dynamic route segments in Next.js the current path or slug can be retrieved using by awaiting the params.

opengraph-image.tsxtsx
import { ImageResponse } from "next/og";

import { OgCard, ogFonts, ogSize } from "@/lib/og-image";

export default async function Image({ params }: PageProps<"/posts/[slug]">) {
const { slug } = await params;

const [post, settings] = await Promise.all([
client.fetch(POST_SEO_QUERY, { slug }),
client.fetch(SETTINGS_QUERY),
]);

if (!post || !settings) {
return new Response("Not found", { status: 404 });
}

const publishedAt = post.publishedAt ? isoDate(post.publishedAt) : null;
const tags = post.tags?.flatMap((tag) => (tag ? [`#${tag}`] : [])) ?? [];
const meta = [publishedAt, ...tags].filter(Boolean).join(" · ");

return new ImageResponse(
<OgCard
wordmark={settings.wordmark}
title={post.title}
meta={meta || undefined}
/>,
{ ...ogSize, fonts: ogFonts }
);
}

04Putting it all together#

When styling the Open Graph image(s), the styles need to be inline and the fonts loaded. This is done within my OgCard components. Let us take a look at how do that in Next.js.

og-image.tsxtsx
import { readFile } from "node:fs/promises";
import path from "node:path";

const BG = "#0e1014";

export const ogSize = { height: 630, width: 1200 };
export const ogContentType = "image/png";

const [newsreaderMedium, jetbrainsMonoRegular] = await Promise.all([
readFile(path.join(process.cwd(), "assets/fonts/Newsreader-Medium.ttf")),
readFile(path.join(process.cwd(), "assets/fonts/JetBrainsMono-Regular.ttf")),
]);

export const ogFonts = [
{
data: newsreaderMedium,
name: "Newsreader",
style: "normal" as const,
weight: 500 as const,
},
{
data: jetbrainsMonoRegular,
name: "JetBrains Mono",
style: "normal" as const,
weight: 400 as const,
},
];

interface OgCardProps {
wordmark: string;
title: string;
meta?: string;
}

export function OgCard({ wordmark, title, meta }: OgCardProps) {
return (
<div
style={{
background: BG,
display: "flex",
flexDirection: "column",
fontFamily: "Newsreader",
height: "100%",
justifyContent: "space-between",
padding: "64px 72px",
width: "100%",
}}
>
...
</div>
);
}

Next.js is using satori for generating the Open Graph images, so please refer to the documentation for more information.

QUESTIONS & ANSWERS

How to validate that a Open Graph image is rendered?

Either follow the path set on content on the og:image attribute in the dom or use an external tool. Search on Google for 'Open Graph Validator' or similar

What is Next.js using to render Open Graph images?

Next.js is using Satori to render the image used for Open Graph image

Why render an Open Graph image from a React component?

If you aren't able to produce an image for a list of articles, blogposts or similar and using AI is either not an option or wanted, producing an Open Graph image dynamically might be the solution

SUBSCRIBE

Get an email when a new post is published. Nothing more.