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:
- Using image files
- 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 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 which generated the other icons I needed:
- favicon.ico
- apple-touch-icon.png
- android-chrome-192x192.png
- 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:
- favicon.ico
- icon.svg
- 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!