How to add a favicon to a Next.js static site?

Faviconnext.jsStatic Site

Favicon Problem Overview


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?

Favicon Solutions


Solution 1 - Favicon

  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>
);

Solution 2 - Favicon

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>
    );
  }
}

Solution 3 - Favicon

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

Solution 4 - Favicon

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.

Solution 5 - Favicon

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.

Solution 6 - Favicon

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;

Solution 7 - Favicon

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>

Solution 8 - Favicon

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAdvait JunnarkarView Question on Stackoverflow
Solution 1 - FaviconAdvait JunnarkarView Answer on Stackoverflow
Solution 2 - Faviconuser3272018View Answer on Stackoverflow
Solution 3 - FaviconVigneshwaran ChandrasekaranView Answer on Stackoverflow
Solution 4 - FaviconAndres ZapataView Answer on Stackoverflow
Solution 5 - FaviconBlackView Answer on Stackoverflow
Solution 6 - FaviconSoundsLikeNateView Answer on Stackoverflow
Solution 7 - FaviconTravnikov.devView Answer on Stackoverflow
Solution 8 - FaviconwingsView Answer on Stackoverflow