Tips for Dynamically Outputting OGP Images with Static Export in Next.js Since App Router
This is for achieving output like this on social media.

If you search the internet, you can find various ways to dynamically output OGP images with Next.js. In practice, though, many are not written for App Router and later, or are not written with Static Export in mind, so you can end up struggling quite a bit.
So this time, I will write down some tips as a memo.
Import ImageResponse from next/og
Since Next.js 14, ImageResponse is imported from next/og.
import { ImageResponse } from "next/og";
The official documentation also includes this in its examples.
When Using Images
Images seem to have various constraints when using Static Export. Simply importing them or fetching binary data both produced errors that I could not resolve, so for now I am embedding them as base64.
const OgpBackground = () => {
return (
<img
alt=""
style={{ display: "flex", position: "absolute", top: "0", left: "0" }}
src={
"data:image/png;base64,iVBORw...CYII="
}
/>
);
};
export default OgpBackground;
I will continue looking for the best approach, but for now I am using this method.
Using Google Fonts
For Google Fonts, as the official documentation says, Use fs (Node.js only) or fetch to read the font as Buffer/ArrayBuffer and provide data here. In other words, you need to fetch an ArrayBuffer from the Google Fonts API and pass it in. The blog post below was helpful. Thank you.
- vercel/satori: Enlightened library to convert HTML and CSS to SVG
- Using Google Fonts with Satori - Tsumami Log
Layout Takes Effort
It seems the style for a div must be either display: flex or display: none. Otherwise, you get the following error.
Error: Expected <div> to have explicit "display: flex" or "display: none" if it has more than one child node.
I created the design itself in Figma and used it as a template.

You need to build the layout in a somewhat tedious way that differs from normal HTML, but after some trial and error I was able to shape it.
One particular point to watch out for is that you may encounter the error above when you want to display Markdown.