How to add a favicon to a Next.js static site?
Asked Answered
A

18

113

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?

Attaway answered 20/5, 2019 at 0:15 Comment(0)
A
181
  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>
);
Attaway answered 23/5, 2019 at 3:47 Comment(10)
Documentation link now here: nextjs.org/docs/advanced-features/custom-document or github.com/zeit/next.js/#custom-documentDunker
although this works, now next.js favours /public folder rather than /static github.com/zeit/next.js/blob/master/errors/…Whippletree
Why'd you reject their edit just to reapply the changes? Also, I can confirm the answer was deleted; I added a screenshot for future reference.Aeniah
@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.Attaway
It doesn't work for me, it displayed React Favicon Logo and kept loading. All I've done is adding .., so it would be: <link rel="shortcut icon" href="../static/favicon.ico" />. P.S: I am using a version prior to 9.0.6 that's why I still use static public directory. Thanks @AdvaitJunnarkar!Vocable
when i move faricon or static file into public file, it didnt work anymoreTimmy
the documentation did it for meTripody
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 <link rel='shortcut icon' href='/favicon.ico' /> but the link stay without my basePath like that in my browser : <link rel="shortcut icon" href="/favicon.ico">Evalyn
how do we do that if we're using app router instead of pages?Polyester
As of 2023, Next13, simply adding the favicon to the public/ folder workedEluviation
U
72

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

Ulster answered 26/4, 2020 at 8:42 Comment(6)
Thank you! All I need is only replace the current favicon.ico on public folder. Using next v10.0.2Pinguid
the best answer!Stubborn
This problem with this though is the formats are wrong since there needs to be atleast 24 favicon assets?Surpassing
This worked perfectly for me, simply added ico file to /public and boom!Seating
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.Attaway
Need to be inside "public/images" folder with Next.js 18.Judicator
B
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>
    );
  }
}
Baugher answered 8/12, 2019 at 1:48 Comment(2)
it is not working for me, the only way which works is that i put faricon into static folderTimmy
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.Baugher
W
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.

Warner answered 3/6, 2020 at 5:25 Comment(4)
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.Duffer
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 [email protected].Warner
I'm using [email protected] either. but still got the same problem :(Duffer
I'm using Next 9.5.0, I placed the favicon.ico file inside public directory and voila it worked!! thanks @AndresZapataTocci
P
22

Only adding .ico file is not enough.

It is not enough as the default.ico file will be used only by desktop browsers. You need to support different devices like tables, smartphones, etc. By adding different sizes the app could be stored on smartphone desktop.

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.

Pless answered 7/5, 2020 at 6:44 Comment(6)
Thx a lot. It's to much code for one favicon, I think, but your solution helpedRepercussion
The only right answer; since you need 24 favicons at least to be complient across devices.Surpassing
This wont' work in next 12, they got rid of PNG and SVG loadersHearne
@Hearne 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.Pless
@Pless - docs on new Next compiler: 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.Hearne
Also worth reviewing - github.com/vercel/next.js/discussions/26167Hearne
C
7

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,
}
Collete answered 24/8, 2022 at 18:27 Comment(0)
S
6

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

Starbuck answered 17/5, 2023 at 12:29 Comment(0)
W
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;

Wall answered 25/9, 2020 at 0:20 Comment(0)
D
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.

Daviddavida answered 27/6, 2022 at 14:22 Comment(0)
R
3

Next JS App Router, Pages Router v13+

For some reason favicon isn't working if the file name is the same as default (i.e favicon.ico) after some combinations, changing the name to icon.ico worked in both the routers ✅

App Router

  1. Delete default vercel icon ( favicon.ico )
  2. Add your custom favicon with file name ( icon.ico ) in /app directory

Pages Router

  1. Add your custom favicon with file name ( icon.ico ) in /public directory
  2. Add <link rel="icon" type="image/x-icon" href="/icon.ico"></link> in _document.js
<Html lang="en">
  <Head>
    <link rel="icon" type="image/x-icon" href="/icon.ico"></link>
  </Head>
  <body>
    <Main />
    <NextScript />
  </body>
</Html>

PS: deleting of default favicon.ico (vercel favicon) is not required in pages router, but do delete if not used

Docs

Redvers answered 27/10, 2023 at 18:6 Comment(0)
J
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>
Joslin answered 27/5, 2021 at 11:49 Comment(0)
J
2

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

Judicator answered 7/10, 2022 at 15:20 Comment(1)
This is the correct answer for Next.js v18 (April 2023)Perdition
M
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.

Mudslinger answered 28/5, 2023 at 4:49 Comment(0)
F
1

(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!

Free answered 29/6, 2023 at 20:7 Comment(0)
C
1

I had this issue with Next.js 14.1. Per the documentation I put favicon.ico in the root of the /app directory but I could not get it to display in the browser. I also tried moving it to /public/images and /public/img with no luck.

Changing the name from favicon.ico to icon.ico and keeping it in the /app directory solved the issue.

Coblenz answered 7/3, 2024 at 2:0 Comment(0)
A
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
Associative answered 12/1, 2022 at 19:55 Comment(0)
I
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).

Imminence answered 26/4, 2023 at 20:18 Comment(1)
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.Panpipe
G
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

Grapeshot answered 17/7, 2023 at 13:54 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.