Next.js Discord

Discord Forum

How do I add a dynamic favicon

Unanswered
Orinoco Crocodile posted this in #help-forum
Open in Discord
Orinoco CrocodileOP
As the title says how do i add a favicon that is different based on env var?

72 Replies

@Clown https://nextjs.org/docs/app/api-reference/file-conventions/metadata/app-icons#generate-icons-using-code-js-ts-tsx
Orinoco CrocodileOP
import Image from "next/image";
import { ImageResponse } from "next/server";

// Route segment config
export const runtime = "edge";

// Image metadata
export const size = {
  width: 32,
  height: 32,
};

export default function Icon() {
  return new ImageResponse(
    <Image src={"/images/icon.png"} alt="favicon" />,
    {
      ...size,
    }
  );
}


I tried but didn't seem to work
That's pointing to my public folder
Maybe its getting cached
Try using the force-dynamic
Orinoco CrocodileOP
What's that?
Check the bottom part of the docs. Although im not sure if thats really the problem because it mostly helps with fetch stuff
Make sure you check that the file is in correct place and also try using an incognito tab/another browser to test out if its getting cached
Orinoco CrocodileOP
I tried incognito and still didn't work
I'm using app router if it makes a difference
Is it in app folder and is it named icon.tsx?
Orinoco CrocodileOP
Yes and yes
Is it just not appearing ? Thats weird.
Orinoco CrocodileOP
give me a sec ill show logs
Orinoco CrocodileOP
Does it need to include base URL btw?
oh wait... now it works?
Orinoco CrocodileOP
never mind - still not working
getting a 404 not found for the icon for some reason
@Clown https://nextjs.org/docs/app/api-reference/file-conventions/metadata/app-icons#generate-icons-using-code-js-ts-tsx
Orinoco CrocodileOP
Am I reading this wrong or can it not be used for favicons
Its telling you to use icon or favicon.ico instead
So i would assume it still works
Btw remove the edge runtime config. Dont think you need that
Orinoco CrocodileOP
Right but I want it dynamic so how would that work?
Generating the "icon" with code should just work
As i said, did you look at the bottom of the docs on how to make it dynamic?
Orinoco CrocodileOP
With the icon.tsx file you make it dynamic
I'm wondering if it's because I'm building the site "static"
@Orinoco Crocodile I'm wondering if it's because I'm building the site "static"
Pretty sure by default its static unless you use something like dynamic routes inside or headers/cookies(not sure if you can use these but these would make it dynamic too)
Orinoco CrocodileOP
Then I don't understand why it's not working hrmm
It places the code in the head
But gives a 404 to loading it
Maybe next/image doesn't work for genning it?
Did you do
export const dynamic = 'force-dynamic'
@Orinoco Crocodile where you able to solve your issue?
Orinoco CrocodileOP
Haven't gotten round to checking sorry
Orinoco CrocodileOP
Still no luck
and you are on latest nextjs version?
Orinoco CrocodileOP
ye
Orinoco CrocodileOP
I have this in console when its builds sometimes
Orinoco CrocodileOP
Hey - still not working on latest version
Orinoco CrocodileOP
Anyone???
This works as expected for me:
import { ImageResponse } from "next/server";

// Route segment config
export const runtime = "edge";

// Image metadata
export const size = {
  width: 32,
  height: 32,
};
export const contentType = "image/png";

// Image generation
export default function Icon() {
  // Generate a random letter
  const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  const randomLetter = letters.charAt(
    Math.floor(Math.random() * letters.length)
  );

  return new ImageResponse(
    (
      // ImageResponse JSX element
      <div
        style={{
          fontSize: 24,
          background: "black",
          width: "100%",
          height: "100%",
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          color: "white",
        }}
      >
        {randomLetter}
      </div>
    ),
    // ImageResponse options
    {
      // For convenience, we can re-use the exported icons size metadata
      // config to also set the ImageResponse's width and height.
      ...size,
    }
  );
}
Orinoco CrocodileOP
so is the image not working then perhaps?
the fact im using an image and not text
Australian Freshwater Crocodile
Why you want expose the content inside env?
Orinoco CrocodileOP
There's two themes basically - easiest way to set it is through env vars which is changed on build
@Orinoco Crocodile so is the image not working then perhaps?
It looks like you can't use next/image because it's server code. You can link directly to images, though. It translates your HTML to an image if you want to create it within the component
Australian Freshwater Crocodile
let faviconPath;
  if (process.env.NEXT_PUBLIC_ENVIRONMENT === 'development') {
    faviconPath = '/favicon-dev.ico';
  } else if (process.env.NEXT_PUBLIC_ENVIRONMENT === 'production') {
    faviconPath = '/favicon-prod.ico';
  }
import { ImageResponse } from "next/server";

// Route segment config
export const runtime = "edge";

// Image metadata
export const size = {
  width: 32,
  height: 32,
};
export const contentType = "image/png";

// Image generation
export default function Icon() {
  // Generate a random letter
  const randomImage = Math.floor(Math.random() * 3) + 1;

  return new ImageResponse(
    (
      // ImageResponse JSX element
      <div
        style={{
          fontSize: 24,
          background: "black",
          width: "100%",
          height: "100%",
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          color: "white",
        }}
      >
        <img
          src={`http://localhost:3000/${randomImage}.png`}
          width={32}
          height={32}
        />
      </div>
    ),
    // ImageResponse options
    {
      // For convenience, we can re-use the exported icons size metadata
      // config to also set the ImageResponse's width and height.
      ...size,
    }
  );
}

This is working for me, but not ideal because of the absolute path
Orinoco CrocodileOP
so use a normal img tag?
@Orinoco Crocodile Where would you put that?
icon.js in your app dir
Orinoco CrocodileOP
no ricardos one
This is working for me, but not ideal because of the absolute path


Yeah absolute path is a pain
Is it just different for certain paths?
Orinoco CrocodileOP
nah its just dependant on the env var
you can place an icon.png anywhere
Orinoco CrocodileOP
different icons for different versions of the site
same code different colour scheme and favicon
(and logo)
hmm, seems like kind of a weird workaround to just changing the icon in the repo
Orinoco CrocodileOP
would need two repos then
or two branches
@Orinoco Crocodile Where would you put that?
Australian Freshwater Crocodile
Put in your component/ page
Orinoco CrocodileOP
and keep pushing to the other branch when it needs to be updated etc
Australian Freshwater Crocodile
<link rel="icon" href={faviconPath} />
Orinoco CrocodileOP
thats what I have now haha two branches with different code
and its pain to manage
@Orinoco Crocodile and its pain to manage
If you want to get really fancy and add more sites later, you could map them in a different file and just copy the image to the icon.png before/on build
Orinoco CrocodileOP
So when I build copy the file in? Not a bad idea