How to Add Favicons to Your Next.js App (App Router)
A step-by-step walkthrough for setting up favicons in Next.js 14+ with the App Router. Covers file conventions, metadata API, and common pitfalls.
Next.js 13 introduced the App Router, which changed how favicons work. Instead of manually writing link tags in a custom document, you drop files into the app/ directory and Next.js generates the metadata automatically. It is simpler once you understand the conventions, but the documentation leaves gaps that trip people up. If you do not have favicon files yet, our complete sizes guide covers every file you need.
The File Convention Approach
The easiest method is to place specially named files in your app/ directory. Next.js recognizes these filenames and generates the appropriate <link> and <meta> tags in your HTML head automatically.
app/
favicon.ico → <link rel="icon" />
icon.png → <link rel="icon" type="image/png" />
icon.svg → <link rel="icon" type="image/svg+xml" />
apple-icon.png → <link rel="apple-touch-icon" />
opengraph-image.png → <meta property="og:image" />
twitter-image.png → <meta name="twitter:image" />That is it for the basics
app/ directory and run your dev server, Next.js handles all the metadata. No configuration file needed, no import statements, nothing in your layout component. The framework does it automatically based on filenames.Size Requirements
Next.js is flexible about input sizes, but browsers have specific expectations. Getting the sizes wrong will not break anything, but it will produce blurry icons on some devices.
| File | Recommended Size | Why |
|---|---|---|
| favicon.ico | 48x48 (multi-size) | Covers 16, 32, 48px needs |
| icon.png | 512x512 | Sharp on high-DPI displays |
| apple-icon.png | 180x180 | Apple requirement for home screen |
| opengraph-image.png | 1200x630 | Aspect ratio for social cards |
| twitter-image.png | 1200x675 | Twitter card aspect ratio |
The Manifest Approach
For Progressive Web Apps and Android devices, you also need a web manifest that lists your icons. Next.js supports this through an app/manifest.ts file.
import type { MetadataRoute } from 'next'
export default function manifest(): MetadataRoute.Manifest {
return {
name: 'My App',
short_name: 'App',
start_url: '/',
display: 'standalone',
background_color: '#ffffff',
theme_color: '#DA7756',
icons: [
{
src: '/icon-192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: '/icon-512.png',
sizes: '512x512',
type: 'image/png',
},
{
src: '/icon-maskable-512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'maskable',
},
],
}
}The Metadata API Approach
If you need more control, say, different icons per route or dynamic icons, you can use the generateMetadata function instead.
import type { Metadata } from 'next'
export const metadata: Metadata = {
icons: {
icon: [
{ url: '/favicon.ico', sizes: '48x48' },
{ url: '/icon.svg', type: 'image/svg+xml' },
],
apple: '/apple-icon.png',
},
}Do not mix approaches
app/) and the metadata API to define icons, Next.js uses the metadata API and ignores the files. Pick one approach and stick with it.Common Pitfalls
Favicon not updating in development
Browsers cache favicons aggressively. If you replace your favicon and the old one still shows up, open a new incognito window or do a hard refresh (Ctrl+Shift+R). The dev server sometimes needs a restart too.
Favicon shows on localhost but not in production
Check that your files are in the app/ directory, not public/. In the App Router, the file convention specifically looks in app/. Files in public/ are served statically but do not trigger automatic metadata generation.
However, if your manifest.ts references icon paths like /icon-192.png, those files should be in public/ since the manifest URLs are served as-is.
Apple Touch Icon is the wrong size
Apple expects exactly 180x180 pixels for the apple-icon.png. If you provide a different size, iOS will resize it, and the result often looks blurry. Generate your icons at the correct dimensions from the start.
The Complete Setup
Here is the full set of files for a Next.js App Router project that covers all browsers, mobile, PWA, and social sharing.
app/
favicon.ico # Multi-size ICO (16, 32, 48)
icon.png # 512x512 PNG
icon.svg # SVG with dark mode support
apple-icon.png # 180x180 Apple Touch
opengraph-image.png # 1200x630 social preview
twitter-image.png # 1200x675 Twitter card
manifest.ts # PWA manifest with all icon refs
public/
android-chrome-192x192.png
android-chrome-512x512.png
icon-maskable-192.png
icon-maskable-512.pngIf maintaining all those files manually sounds tedious, tools like Iconello can generate the full package from a text prompt. Describe the icon you want and you get all the files at the correct sizes, ready to drop into your project. After setting up, run through the favicon testing checklist to verify everything works across browsers.
Related Articles
How to Test Your Favicon Across All Browsers and Devices
Your favicon looks great in Chrome but broken on Safari? A systematic testing checklist with tools and common failure modes.
How to Make a Favicon from Your Existing Logo
Your logo probably will not work as a favicon without changes. Here is the practical workflow for extracting, simplifying, and exporting a favicon from any logo.
How to Add a Favicon to WordPress (3 Methods)
WordPress has a built-in favicon feature, but it has limits. Three ways to set up your favicon, from simplest to most complete.