Find your setup
| built with | files go in | tags go in |
|---|---|---|
| Vite | public/ | index.html |
| Next.js App Router | app/, renamed | generated by Next.js, see Next.js |
| React Router (framework mode) | public/ | the links export in app/root.tsx |
| Create React App | public/ | public/index.html |
Vite
Copy the files into public/ and put the snippet in the <head> of index.html. Full details, including why not to import icons from src/, are on the Vite page.
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="icon" href="/favicon-96x96.png" type="image/png" sizes="96x96">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/manifest.webmanifest">React Router
In framework mode, the root route renders the document and exposes a links function. Copy the files into public/ and return them from there:
// app/root.tsx
export const links = () => [
{ rel: 'icon', href: '/favicon.ico', sizes: '32x32' },
{ rel: 'icon', href: '/icon.svg', type: 'image/svg+xml' },
{ rel: 'icon', href: '/favicon-96x96.png', type: 'image/png', sizes: '96x96' },
{ rel: 'apple-touch-icon', href: '/apple-touch-icon.png' },
{ rel: 'manifest', href: '/manifest.webmanifest' },
]Create React App
Create React App is deprecated, but many projects still run on it. Copy the files into public/ and edit public/index.html, where paths use the %PUBLIC_URL% placeholder:
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" sizes="32x32">
<link rel="icon" href="%PUBLIC_URL%/icon.svg" type="image/svg+xml">
<link rel="icon" href="%PUBLIC_URL%/favicon-96x96.png" type="image/png" sizes="96x96">
<link rel="apple-touch-icon" href="%PUBLIC_URL%/apple-touch-icon.png">
<link rel="manifest" href="%PUBLIC_URL%/manifest.webmanifest">The CRA template ships its own manifest.json and logo192.png. Replace them with the generated manifest and icons, or update the existing manifest to point at the new files.
Changing the favicon at runtime
To show an unread count or progress in the tab from React state, use the dynamic favicon module: call favicon.badge(n) from an effect, and favicon.reset() in its cleanup.
Questions
Can I import the favicon in a React component?
No. Favicons belong in the HTML document head, served from fixed paths. Importing them through the bundler gives them hashed names.
How do I change the favicon per page in React?
Update the href of the icon <link> from an effect, or use the dynamic module for badges. Crawlers only see the static icon, so keep that one stable.
Which framework option should I pick in the editor?
Vite for Vite, React Router and most client-rendered apps. Next.js for Next. The files are the same; only the install notes change.