Next.js

Add a favicon to a Next.js App Router or Pages Router project

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.

Quick answer for the App 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 .