In the latest versions (app directory), you can simply add your favicon file in the app/
directory, just make sure to name the icon using the expected Next standard according to your icon type, from the doc:
File convention |
Supported file types |
Valid locations |
favicon |
.ico |
app/ |
icon |
.ico , .jpg , .jpeg , .png , .svg |
app/**/* |
apple-icon |
.jpg , .jpeg , .png |
app/**/* |
If your filve is an SVG icon, you can therefore simply put it in app/icon.svg
. You don't need to edit the metadata, and you certainly don't need to convert your file to a .ico
file.
The <link />
entry generated is something that looks like:
<link
rel="icon"
href="/icon.svg?9905c4fc24cc0f60"
type="image/svg+xml"
sizes="any"
>
Per path icon
According to this documentation, if you are using an image icon, you can even have a different icon in subpaths. For example, if you have a dashboard
subtree in your app:
You can have a diffrent favicon displayed for your users when they are in a dahboard page, you would simply need to have these files:
app/icon.svg
the icon for all your pages unless its redefined in a subtree
app/dashboard/icon.svg
the icon used in any page in the dashboard subtree (unless of course if its redefined in a sub-subtree)
Programmatically generate icons
You can even use a script to generate your icon, in that case the name conventions are:
File convention |
Supported file types |
Valid locations |
icon |
.js , .ts , .tsx |
app/**/* |
apple-icon |
.js , .ts , .tsx |
app/**/* |
In that case, you can use the dynamic route parameters to customize even further and have an icon that is built for a given path slug. For example, you could add the following icon in app/dashboard/[slug]/icon.tsx
to have a black circle with the first letter of your slug drawn:
import { ImageResponse } from "next/og";
export const size = {
width: 32,
height: 32,
};
export const contentType = "image/png";
export default function Icon({ params }: { params: { slug: string } }) {
return new ImageResponse(
(
<div
style={{
fontSize: 24,
background: "black",
width: "100%",
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "white",
backgroundColor: "black",
borderRadius: "100%",
textTransform: "capitalize",
}}
>
{params.slug[0]}
</div>
),
{
...size,
},
);
}
The <link />
entry generated is something that looks like:
<link
rel="icon"
href="/dashboard/cloud-computing/icon?f6e1d0bb0f362374"
type="image/png"
sizes="32x32"
>