Next.js Discord

Discord Forum

Can't resolve '../../../assets/metropolis.ttf' when generating dynamic OG images in API route

Unanswered
Sweat bee posted this in #help-forum
Open in Discord
Sweat beeOP
I'm trying to generate OG images based on blog's title. I have 2 local fonts in my assets directory, which i'm using it in my API routes. as follows.

// app/api/og/route.tsx
import { ImageResponse } from "next/og";

export const runtime = "edge";

export async function GET(request: Request) {
  try {
    const montserrat = await fetch(
      new URL("../../../assets/montserrat.ttf", import.meta.url)
    ).then((res) => res.arrayBuffer());

    const metropolis = await fetch(
      new URL("../../../assets/metropolis.ttf", import.meta.url)
    ).then((res) => res.arrayBuffer());

    return new ImageResponse(
      (
        <div>
          ...rest
        </div>
      ),
      {
        fonts: [
          {
            name: "montserrat",
            data: montserrat,
            style: "normal",
          },
          {
            name: "metropolis",
            data: metropolis,
            style: "normal",
          },
        ],
      }
    );
  } catch (err) {
    return new Response("Failed to generate OG image", { status: 500 });
  }
}


The fonts are working as expected on local, but throws the error Module not found (attached in screenshot).

I would appreciate a possible fix for this.

16 Replies

Sweat beeOP
Also, i'm following this guide: https://vercel.com/guides/using-custom-font
is assets in the folder from the project root?
the example has a couple extra dots
new URL('../../../../assets/typewr__.ttf', import.meta.url),

yours
new URL("../../../assets/montserrat.ttf",
Sweat beeOP
The path is correct
adding a pair of dot gives this error
did you try put the fonts on public and use absolute path?
Sweat beeOP
checking it rn
Sweat beeOP
  const getMontserrat = async () => {
    const response = await fetch(new URL("./fonts/montserrate.ttf", import.meta.url));
    const montserrat = await response.arrayBuffer();

    return montserrat;
  };
is this correct? my fonts are inside public/fonts/*
Sweat beeOP
it worked after some tweaks
thank you
can you mark it as solved and show how you solved it, maybe it helps someone in the future
Sweat beeOP
sure thing
i’ll do it in a bit
Sweat beeOP
I was able to fetch the font using a fetch function

  const getMontserrat = async () => {
    const response = await fetch(
      new URL("../../../public/fonts/montserrat.ttf", import.meta.url)
    );
    const montserrat = await response.arrayBuffer();

    return montserrat;
  };



and utilize the font as follows:

  return new ImageResponse(
    (...rest),
    {
      debug: true,
      fonts: [
        {
          name: "montserrat",
          data: await getMontserrat(),
          style: "normal",
        },
      ],
    }
  );