Next.js

Favicons in Next.js — the modern App Router setup

How to ship a complete modern favicon set in a Next.js App Router project. Where files go, which metadata API to use, and the specific gotchas of the /app directory.

Next.js App Router has its own file-based metadata convention. Knowing the convention saves you from manually writing <link> tags or importing a head component. This guide is the modern setup, App Router only (if you are on Pages Router, see the note at the end).

The file layout

Drop these into app/:

app/
├── favicon.ico
├── icon.svg
├── icon.png
├── apple-icon.png
└── manifest.webmanifest

That is it. Next auto-generates the correct <link> tags for each file it finds. No imports, no manifest object.

  • favicon.ico — served at /favicon.ico, linked as shortcut icon
  • icon.svg — the modern SVG favicon, linked with type="image/svg+xml"
  • icon.png — fallback PNG for browsers that do not support SVG
  • apple-icon.png — the 180×180 iOS home screen icon
  • manifest.webmanifest — linked with rel="manifest"

If you want multi-size PNGs, name them with their dimensions: icon-96x96.png, icon-192x192.png, etc. Next reads the filename and emits the right sizes attribute.

Where to put the manifest icons

Both web-app-manifest-192x192.png and web-app-manifest-512x512.png live in /public. They are referenced from manifest.webmanifest by path, not filename convention.

{
  "icons": [
    {
      "src": "/web-app-manifest-192x192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any maskable"
    },
    {
      "src": "/web-app-manifest-512x512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any maskable"
    }
  ]
}

When to use the metadata API instead

If you need paths outside /app or want to conditionally inject icons based on route, use the metadata export in your root layout.tsx:

import type { Metadata } from "next";

export const metadata: Metadata = {
  icons: {
    icon: [
      { url: "/favicon.svg", type: "image/svg+xml" },
      { url: "/favicon-96x96.png", sizes: "96x96", type: "image/png" },
    ],
    shortcut: "/favicon.ico",
    apple: "/apple-touch-icon.png",
  },
  manifest: "/site.webmanifest",
};

The file-based convention is preferred. Use the metadata API only when the convention cannot express what you need.

Common pitfalls

  • Duplicate <link> tags. Do not put favicon files in both /app and /public with the same names. Next will emit a metadata tag for the /app file and the browser will also hit /public. Pick one.
  • Stale /favicon.ico. The edge caches /favicon.ico aggressively. After changing the file, rename or hash it, or add a version query on the <link> tag.
  • Missing apple-icon. Next requires apple-icon.png (singular icon), not apple-touch-icon.png. If you copy the file verbatim from the public convention, rename on the way in.
  • theme-color meta. Set it via metadata.themeColor in your root layout, not in manifest only.

Pages Router quick note

Legacy Pages Router projects do not get the file-based metadata. Put favicon files in /public and add <link> tags inside pages/_document.tsx or next/head in _app.tsx. The tag set is the standard five links documented in favicon sizes.

Generate the set

Drop your logo SVG into Faviconry, download the zip, copy the Next App Router-named files (icon.svg, apple-icon.png, favicon.ico) into /app, and copy the manifest + 192/512 PNGs into /public. Two minutes end-to-end.

Frequently asked questions

Do I need to add icons to metadata or just drop them in public?

For App Router, put files like icon.svg, apple-icon.png, and favicon.ico directly inside /app. Next's file-based metadata system picks them up automatically and emits the correct <link> tags. You only need the metadata.icons object if you want paths outside this convention, like /public-hosted CDN URLs.

Why does my favicon not update after deploy?

Next.js aggressively caches /favicon.ico at the edge. After deploying a new icon, browsers also cache favicons per hostname for days. Force a refresh by renaming the file, changing the content hash, or hard-reloading with dev tools open and cache disabled.

Can I use an SVG as my primary favicon in Next?

Yes. Name it icon.svg inside /app and Next emits the SVG favicon link automatically. It also generates a matching <meta> tag set. Keep a favicon.ico alongside for legacy browsers and the root /favicon.ico fallback.