If you've ever opened your Next.js site on an iPhone and seen a blank gray square when adding it to the home screen, you're missing the Apple touch icon. The browser tab favicon might look fine, but iOS uses a separate file — and Next.js has a specific way to serve it.

This guide walks through the nextjs apple icon setup using the App Router's file-based metadata system. No custom API routes, no manual <link> tags in _document.tsx — just drop a file in the right folder and you're done.

Prerequisites

Before we start, make sure you have:

Step 1: Prepare the Apple Touch Icon

Apple's touch icon is a PNG file that iOS uses when a user adds your site to the home screen. The recommended size is 180×180 pixels, but you can also provide a 167×167 for iPad Pro and 152×152 for older iPads. However, iOS will automatically scale down a 180×180 icon, so you only need one file.

If you don't have a ready icon, you can generate one from your logo using a tool like Mzu favicondl. It can export a 180×180 PNG with the correct transparency and padding.

Step 2: Place the File in the App Directory

In Next.js App Router, you can add apple-icon.png (or apple-icon.jpg) directly in your app/ directory. Next.js automatically detects it and serves it at the root of your site. The file should be placed in the same folder as your layout.tsx — typically app/.

Here's an example folder structure:

app/
├── layout.tsx
├── page.tsx
├── apple-icon.png
└── icon.png

That's it. Next.js will automatically generate the appropriate <link rel='apple-touch-icon'> tag in the head of your pages. You don't need to write any HTML manually.

Step 3: Verify the Generated HTML

To confirm the icon is being served, run your dev server and inspect the page source. You should see a line like this:

<link rel='apple-touch-icon' href='/apple-icon.png' sizes='180x180' type='image/png'/>

If you don't see it, check that the file is named exactly apple-icon.png and is in the correct directory. Next.js is case-sensitive on Linux and macOS.

Step 4: Using the Metadata API for More Control

If you need to specify multiple icons or want to set them programmatically, you can use the metadata export in your layout. This is useful if you have different icons for different routes or want to add a maskable icon for Android.

Here's an example in app/layout.tsx:

import type { Metadata } from 'next';

export const metadata: Metadata = {
  icons: {
    apple: [
      { url: '/apple-icon.png', sizes: '180x180', type: 'image/png' },
    ],
  },
};

This approach gives you full control over the rel, sizes, and type attributes. You can also use it to add a maskable icon for Android PWAs, though that's a separate topic.

Common Pitfalls

Here are a few issues you might run into:

Conclusion

Setting up the Apple touch icon in Next.js is straightforward once you know the file-based convention. Drop a properly sized PNG in your app/ folder, and Next.js handles the rest. For more advanced scenarios, the metadata API gives you programmatic control.

If you need to generate the icon itself, try Mzu favicondl to create all the required sizes from your logo. And for a broader look at favicon setup in Next.js, check out our Next.js Favicon guide.

Check the documented requirements

Next.js documents favicons and app icons in its metadata file conventions.