Next.js Favicon Complete Guide

Master favicon setup in Next.js: App Router (13+), Pages Router (12-), Metadata API, automatic optimization, and best practices.

Next.js 13+ (App Router) - Recommended

Automatic Favicon Handling

1. File Structure (Automatic)

my-next-app/
  app/
    favicon.ico           ? Automatic! (16x16, 32x32, 64x64)
    icon.png              ? Automatic! Generates multiple sizes
    apple-icon.png        ? Automatic! Apple touch icon
    layout.tsx
  public/
    site.webmanifest
  package.json
Magic! Next.js 13+ automatically generates all favicon sizes from app/icon.png or app/favicon.ico

2. Using Metadata API (app/layout.tsx)

import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'My Next.js App',
  description: 'App description',
  icons: {
    icon: [
      { url: '/favicon.ico' },
      { url: '/icon.png', sizes: '32x32', type: 'image/png' },
      { url: '/icon-192.png', sizes: '192x192', type: 'image/png' },
      { url: '/icon-512.png', sizes: '512x512', type: 'image/png' },
    ],
    apple: [
      { url: '/apple-icon.png' },
      { url: '/apple-icon-180.png', sizes: '180x180', type: 'image/png' },
    ],
    other: [
      {
        rel: 'mask-icon',
        url: '/safari-pinned-tab.svg',
        color: '#000000'
      }
    ]
  },
  manifest: '/site.webmanifest',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

3. Dynamic Icon Generation (Advanced)

// app/icon.tsx (or icon.js)
import { ImageResponse } from 'next/og'

export const runtime = 'edge'

export const size = {
  width: 32,
  height: 32,
}

export const contentType = 'image/png'

export default function Icon() {
  return new ImageResponse(
    (
      <div
        style={{
          fontSize: 24,
          background: 'black',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          color: 'white',
        }}
      >
        A
      </div>
    ),
    {
      ...size,
    }
  )
}

4. Public Folder (Manual Files)

public/
  favicon-16x16.png
  favicon-32x32.png
  android-chrome-192x192.png
  android-chrome-512x512.png
  site.webmanifest
  browserconfig.xml

Next.js 12- (Pages Router)

Legacy Setup

1. File Structure

my-next-app/
  public/                 ? Place all favicons here
    favicon.ico
    favicon-16x16.png
    favicon-32x32.png
    apple-touch-icon.png
    android-chrome-192x192.png
    android-chrome-512x512.png
    site.webmanifest
  pages/
    _document.tsx
    index.tsx

2. Update pages/_document.tsx

import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html lang="en">
      <Head>
        {/* Favicons */}
        <link rel="icon" type="image/x-icon" href="/favicon.ico" />
        <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
        <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
        <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
        
        {/* Android/Chrome */}
        <link rel="icon" type="image/png" sizes="192x192" href="/android-chrome-192x192.png" />
        <link rel="icon" type="image/png" sizes="512x512" href="/android-chrome-512x512.png" />
        
        {/* Web App Manifest */}
        <link rel="manifest" href="/site.webmanifest" />
        
        {/* Theme Color */}
        <meta name="theme-color" content="#000000" />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

3. Per-Page Override (Optional)

// pages/custom-page.tsx
import Head from 'next/head'

export default function CustomPage() {
  return (
    <>
      <Head>
        <link rel="icon" href="/custom-favicon.ico" />
      </Head>
      <div>Custom page with different favicon</div>
    </>
  )
}

Next.js Favicon Best Practices

? Best Practices

  • Use app/icon.png for automatic generation (13+)
  • Leverage Metadata API for type safety
  • Use /public for manual files
  • Include web manifest for PWA
  • Test both dev and production builds
  • Optimize images with next/image
  • Set proper cache headers
  • Use SVG for scalable icons

? Common Mistakes

  • Not using Metadata API (13+)
  • Placing favicons outside /public
  • Missing _document.tsx (Pages Router)
  • Not testing production build
  • Using wrong paths (relative vs absolute)
  • Forgetting manifest.json
  • Not optimizing image sizes
  • Missing theme-color meta tag

Generate Next.js-Ready Favicons

Create optimized favicon packages for Next.js applications

Generate Favicons

Related Articles

An unhandled error has occurred. Reload 🗙