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 iconicon.svg— the modern SVG favicon, linked withtype="image/svg+xml"icon.png— fallback PNG for browsers that do not support SVGapple-icon.png— the 180×180 iOS home screen iconmanifest.webmanifest— linked withrel="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/appand/publicwith the same names. Next will emit a metadata tag for the/appfile and the browser will also hit/public. Pick one. - Stale /favicon.ico. The edge caches
/favicon.icoaggressively. 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(singularicon), notapple-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.
Other frameworks
- React React itself has no favicon convention. Your bundler does. This guide covers the modern setup for Vite-powered React, Create React App, and framework-less setups.
- Astro Every Astro site ships favicons the same way: drop files in /public, link them from a BaseLayout. This guide is the modern five-file setup for Astro projects.