Adding Favicon to NextJs App router application
Asked Answered
F

15

31

I have an issue with the new Next.js App Router. They removed head.js files and now (as it is written in the doc) I have to use metadata in layout.ts. My favicon name is favicon.png.

How do i specify it here:

export const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
}
Flanagan answered 8/3, 2023 at 15:14 Comment(0)
S
33

You can do it as follow:

export const metadata = {
  icons: {
    icon: '/icon.png',
  },
};

The output will be

<link rel="icon" href="/icon.png" />

See all documentation regarding icons metadata:

https://beta.nextjs.org/docs/api-reference/metadata#icons

Subjunction answered 8/3, 2023 at 16:7 Comment(4)
You'll also need to add icon.jpg to /public.Cappadocia
I want sizes too..... something like this <link rel="icon" href="/favicon.svg" sizes="64x64"> how can i achieve this?Holden
@Holden check out my answer (https://mcmap.net/q/458628/-adding-favicon-to-nextjs-app-router-application) and see if it helpsHolofernes
important to note that the name of the favicon has to be "icon"Each
M
79

This is the simplest way to use Favicon in the Next.js 13.4 Stable version.

  1. You need to convert your jpg, png, or SVG to .ico. It takes only a few seconds.

  2. Rename your .ico file to icon.ico and paste it into the app folder and remove the favicon.ico from the app folder

Done

Mazman answered 6/6, 2023 at 7:37 Comment(5)
I really appreciate your solution - it's the only one that worked! Thank you so much!Viator
Thank you. Can't believe I have to come here to make that clear. Anyone else having troubles with Next 13 App Router docs?Wellappointed
My favicon.ico file was 16 KB and logo.svg was 5 KB. So, I put logo.svg in /app and renamed it to icon.svg. This means, you can add png, jpg images too. Just make sure the name starts with icon.Tycoon
In official doc: nextjs.org/docs/app/api-reference/file-conventions/metadata/… it says place favicon.ico in app folder, why does it not work and we have to use icon.ico instead?Retractor
It's puzzling. favicon.ico isn't work, icon.ico worked. But the official doc writes favicon.ico. Who knows what happend.Constriction
S
33

You can do it as follow:

export const metadata = {
  icons: {
    icon: '/icon.png',
  },
};

The output will be

<link rel="icon" href="/icon.png" />

See all documentation regarding icons metadata:

https://beta.nextjs.org/docs/api-reference/metadata#icons

Subjunction answered 8/3, 2023 at 16:7 Comment(4)
You'll also need to add icon.jpg to /public.Cappadocia
I want sizes too..... something like this <link rel="icon" href="/favicon.svg" sizes="64x64"> how can i achieve this?Holden
@Holden check out my answer (https://mcmap.net/q/458628/-adding-favicon-to-nextjs-app-router-application) and see if it helpsHolofernes
important to note that the name of the favicon has to be "icon"Each
H
12

To add multiple icons and add other attributes like type and sizes:

// layout.tsx
    
export const metadata: Metadata = {
  ...,
  icons: [
    {
      rel: 'icon',
      type: 'image/png',
      sizes: '32x32',
      url: '/favicon/favicon-32x32.png',
    },
    {
      rel: 'icon',
      type: 'image/png',
      sizes: '16x16',
      url: '/favicon/favicon-16x16.png',
    },
    {
      rel: 'apple-touch-icon',
      sizes: '180x180',
      url: '/favicon/apple-touch-icon.png',
    },
  ],
}
Holofernes answered 21/5, 2023 at 19:33 Comment(2)
thanks it does add sizes attribute but it sets all rel to icons like here is my code icons: [ {rel: "icon",type: "image/png",sizes: "32x32",url: "/favicon.png",}, {rel: "apple-touch-icon",type: "image/png",sizes: "180x180",url: "/favicon.png",}, {rel: "shortcut icon",type: "image/png",url: "/favicon.png",},], and here is what i got in chrome <link rel="icon" href="/favicon.png" type="image/png" sizes="32x32"><link rel="icon" href="/favicon.png" type="image/png" sizes="180x180"><link rel="icon" href="/favicon.png" type="image/png">Holden
how would you handle for toggling browser theme from light to dark?Saltworks
A
8
// app/layout.tsx

import { Metadata } from 'next';

export const metadata: Metadata = {
  icons: {
    icon: ['/favicon.ico?v=4'],
    apple: ['/apple-touch-icon.png?v=4'],
    shortcut: ['/apple-touch-icon.png'],
  },
  manifest: '/site.webmanifest',
};

// public/
//    |- ...
//    |- android-chrome-192x192.png
//    |- android-chrome-512x512.png
//    |- apple-touch-icon.png
//    |- favicon-16x16.png
//    |- favicon-32x32.png
//    |- favicon.ico
//    |- site.webmanifest
//    |- ...

Icon Convertor: https://favicon.io/favicon-converter/

Aube answered 29/6, 2023 at 13:55 Comment(1)
this what i want 👍Silverware
A
5

Based on docs here, adding link in RootLayout will also work

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <link rel="icon" href="/favicon.ico" sizes="any" />
        {children}
      </body>
    </html>
  );
}
Avelin answered 30/5, 2023 at 16:56 Comment(0)
D
4

acctually this will be correct,

    export const metadata = {
        icons: {
            icon:'/_next/static/media/metadata/favicon.png',
        },
    };    

and then put you favicon image in that URL (_next/static/media/metadata).

Derogate answered 22/3, 2023 at 20:56 Comment(0)
E
3

As others have explained, move the favicon.ico file from the public/ directory into the src/app/ directory. NextJS will then automatically generate the link tag in the page's head tag (see here for official docs).

There is no need to add it to the metadata object in src/app/layout.tsx unless you name it something other than favicon.ico.

Important!!!

Others have failed to mention this. Make sure you do not have a favicon.ico file in both public/ and src/app/ directory or else NextJS will not know which one to pick:

Error: A conflicting public file and page file was found for path /favicon.ico

This error message is only visible if you inspect the page and click the /favicon.ico link in the head tag.

Etamine answered 21/11, 2023 at 15:20 Comment(0)
F
2

In the latest versions (app directory), you can simply add your favicon file in the app/ directory, just make sure to name the icon using the expected Next standard according to your icon type, from the doc:

File convention Supported file types Valid locations
favicon .ico app/
icon .ico, .jpg, .jpeg, .png, .svg app/**/*
apple-icon .jpg, .jpeg, .png app/**/*

If your filve is an SVG icon, you can therefore simply put it in app/icon.svg. You don't need to edit the metadata, and you certainly don't need to convert your file to a .ico file.

The <link /> entry generated is something that looks like:

<link 
    rel="icon"
    href="/icon.svg?9905c4fc24cc0f60"
    type="image/svg+xml"
    sizes="any"
>

Per path icon

According to this documentation, if you are using an image icon, you can even have a different icon in subpaths. For example, if you have a dashboard subtree in your app:

enter image description here

You can have a diffrent favicon displayed for your users when they are in a dahboard page, you would simply need to have these files:

  • app/icon.svg the icon for all your pages unless its redefined in a subtree
  • app/dashboard/icon.svg the icon used in any page in the dashboard subtree (unless of course if its redefined in a sub-subtree)

Programmatically generate icons

You can even use a script to generate your icon, in that case the name conventions are:

File convention Supported file types Valid locations
icon .js, .ts, .tsx app/**/*
apple-icon .js, .ts, .tsx app/**/*

In that case, you can use the dynamic route parameters to customize even further and have an icon that is built for a given path slug. For example, you could add the following icon in app/dashboard/[slug]/icon.tsx to have a black circle with the first letter of your slug drawn:

enter image description here

import { ImageResponse } from "next/og";

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

export default function Icon({ params }: { params: { slug: string } }) {
    return new ImageResponse(
        (
            <div
                style={{
                    fontSize: 24,
                    background: "black",
                    width: "100%",
                    height: "100%",
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "center",
                    color: "white",
                    backgroundColor: "black",
                    borderRadius: "100%",
                    textTransform: "capitalize",
                }}
            >
                {params.slug[0]}
            </div>
        ),
        {
            ...size,
        },
    );
}

The <link /> entry generated is something that looks like:

<link
    rel="icon"
    href="/dashboard/cloud-computing/icon?f6e1d0bb0f362374"
    type="image/png"
    sizes="32x32"
>
Falcongentle answered 23/12, 2023 at 16:6 Comment(0)
L
1

in layout.tsx

export const metadata: Metadata = {
  icons: {
    icon: {
      url: "/favicon.png",
      type: "image/png",
    },
    shortcut: { url: "/favicon.png", type: "image/png" },
  },
};

and in public I have a image called favicon.png

Lysis answered 19/4, 2023 at 22:22 Comment(0)
E
1

Step One: Delete the favicon.ico from root(app) directory.

Step Two: Place your icon in the root(app) directory like (app/icon.svg) app/icon.png, app/icon.jpg.

Edentate answered 29/5, 2023 at 13:51 Comment(0)
W
1

You can also do icons: '<Path to icon>' (instead of passing an array) i.e:

In app/layout.tsx:

export const metadata: Metadata = {
  title: ...
  ...
  icons: 'favicon.ico',
}

Also, make sure that the file (like favicon.ico) is either in /app, or in /public but not in both.

Waterside answered 11/9, 2023 at 11:40 Comment(0)
M
1
  1. Delete favicon.ico from /app diractory
  2. Add your generated icons to /public/favicon
  3. Add icons to your manifest
  4. Now your manifest will work

Example


export const metadata: Metadata = {
  title: "Yout page title",
  description: "",

  icons: {
    icon: [
      {
        rel: "icon",
        type: "image/ico",
        url: "/favicon/favicon.ico",
      },
      {
        rel: "icon",
        type: "image/png",
        sizes: "16x16",
        url: "/favicon/favicon-16x16.png",
      },
      {
        rel: "icon",
        type: "image/png",
        sizes: "32x32",
        url: "/favicon/favicon-32x32.png",
      },
      {
        rel: "icon",
        type: "image/png",
        sizes: "192x192",
        url: "/favicon/android-chrome-192x192.png",
      },
      {
        rel: "icon",
        type: "image/png",
        sizes: "512x512",
        url: "/favicon/android-chrome-512x512.png",
      },
    ],
  },

  manifest: "/favicon/site.webmanifest",
};
Monson answered 16/5 at 11:36 Comment(0)
T
0

To me, the only method that worked is here.

This example is from the kapeesa gaming platform

Rename your icon file name to favicon.ico

e.g mine was kapeesa.png which I renamed to favicon.ico

Put your favicon.ico file in the src/app/ directory.

You usually have to replace the one you find in this path src/app/

That's it. It'll be used, fingerprinted, kabam.

Triphthong answered 28/5, 2023 at 9:53 Comment(1)
Does it take some time or did you have to do something like clearing cache? It's not working for meCacology
T
0

just put your favicon.ico in the root of src/app/ or app/ directory if still not working rename favicon to icon

Tarmac answered 4/7, 2023 at 8:33 Comment(0)
O
0

The cause of the problem is that the icon generated by create-next-project is cached in .next/cache directory. To solve the problem, delete .next directory in your project and then rename your icon file name to favicon.ico and move it to the app directory.

Oyster answered 26/6 at 1:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.