How to Add a Favicon to Next.js
Next.js can generate favicon link tags from files in the
app directory, or serve a traditional favicon
package from public. The best setup depends on
whether your project uses the App Router or Pages Router.
Put favicon.ico in the root of your
app directory:
app/
favicon.ico
layout.tsx
page.tsx
Next.js detects app/favicon.ico and adds the
favicon link tag to your site's document head automatically.
Step 1: Generate Your Favicon Files
Start with a square logo or image. Use our
image to favicon converter
to create favicon.ico, PNG icons, an Apple Touch
Icon, Android icons, and a web manifest in one download. If you
need a simple letter icon, use the
text favicon generator.
Method 1: Next.js App Router (Recommended)
For an App Router project, place favicon.ico in the
root app directory. The favicon file convention is
supported only at that root level.
your-project/
app/
favicon.ico
layout.tsx
page.tsx
You can also give Next.js dedicated PNG files for modern browser
and Apple surfaces. Rename files from the downloaded package as
shown below:
your-project/
app/
favicon.ico
icon.png # rename favicon-32x32.png
apple-icon.png # rename apple-touch-icon.png
layout.tsx
page.tsx
Next.js reads the image dimensions and MIME type, then generates
the corresponding rel="icon" and
rel="apple-touch-icon" tags. You do not need to add
those tags manually.
Method 2: Keep the Complete Package in Public
Use the public directory when you want to keep the
original favicon.io filenames or serve the full package. Every
file in public is available from the root URL.
your-project/
public/
favicon.ico
favicon-16x16.png
favicon-32x32.png
apple-touch-icon.png
android-chrome-192x192.png
android-chrome-512x512.png
site.webmanifest
For example, public/favicon.ico is served at
https://example.com/favicon.ico.
App Router metadata for public files
If you keep the package in public, reference the
files from the metadata export in your root
app/layout.tsx:
import type { Metadata } from "next";
export const metadata: Metadata = {
icons: {
icon: [
{ url: "/favicon.ico" },
{ url: "/favicon-16x16.png", sizes: "16x16", type: "image/png" },
{ url: "/favicon-32x32.png", sizes: "32x32", type: "image/png" },
],
apple: "/apple-touch-icon.png",
},
manifest: "/site.webmanifest",
};
Method 3: Next.js Pages Router
Pages Router projects should place favicon.ico and
any additional favicon files in public. The browser
can request /favicon.ico directly. To declare the
complete package explicitly, add the link tags to
pages/_document.js:
import { Html, Head, Main, NextScript } from "next/document";
export default function Document() {
return (
<Html lang="en">
<Head>
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
Step 3: Verify the Favicon
Start or rebuild your Next.js app, then open the site in a new
private window. You can also visit /favicon.ico,
/icon.png, or another configured icon URL directly
to confirm the file is being served.
After deployment, run the
favicon checker against
your production URL. It will inspect favicon link tags, common
icon files, Apple Touch Icon setup, and the web manifest.
Troubleshooting Next.js Favicons
- Favicon returns 404: Confirm the file is named
exactly
favicon.ico. App Router projects must put
it at app/favicon.ico; Pages Router projects should
use public/favicon.ico.
- Old favicon still appears: Browsers cache
favicons aggressively. Test in a private window, clear the
browser cache, or temporarily change the icon filename.
- Duplicate favicon tags: Do not combine App
Router icon files with a second set of identical manual
metadata entries. Choose one primary method.
- Works locally but not after deployment: Check
the exact icon URL on the production domain and make sure file
capitalization matches. Linux deployment filesystems are case
sensitive.
- Google still shows the old favicon: Confirm
the production icon is crawlable, then request homepage
indexing in Google Search Console. Search-result updates can
take longer than browser-tab updates.
Next.js Favicon FAQ
Where does favicon.ico go in Next.js?
In an App Router project, put it at
app/favicon.ico. In a Pages Router project, put it
at public/favicon.ico so it is served from
/favicon.ico.
Does Next.js add favicon tags automatically?
Yes for App Router metadata files. Next.js automatically creates
the link tags for app/favicon.ico,
app/icon.png, and app/apple-icon.png.
Files kept in public can be referenced through a
metadata export or manual link tags.
Should a Next.js favicon use ICO or PNG?
Use both when possible. favicon.ico is the universal
fallback, while PNG files provide explicit modern sizes and an
Apple Touch Icon. The favicon.io package includes all of them.
Why is my Next.js favicon not updating?
Browser caching is usually the cause. Verify the icon URL
directly, test in a private window, and restart the development
server after adding a new metadata file.
For the underlying framework behavior, see the official
Next.js icon metadata documentation
and
public folder documentation
.