105

I'm trying to add a favicon to a Next.js static site without much luck.

I've tried customising the document with components from 'next/document' https://nextjs.org/docs/#custom-document

A straight link to the favicon.ico file doesn't work because the file isn't included in the build and the href doesn't update to /_next/static/...

Importing the image and adding to the link's href doesn't work either (see commented out lines).

import React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';

// import favicon from '../data/imageExports';

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps };
  }

  render() {
    return (
      <Html>
        <Head>
          {/* <link rel="shortcut icon" href={favicon} /> */}
          <link rel="shortcut icon" href="../images/icons/favicon.ico" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

The favicon links get added however it doesn't display. I'd expect it to work when I import the file, but it just adds a <link rel="shortcut icon" href="[object Object]"> link.

Has anyone done this yet?

Advait Junnarkar
  • 3,283
  • 4
  • 13
  • 25

16 Answers16

172
  1. Create a /static folder in project root. This will be added to the static export folder.
  2. Add favicon file in /static folder.
  3. Add _document.js to /pages/ folder according to documentation (nextjs.org) or documentation (github.com).
  4. Add <link rel="shortcut icon" href="/static/favicon.ico" /> to head.
  5. npm run build && npm run export

P.S. Thanks to the previous answer that was deleted. It works!


Edit: Another way is to do this is to import Head into your root layout and add the link there. Anything added to Head gets inserted into the document head tag.

import Head from 'next/head';

const Page = (props) => (
  <div>
    <Head>
      <link rel="shortcut icon" href="/static/favicon.ico" />
    </Head>
    // Other layout/components
  </div>
);

export default Page;

Update :

The static directory has been deprecated in favor of the public directory. Doc

So, the code would now look like

import Head from 'next/head';

const Page = (props) => (
  <div>
    <Head>
      <link rel="shortcut icon" href="/favicon.ico" />
    </Head>
    // Other layout/components
  </div>
);
S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Advait Junnarkar
  • 3,283
  • 4
  • 13
  • 25
  • 3
    Documentation link now here: https://nextjs.org/docs/advanced-features/custom-document or https://github.com/zeit/next.js/#custom-document – Denis Dec 29 '19 at 20:39
  • 10
    although this works, now next.js favours `/public` folder rather than `/static` https://github.com/zeit/next.js/blob/master/errors/static-dir-deprecated.md – Gonzalo.- Jan 13 '20 at 21:24
  • Why'd you reject their edit just to reapply the changes? Also, I can confirm the answer was deleted; I added a [screenshot](https://i.stack.imgur.com/oEKzt.png) for future reference. – S.S. Anne Feb 13 '20 at 22:23
  • 2
    @S.S.Anne That was a misclick for Tesseracter's edit, the edit was good - my apologies for that, so I rolled it back. Regarding the deleted answer, I don't know why that person deleted it, that solution worked then. – Advait Junnarkar Feb 13 '20 at 22:28
  • 1
    It doesn't work for me, it displayed React Favicon Logo and kept loading. All I've done is adding `..`, so it would be: ``. P.S: I am using a version prior to `9.0.6` that's why I still use `static` public directory. Thanks @AdvaitJunnarkar! – Elharony Mar 29 '20 at 18:35
  • when i move faricon or static file into public file, it didnt work anymore – Sallwa Apr 02 '20 at 06:52
  • the documentation did it for me –  Aug 04 '21 at 17:08
  • 1
    When using a basePath, is it supposed to work with the public folder ? I have a basePath, my `favicon.ico` is in the public folder and I defined it like that `` but the link stay without my basePath like that in my browser : `` – R. Boutte May 05 '22 at 15:26
  • how do we do that if we're using app router instead of pages? – akzarma May 17 '23 at 06:53
  • As of 2023, Next13, simply adding the favicon to the public/ folder worked – Bosco Domingo Jul 18 '23 at 10:36
67

Simply add your favicon.ico in public folder, Next js will automatically take that favicon for all pages.

No need to add any favicon link to any pages or in tag no need to add link for favicon.

https://github.com/zeit/next.js/blob/master/errors/static-dir-deprecated.md

  • 2
    Thank you! All I need is only replace the current favicon.ico on public folder. Using next v10.0.2 – Hanif Jan 29 '21 at 10:11
  • 2
    the best answer! – Hanane Feb 16 '21 at 08:56
  • 1
    This problem with this though is the formats are wrong since there needs to be atleast 24 favicon assets? – Oliver Dixon Apr 15 '21 at 10:27
  • This worked perfectly for me, simply added ico file to /public and boom! – Michiel J Otto Jul 06 '21 at 11:08
  • 1
    Assets in public folder can be accessed by browsers. Tour browser will look for the favicon.ico file, not Next. However, if you don't a link there are issues with mobile and tablet. Especially when someone tries to save a link to their app launcher, the icon won't use the favicon. – Advait Junnarkar Jan 13 '22 at 00:41
  • Need to be inside "public/images" folder with Next.js 18. – Emre Oct 07 '22 at 15:21
45

The accepted answer is nice, but might be worth pointing out that you don't have to modify _document.js for adding a favicon (nor for adding any tags to head).

I found out for myself that placing favicon in _app.js makes more sense. This file is most likely to exist already for setting up a layout for the pages or something like this. And you can add Head tag literally anywhere (see the docs)

So I ended up with _app.js

class MyApp extends App {
  render() {
    const { Component, pageProps } = this.props;

    return (
      <Layout>
        <Head>
          <link rel="shortcut icon" href="/favicon.ico" />
        </Head>
        <Component {...pageProps} />
      </Layout>
    );
  }
}
Ryan Walker
  • 715
  • 2
  • 10
  • 23
user3272018
  • 2,309
  • 5
  • 26
  • 48
  • it is not working for me, the only way which works is that i put faricon into static folder – Sallwa Apr 02 '20 at 06:58
  • 1
    You can store your favicon in wherever you want, this question is about how to add it to a website, not where to locate the file. So probably you just specified wrong path to your favicon. – user3272018 Apr 02 '20 at 18:05
23

As of June 2020, you don't have to add/edit the document.js or _head.js files. All you need do to is place the favicon.ico file inside the public directory and that's it.

Pedram
  • 15,766
  • 10
  • 44
  • 73
Andres Zapata
  • 1,710
  • 1
  • 16
  • 32
  • I've added "favicon.ico" into folder public but when I run build I don't see the favicon be compiled inside folder .next. Do you have an example? Thanks you. – nart Jun 07 '20 at 09:37
  • It doesn't get put into any other folder, you just leave it in the public folder. If it's there, nextjs picks it up and uses it. I'm using next@9.4.4. – Andres Zapata Jun 07 '20 at 19:27
  • I'm using next@9.4.4 either. but still got the same problem :( – nart Jun 10 '20 at 03:46
  • I'm using Next 9.5.0, I placed the favicon.ico file inside public directory and voila it worked!! thanks @AndresZapata – Sumit Aug 05 '20 at 10:00
19

Only adding .ico file is not enough.

Add link tags to <Head> section in _document.jsx or _document.tsx The question is only about .ico file, but I would recommend to add different dimensions and formats for better support.

import React from 'react';
import Document, { Html, Head, Main, NextScript, DocumentContext, DocumentInitialProps } from 'next/document';

class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps };
  }

  render(): React.ReactElement {
    return (
      <Html>
        <Head>
          <link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png" />
          <link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png" />
          <link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png" />
          <link rel="manifest" href="/favicons/site.webmanifest" />
          <link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#5bbad5" />
          <meta name="msapplication-TileColor" content="#ffc40d" />
          <meta name="theme-color" content="#ffffff" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

You can generate different icons using RealFaviconGenerator and upload results to /public/favicons/ folder. This folder can be referenced by /favicons/ due to nature of public directory.

Black
  • 9,541
  • 3
  • 54
  • 54
  • 2
    Thx a lot. It's to much code for one favicon, I think, but your solution helped – Gorr1995 Jun 07 '20 at 13:43
  • 3
    The only right answer; since you need 24 favicons at least to be complient across devices. – Oliver Dixon Apr 15 '21 at 10:27
  • This wont' work in next 12, they got rid of PNG and SVG loaders – serraosays Jun 14 '22 at 01:01
  • @serraosays Could you please share the link to doc mentioning that? I am running Next 12.1 and don't have any issues with this configuration. – Black Jun 15 '22 at 03:43
  • @Black - docs on new Next compiler: https://nextjs.org/docs/advanced-features/compiler. They're kind of forcing you to use next/image now. I haven't found a way to load jpg, png, etc without custom webpack 5 loaders (which implies they dropped those loaders from the default). Would love to be wrong about this, it's a pain right now. – serraosays Jun 15 '22 at 17:34
  • Also worth reviewing - https://github.com/vercel/next.js/discussions/26167 – serraosays Jun 15 '22 at 17:38
6

I had to do favicon.src to make it work

Doesn't work:

import favicon from '...'
...

<link rel="shortcut icon" href={favicon} />

Works:

import favicon from '...'
...

<link rel="shortcut icon" href={favicon.src} />

To figure this out, I ran console.log(favicon) and it turns out that it was an object that looks something like this:

{
  height: 16,
  src: "path/to/favicon.603d046c.ico"
  width: 16,
}
Sammy Sam
  • 61
  • 1
  • 2
5

In my case it DID NOT WORK WITH OUT THE IMPORT:

file: _app.tsx


    import { AppContext, AppProps } from "next/app";
    import "../styles/common.scss";
    import Head from 'next/head';
    //For me it didn't work without the following import...
    import favico from "../static/favicon.ico";
    
    
    function MyApp({ Component, pageProps }: AppProps) {
      const csrfToken = pageProps["anti-csrftoken-a2z"];
      return (
        <div>
          <Head>
            <link rel="shortcut icon" href={favico} type="image/x-icon" />
          </Head>
          <Component {...pageProps} />
        </div>
      );
    }
    
    MyApp.getInitialProps = async ({ Component, ctx }: AppContext) => {
      let pageProps = {};
      if (Component.getInitialProps) {
        pageProps = await Component.getInitialProps(ctx);
      }
      return { pageProps };
    };
    
    export default MyApp;

3

Next.js can serve static files, like images, under a folder called public in the root directory. Files inside public can then be referenced by your code starting from the base URL (/).

For example, if you add an image to public/me.png, the following code will access the image:

import Image from 'next/image'

function Avatar() {   
    return <Image src="/me.png" alt="me" width="64" height="64" />
}

export default Avatar 

Note: next/image requires Next.js 10 or later.

This folder is also useful for robots.txt, favicon.ico, Google Site Verification, and any other static files (including .html)!

For your case, if you just replace the favicon.ico it will update accordingly.

For more details visit the official documentation.

juliomalves
  • 42,130
  • 20
  • 150
  • 146
Humayun Kabir
  • 518
  • 4
  • 15
2

I think it would be useful for someone

<Head>
    <link rel="apple-touch-icon" sizes="57x57" href="/favicons/apple-touch-icon-57x57.png" />
    <link rel="apple-touch-icon" sizes="60x60" href="/favicons/apple-touch-icon-60x60.png" />
    <link rel="apple-touch-icon" sizes="72x72" href="/favicons/apple-touch-icon-72x72.png" />
    <link rel="apple-touch-icon" sizes="76x76" href="/favicons/apple-touch-icon-76x76.png" />

    <link rel="apple-touch-icon" sizes="114x114" href="/favicons/apple-touch-icon-114x114.png" />
    <link rel="apple-touch-icon" sizes="120x120" href="/favicons/apple-touch-icon-120x120.png" />
    <link rel="apple-touch-icon" sizes="144x144" href="/favicons/apple-touch-icon-144x144.png" />
    <link rel="apple-touch-icon" sizes="152x152" href="/favicons/apple-touch-icon-152x152.png" />
    <link rel="apple-touch-icon" sizes="167x167" href="/favicons/apple-touch-icon-167x167.png" />
    <link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon-180x180.png" />

    <link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png" />
    <link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png" />
    <link rel="icon" type="image/png" sizes="96x96" href="/favicons/favicon-96x96.png" />
    <link rel="icon" type="image/png" sizes="128x128" href="/favicons/favicon-128x128.png" />
    <link rel="icon" type="image/png" sizes="196x196" href="/favicons/favicon-196x196.png" />
    <link rel="icon" type="image/png" sizes="192x192" href="/favicons/android-chrome-192x192.png" />
    <link rel="icon" type="image/png" sizes="512x512" href="/favicons/android-chrome-512x512.png" />

    <link rel="shortcut icon" href="/favicons/favicon.ico" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="mobile-web-app-capable" content="yes" />

    <meta name="msapplication-TileImage" content="/favicons/mstile-144x144.png"/>
    <meta name="msapplication-square70x70logo" content="/favicons/mstile-70x70.png"/>
    <meta name="msapplication-square150x150logo" content="/favicons/mstile-150x150.png"/>
    <meta name="msapplication-square144x144logo" content="/favicons/mstile-144x144.png"/>
    <meta name="msapplication-square310x310logo" content="/favicons/mstile-310x310.png"/>
</Head>
Travnikov.dev
  • 464
  • 6
  • 14
2

I had to put mine under public/images directory with Next.js v18. Putting under public did not work.

Emre
  • 831
  • 11
  • 13
1

May 2023/NextJS 13 Update:

Add a favicon.ico to your /app folder. NextJS will automatically generate the appropriate code in the <head> for it.

You can also add icon.(ico|jpg|jpeg|png|svg), or apple-icon.(jpg|jpeg|png|svg) file to the root segment.

https://nextjs.org/docs/app/api-reference/file-conventions/metadata/app-icons

mike
  • 164
  • 3
  • 10
1

This confused me too, but it's actually really simple.

You just need to —

  1. add your favicon.ico file to /public/assets/favicon.ico.
  2. somewhere in your code, you need to add the favicon into your page <head> like —
import Head from 'next/head'

<Head>
    ... the rest of your HTML head ...
    <link rel="icon" href="/favicon.ico" /> // <- HERE
</Head>

I wrote more about this here — Favicons in NextJS | MONN blog — if you're after something a bit more in-depth. I also go over my usual go-to method of creating a <HeadMetaTags /> to encapsulate all this.

0

For me it was missing in production site but working fine in local because I didn't add the public folder in the artifacts of the production site. I assumed that next.js would put all it needs in .next folder but it's not the case.

cp -R ./.next/ artifacts/
cp -R ./node_modules/ artifacts
cp -R ./public/ artifacts  #missing line in my github action code
cp package.json ./artifacts/package.json
wings
  • 338
  • 4
  • 15
0

The issue might come from the ico format. For some reason it needs to be inside an images folder within the public directory for the favicon to work with this format. Whereas when I tried using an svg and a png it worked even if the files are located at the root of the public directory (not within any images folder).

In both cases though, as it was indicated above, it seems that you will need to specify the new favicon path in the _document.tsx file inside the <Head /> component from next/document.

Either of the following worked for me:

<Head>
  <link rel="shortcut icon" href="images/favicon.ico" />
</Head>

Or

<Head>
  <link rel="shortcut icon" href="favicon.svg" />
</Head>

The svg and png formats are more reliable though. The ico is still not working in 100% of the cases for me even when put inside the public/images folder (I tested using Next.js v13.3.1).

baloo
  • 1
  • 2
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 28 '23 at 13:56
0

(Updated answer for Next.js 13 as of June 2023)

  1. Add to /pages/_document.js (or use the new /app router structure if you have migrated to that from /pages)

https://nextjs.org/docs/app/api-reference/file-conventions/metadata/app-icons#image-files-ico-jpg-png

Docs say to add to _app.js but _document.js works as well.

This is my /pages_document.js file for a working example:

import { Html, Head, Main, NextScript } from "next/document"

export default function Document() {
  return (
    <Html lang="en">
      <Head>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
        
        // Here is where you add the link to the favicon
        <link rel="icon" href="/favicon/favicon.ico" sizes="any" />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}
  1. Place your favicon files in /public

I made a folder inside of /public called "favicon" so the path to the file you will link to in the above code example is /public/favicon/favicon.io.

If you drop your favicon.io files in /public without creating a subfolder just update the link in the example to /public/favicon.io instead.

Hope this helps!

0

if you are using next.js 13 you'll have to add icons field to metadata object in app/layout.tsx

Ref: https://nextjs.org/docs/app/api-reference/functions/generate-metadata#icons

Rohit Dhas
  • 207
  • 1
  • 3
  • 9