Next.js: favicon, SVG icon, Apple & Chrome icons
Tags: nextjs, webdev, blog, metadata
Published: 2023-11-21 15:31:17

---
title: Next.js: favicon, SVG icon, Apple & Chrome icons
published: true
date: 2023-11-13 00:00:00 UTC
tags: nextjs,webdev,blog,metadata
canonical_url: https://www.davegray.codes/posts/nextjs-favicon-svg-icon-apple-chrome
cover_image: https://raw.githubusercontent.com/gitdagray/my-blogposts/main/images/nextjs-favicon-svg-icon-apple-chrome.png
---

I began discussing [Next.js Metadata](https://www.davegray.codes/posts/nextjs-ordering-merging-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](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/app-icons) 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](https://dev.to/masakudamatsu/favicon-nightmare-how-to-maintain-sanity-3al7) _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:

```html
<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]((https://dev.to/masakudamatsu/favicon-nightmare-how-to-maintain-sanity-3al7)).

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](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/app-icons) 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](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/app-icons#generate-icons-using-code-js-ts-tsx) 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: 

```html 
<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](https://www.canva.com/), but you can also use [RealFaviconGenerator.net](https://realfavicongenerator.net/) 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 [RealFaviconGenerator.net](https://realfavicongenerator.net/) 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](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/manifest) 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:

```ts 
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](https://developer.mozilla.org/en-US/docs/Web/Manifest). If you leave some of these out, [Lighthouse](https://developer.chrome.com/en/docs/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:_

```html 
<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](https://dev.to/masakudamatsu/favicon-nightmare-how-to-maintain-sanity-3al7) 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!_ 

<hr>

## Let's Connect!

Hi, I'm Dave. I work as a full-time developer, instructor and creator. 

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

**My Stuff:** [Courses, Cheat Sheets, Roadmaps](https://courses.davegray.codes/)

**My Blog:** [davegray.codes](https://www.davegray.codes/)

**YouTube:**  [@davegrayteachescode](https://www.youtube.com/davegrayteachescode) 

**X:**  [@yesdavidgray](https://x.com/yesdavidgray)  

**GitHub:** [gitdagray](https://github.com/gitdagray)

**LinkedIn:**  [/in/davidagray](https://www.linkedin.com/in/davidagray/) 

**Buy Me A Coffee:**  [You will have my sincere gratitude](https://www.buymeacoffee.com/davegray)   

Thank you for joining me on this journey. 

Dave