Next.js: favicon, SVG icon, Apple & Chrome icons

Next.js: favicon, SVG icon, Apple & Chrome icons


5 min read

I began discussing Next.js Metadata in my last blog post, and I set up some basic information for my blog. That said, there are still a few areas to take a deeper dive on and the first is how to handle favicon and icon requirements.

Next.js Favicons

The Next.js docs on Metadata Files provided guidance. However, I also wanted to find general recommendations for these icon files on the web.

Fortunately, I discovered an in-depth article titled Definitive edition of "How to Favicon" in 2023 by Masa Kudamatsu. It could be my background in higher education, but I liked this article very much as Kudamatsu cited references from his research throughout his writing.

According to Kudamatsu, we need the following in the <head> element of our web pages:

<link rel="icon" href="/favicon.ico" sizes="48x48" >
<link rel="icon" href="/favicon.svg" sizes="any" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png"/>
<link rel="manifest" href="/site.webmanifest" />

Kudamatsu has specific reasons for each link above. Most interesting is his recent August 2023 update for using sizes="48x48" on the favicon.ico. I won't dive into it here, but I highly recommend reading the article.

As of this writing in November 2023, I wanted to see if Next.js could provide Kudamatsu's recommendations for favicons. I found that it can, and I'll provide how I got there.

The Next.js Metadata Files docs provide two ways to set app icons:

  1. Using image files
  2. Using code to generate an icon

Generate an Icon

Of course, I wanted to use code to generate an icon or icons if I could. However, I found the docs later state under a Good to know footnote that you cannot generate a favicon icon.

Nevertheless, I tried the provided code in the docs for creating an icon.tsx in my app directory. It does generate an icon.

Here is the icon I found in the <head> of my page when using the icon.tsx file to generate an icon:

<link rel="icon" href="/icon?064c227bb33add9b" type="image/png" sizes="32x32">

So that was worth a try, but I quickly decided to go the image files route instead.

Using Image Files

Step One: Create an SVG Icon

There are many tools you can use to create an SVG icon. I used Canva, but you can also use which is where I went after creating my SVG icon. No matter what tool you use, save the file as icon.svg so Next.js will recognize it.

Step Two: Generate the Remaining Icons

I took the SVG icon I created and uploaded it to which generated the other icons I needed:

  1. favicon.ico
  2. apple-touch-icon.png
  3. android-chrome-192x192.png
  4. android-chrome-512x512.png

It also generated a file named site.webmanifest, but I will show my own manifest file below. You can also discard any other generated files.

Step Three: Rename Files

Not all of the files listed above have names that are compatible with Next.js. Specifically, the apple-touch-icon.png needs to be renamed to apple-icon.png. I also renamed the android-chrome files to simply icon-192.png and icon-512.png, but that was my preference.

Step Four: Web Manifest

You need the Web Manifest to identify the two android-chrome icons. You won't see a direct link to these icons in the <head> element, but you will see a link to the manifest file.

The Next.js manifest docs allow for a static file or for a generated file. The manifest must be named manifest.json or manifest.webmanifest and be at the root level of the app directory.

I opted to generate my manifest with the function provided in the Next.js docs.

Here is what my manifest.ts file contains:

import { MetadataRoute } from 'next'

export default function manifest(): MetadataRoute.Manifest {
    return {
        name: 'Dave Gray Teaches Code',
        short_name: "Dave Gray",
        description: "Dave's Blog powered by Next.js",
        start_url: '/',
        display: 'standalone',
        background_color: '#1E283A',
        theme_color: '#1E283A',
        icons: [
                "src": "/images/icon-192.png",
                "sizes": "192x192",
                "type": "image/png"
                "src": "/images/icon-512.png",
                "sizes": "512x512",
                "type": "image/png"

If you are curious about the settings above, you can read the Web Manifest specs. If you leave some of these out, Lighthouse may complain when evaluating your site.

Note: You only need to provide info for the two android-chrome icons in this file as I did above.

Step Five: Where to Put Your Files

You should now have the following files in root of your app directory:

  1. favicon.ico
  2. icon.svg
  3. manifest.ts

And you should have the android-chrome icons in your public folder.

I'm using an images folder inside my public folder, so notice my manifest file has /images/icon-192.png. You do not have to specify your public folder as part of the file path in the manifest.

Step Six: Build Your App

Open a terminal window and type npm run dev.

Open up your Next.js app in your browser and inspect the <head> element.

You should now see the following links:

<link rel="manifest" href="/manifest.webmanifest">
<link rel="icon" href="/favicon.ico" type="image/x-icon" sizes="48x48">
<link rel="icon" href="/icon.svg?f4ac04897a3b2294" type="image/svg+xml" sizes="any">
<link rel="apple-touch-icon" href="/apple-icon.png?ebbb82dc3cc1b5eb" type="image/png" sizes="180x180">

Note: The manifest link may not be next to the icon links, but it should be in there somewhere.

With Kudamatsu updating his article to recommend the sizes="48x48" setting for the favicon.ico in August, I'm glad to see that is already reflected in how Next.js handles that file!

Let's Connect!

If you enjoyed this article, you might enjoy my other content, too.

My Stuff: Courses, Cheat Sheets, Roadmaps

YouTube: @davegrayteachescode

X: @yesdavidgray

GitHub: gitdagray

LinkedIn: /in/davidagray

Buy Me A Coffee: You will have my sincere gratitude

Thank you for joining me on this journey.