Next.js 14 の ImageResponse を使用して OGP 画像を動的生成する
Next.jsの標準機能であるImageResponseを使用して X や Facebook 等のポストで表示されるOGP画像を動的生成する方法を紹介します。
API の作成
./app/api/og/route.tsx を作成し中に OGP 画像を動的生成するコードを書きます。
import { ImageResponse } from "next/og";
import { NextRequest } from "next/server";
export async function GET(req: NextRequest) {
const { searchParams } = req.nextUrl;
const Title = searchParams.get("title");
return new ImageResponse(
(
<div
style={{
height: "100%",
width: "100%",
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
justifyContent: "center",
backgroundImage:
"url(https://raw.githubusercontent.com/hyt-fjwr/hytfjwr/master/public/og/og.png)",
}}
>
<h1
style={{
marginLeft: 205,
marginRight: 205,
display: "flex",
fontSize: 120,
letterSpacing: "-0.025em",
fontStyle: "normal",
fontWeight: "bold",
color: "white",
whiteSpace: "pre-wrap",
backgroundColor: "rgba(15, 15,19, .5)",
paddingLeft: "25px",
paddingRight: "25px",
borderRadius: "25px",
}}
>
{Title}
</h1>
<h2
style={{
marginLeft: 205,
marginRight: 205,
display: "flex",
fontSize: 50,
letterSpacing: "-0.025em",
fontStyle: "normal",
fontWeight: "bold",
color: "white",
whiteSpace: "pre-wrap",
backgroundColor: "rgba(15, 15,19, .5)",
paddingLeft: "25px",
paddingRight: "25px",
borderRadius: "25px",
}}
>
Hayato Fujiwara
</h2>
</div>
),
{
width: 1920,
height: 1080,
}
);
}
上記のように ImageResponse では div タグ内でスタイリングをします。
API の呼び出し
API が完成したので実際に各ページで呼び出してみましょう。 例として / ページの OGP を設定するために./app/layout.tsx 内に記述していきます。
//省略...//
export const metadata: Metadata = {
title: "Hayato Fujiwara",
description:
"My portfolio created with Nextjs, Radix Primitives, Framer Motion, Tailwind",
openGraph: {
title: "Hayato Fujiwara",
description:
"My portfolio created with Nextjs, Radix Primitives, Framer Motion, Tailwind",
type: "website",
url: "https://hytfjwr.com",
images: [
{
url: "https://hytfjwr.com/api/og?title=hytfjwr.com",
alt: "hytfjwr.com",
},
],
},
};
//以下省略...//
ページの title や description を設定する Metadata に openGraph という項目を追加し中身の images の中に作成した API の URL を記述します。
API では title というパラメータを追加していたの URL へのパラメータ追加も忘れずにしましょう。
完成画像

Discord での確認ですが上記のような画像が自動生成され、OGP 画像として設定されます。 これにより各ページ(pages.tsx)に Metadata を設定することで、ページ別で違った文字を挿入した画像が OPG 画像として設定できます。
全体的な流れとしては以上です。