DEV Community

Jakub T. Jankiewicz
Jakub T. Jankiewicz

Posted on • Updated on

Favicon for Next.js and TypeScript

I'm still learning Next.js and after having hard time to find out of the box solution to create favicon that will work everywhere, after done this myself, I've decided to create quick article about this.

What is favicon

Favicon is small icon that is usually shown in browser tab next to title of the site. Some Operating System display it differently, like Android or MacOS.

Best way to get Favicon that will just work

The best way to get favicon that will work on every device is to use generator that will do that for you.

I personally use Real Favicon Generator I trust that It create favicon for every possible use case.

To generate favicon you just upload an image. If you want best possible favicon you can generate one for MacOS and Windows that often need different background.

I personally always create favicon (that is just based on logo) in vector format (using Free Libre Open Source program Inkscape).

When you generate favicon remember to use /favicon directory.

Where to put the files

The files should be extracted into /public/ directory of Next.js project. So the files will be in in /public/favicon/. If you didn't use /favicon path when creating icons you will need to create one.

Next.js component

Now you need to add favicon that you've generated with Favicon Generator. The best idea is to create component called <Favicon/> that you can use in rest of the application:

// /compoponents/Favicon.tsx
const Favicon = (): JSX.Element => {
    return (
        <>
          {/* copy paste the html from generator */}
        </>
     );
}

export default Favicon;
Enter fullscreen mode Exit fullscreen mode

When you copy paste the html it will look similar to this:

// /compoponents/Favicon.tsx
type FaviconProps = {
    name: string;
};

const Favicon = ({ name }: FaviconProps): JSX.Element => {
    return (
        <>
            <link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png"/>
            <link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png"/>
            <link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png"/>
            <link rel="manifest" href="/favicon/site.webmanifest"/>
            <link rel="mask-icon" href="/favicon/safari-pinned-tab.svg" color="#5bbad5"/>
            <meta name="apple-mobile-web-app-title" content="Snippit"/>
            <meta name="application-name" content={name}/>
            <meta name="msapplication-TileColor" content="#ffc40d"/>
            <meta name="theme-color" content="#ffffff"/>
        </>
    );
}

export default Favicon;
Enter fullscreen mode Exit fullscreen mode

You may need to close each tags, so they are a proper JSX.

Using component

To use new <Favicon/> component you need to update _document.tsx file.

Here is base document that you can use and extend. Or modify and just add <Favicon/> into <Head> tag.

You also need to provide the name of your app in the name prop.

// /pages/_document.tsx
import Document, { Head, Html, Main, NextScript, DocumentContext } from "next/document";

import Favicon from '../components/Favicon';

class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext): Promise<Record<string, unknown> & {html: string}> {
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps };
  }

  render(): JSX.Element {
    return (
      <Html>
        <Head>
          <meta charSet="utf-8" />
          <Favicon name="My Awesome Page"/>
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;
Enter fullscreen mode Exit fullscreen mode

And that's it. If you want some better performance you can use compression when generating favicon.

If you like this post, you can follow me on twitter at @jcubic and check my home page.

And here you can find some NextJS jobs.

Latest comments (0)