Set Up Next.js Favicons with Just 3 Files


TL;DR

Essential Favicons Setup

For a quick and efficient favicon setup in Next.js, you only need these three files:

  1. favicon.ico

    • Purpose: The classic favicon displayed in browser tabs.
    • Placement: Place a 32×32 favicon.ico file in the app directory. Next.js will automatically serve it at /favicon.ico.
  2. icon.svg

    • Purpose: Modern browsers prefer SVG icons for scalability and crispness.

    • Placement: Save your SVG icon as icon.svg in the public directory.

    • Usage in Next.js Metadata:

         {
           rel: 'icon',
           url: '/icon.svg',
           type: 'image/svg+xml',
         }
      
      
  3. apple-touch-icon

    • Purpose: Used when users add your website to their iOS home screen.

    • Placement: Add a 180×180 PNG named apple-touch-icon.png to the public directory.

    • Usage in Next.js Metadata:

         {
           rel: 'apple-touch-icon',
           sizes: '180x180',
           url: '/apple-touch-icon.png',
         }
      

Note:

  • The app directory in Next.js 13 (using the App Router) is special because placing a favicon.ico file at the root of this directory ensures it's automatically served at /favicon.ico without additional configuration.
  • The public directory is ideal for other static assets because it's served at the root (/) of your application, making it straightforward to reference these files in your code.

This minimal setup ensures compatibility with most browsers and devices, providing essential icon support without unnecessary complexity.


Expanded Setup for PWA Support

If your app is a Progressive Web App (PWA), you'll need to define additional icons in a manifest.json file. This enhances the user experience when your app is installed on a device.

Additional Icons for PWAs

  1. 192×192 PNG

    • Purpose: Used for Android home screen icons and in notifications.
    • Placement: Save as icon-192.png in the public directory.
  2. 512×512 PNG

    • Purpose: The default icon for splash screens when the app is launched.
    • Placement: Save as icon-512.png in the public directory.
  3. 512×512 Maskable PNG

    • Purpose: Ensures proper display on devices that apply masks to icons (e.g., Android devices with non-rectangular shapes).
    • Placement: Save as icon-maskable.png in the public directory.
    • Design Consideration: Include extra padding. The safe area for a maskable icon is a central circle of 409×409 pixels inside the 512×512 canvas. Use tools like maskable.app to adjust the padding correctly.

Example Manifest File

Create a manifest.json file in the public directory:

{
  "name": "Your App Name",
  "short_name": "App",
  "start_url": ".",
  "display": "standalone",
  "background_color": "#FFFFFF",
  "description": "Your app description",
  "icons": [
    { "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
    {
      "src": "/icon-maskable.png",
      "type": "image/png",
      "sizes": "512x512",
      "purpose": "maskable"
    },
    { "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
  ]
}

HTML Reference for Non-Next.js Apps

If you're not using Next.js, include the following in your <head>:

<link
  rel="icon"
  href="/apps/startupstarterkits.com/public/favicon.ico"
  sizes="32x32"
/>
<link rel="icon" href="/icon.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<link rel="manifest" href="/manifest.json" />

Generating the favicon.ico File

To generate the .ico file with 128x128, 64x64, 48x48, 32×32 and 16×16 resolutions, use ImageMagick:

** Note use a 1200x1200 image for best results **

magick source.png -resize 16x16 icon-16.png
magick source.png -resize 32x32 icon-32.png
magick source.png -resize 48x48 icon-48.png
magick source.png -resize 64x64 icon-64.png
magick source.png -resize 128x128 icon-128.png

Combine them into a single favicon.ico file.

magick icon-128.png icon-64.png icon-48.png icon-32.png icon-16.png favicon.ico

Place the generated favicon.ico in your application's root directory.


Optional: Theming with Media Queries

For advanced theming, you can define light and dark mode icons using media queries in the metadata.icons array:

export const metadata = {
  icons: [
    {
      rel: 'icon',
      media: '(prefers-color-scheme: light)',
      url: '/icon-light.svg',
      type: 'image/svg+xml',
    },
    {
      rel: 'icon',
      media: '(prefers-color-scheme: dark)',
      url: '/icon-dark.svg',
      type: 'image/svg+xml',
    },
  ],
}

This setup automatically displays the appropriate icon based on the user's system settings, enhancing user experience by aligning with their preferred theme.


Understanding the Purpose of Each Icon

favicon.ico

  • Purpose: The default icon displayed in browser tabs and bookmarks.
  • Why It's Needed: Provides brand recognition and improves user experience by allowing users to quickly identify your site among multiple tabs.
  • Placement in Next.js: Place it in the app directory root. Next.js will automatically serve it at /favicon.ico.

icon.svg

  • Purpose: A scalable icon for modern browsers, ensuring crisp display on all devices.
  • Why It's Needed: SVGs scale without loss of quality, making them ideal for high-resolution displays.
  • Placement: Place in the public directory.

apple-touch-icon.png

  • Purpose: Used when iOS users add your website to their home screen.
  • Why It's Needed: Ensures your app icon looks professional and recognizable on iOS devices.
  • Placement: Place in the public directory.

SEO and Accessibility Considerations

  • Brand Recognition: Consistent and professional icons improve brand visibility across devices and platforms.
  • User Experience: Properly sized and formatted icons ensure a seamless experience, whether users are browsing, bookmarking, or adding your app to their home screen.
  • Accessibility: High-quality icons with appropriate sizes enhance readability and usability for all users.

Troubleshooting Tips

  • Browser Caching: Browsers often cache favicons and may not immediately reflect updates.

    Solution: Instruct users (or yourself during testing) to clear the browser cache or perform a hard refresh (usually Ctrl+F5 or Cmd+Shift+R).

  • Incorrect File Paths: Ensure that your icon files are placed in the correct directories and that the paths in your code match.

  • Missing Sizes or Types: Omitting sizes or type attributes can lead to browsers ignoring your icons.

    Solution: Always specify the sizes and type attributes in your metadata or HTML tags.


Additional Resources


Recap: All the Icons You Need

Here's a summary of all the icons and their configurations for a fully functional setup:

Files to Include

  • favicon.ico: 32×32 (placed in app/ directory)
  • icon.svg: Scalable SVG icon (placed in public/ directory)
  • apple-touch-icon.png: 180×180 PNG (placed in public/ directory)
  • icon-192.png: 192×192 PNG (for Android home screens)
  • icon-512.png: 512×512 PNG (for splash screens)
  • icon-maskable.png: 512×512 PNG with padding (for maskable icons)

Next.js Metadata Example

{
  "icons": [
    {
      rel: 'icon',
      url: '/icon.svg',
      type: 'image/svg+xml',
    },
    {
      rel: 'apple-touch-icon',
      sizes: '180x180',
      url: '/apple-touch-icon.png',
    },
    // Only required for PWA apps.
    {
      rel: 'manifest',
      url: '/manifest.json',
    }
  ]
}

A Simple Favicon Solution for MVPs

If you’re building a Minimum Viable Product (MVP) or want a quick solution without worrying about multiple icon sizes, use Next.js’s built-in ImageResponse to generate a simple 32×32 favicon dynamically:

export const contentType = 'image/png'

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

Why This Works

  • Dynamic Generation: The favicon is created on the fly.
  • Simple Setup: Great for MVPs or quick projects that don’t require complex configurations.
  • Good Enough for Most Scenarios: Works well for browser tabs but may not suit PWAs or iOS home screen icons.

Start with this approach and upgrade to a more comprehensive setup as your project grows.


Make It Even Easier with SSK

Dealing with favicons, PWA icons, and metadata can feel like a hassle, especially during crunch time. What if you could skip all the manual work?

✨ Meet StartupStarterKits.com, your new go-to for app development:

  • Zero Fuss: SSK-Core sets up everything for you—from favicons to PWA icons and even manifest.json.
  • Time-Saving: Spend more time building features and less time wrestling with metadata.
  • Scalable Solution: Whether you’re a solo dev or part of a big team, SSK handles the complexity for you.
SSK-Pro

Think of SSK as the ultimate dev toolkit—it takes care of the nitty-gritty so you can focus on what really matters. Try it today.


Conclusion

Setting up favicons in Next.js doesn’t have to be complicated. With just three files, you can ensure your app looks polished and professional across browsers and devices. For more advanced setups, adding PWA support and media queries enhances the user experience even further.

Feeling overwhelmed? StartupStarterKits.com has your back, handling everything so you can focus on innovation.

Cheers,
Tómas