Takumi

Next.js

Generate Open Graph images from React components in Next.js App Router route handlers.

Return an Open Graph image from a Next.js App Router route. ImageResponse from takumi-js/response renders a React component and answers with the image.

Install Takumi

npm i takumi-js

Keep the native binding out of the bundle

Add @takumi-rs/core to serverExternalPackages. It holds a native .node addon, which Next.js cannot bundle.

next.config.ts
import type { NextConfig } from "next";

const config: NextConfig = {
  serverExternalPackages: ["@takumi-rs/core"], 
};

export default config;

Create an image component

app/og/OgImage.tsx
type OgImageProps = {
  title: string;
  description: string;
};

export default function OgImage({ title, description }: OgImageProps) {
  return (
    <div
      style={{
        width: "100%",
        height: "100%",
        display: "flex",
        flexDirection: "column",
        justifyContent: "center",
        padding: "64px",
        backgroundImage: "linear-gradient(to bottom right, #fff7ed, #fecaca)",
      }}
    >
      <p style={{ fontSize: 72, fontWeight: 700, color: "#111827" }}>{title}</p>
      <p style={{ fontSize: 42, fontWeight: 500, color: "#4b5563" }}>{description}</p>
    </div>
  );
}

Return the image from a route handler

app/og/route.tsx
import { ImageResponse } from "takumi-js/response";
import OgImage from "./OgImage";

export function GET(request: Request) {
  const url = new URL(request.url);
  const title = url.searchParams.get("title") ?? "Takumi + Next.js";
  const description = url.searchParams.get("description") ?? "Render OG images with React.";

  return new ImageResponse(<OgImage title={title} description={description} />, {
    width: 1200,
    height: 630,
  });
}

Visit /og?title=Hello to see the image.

Use the opengraph-image file convention

Next.js also reads an opengraph-image.tsx file next to a page and adds the meta tags for you. Return an ImageResponse from its default export:

app/opengraph-image.tsx
import { ImageResponse } from "takumi-js/response";
import OgImage from "./og/OgImage";

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

export default function Image() {
  return new ImageResponse(
    <OgImage title="Takumi + Next.js" description="Render OG images with React." />,
    size,
  );
}

If the build fails, see Troubleshooting.

Last updated on