All platforms

Favicon for Vite

How to add a favicon in Vite

To add a favicon in a Vite project (any framework or none), place your icon files in the public folder and reference them with <link> tags in index.html at the project root. Vite copies public/ to the build output root verbatim and does not hash those files, so /favicon.ico resolves predictably.

What you need

  • favicon.ico plus PNG favicons (16/32), a 180x180 apple-touch-icon, and android-chrome 192/512.
  • The public folder at your project root (served from / in dev and copied to dist/ in build).
  • A site.webmanifest for Android/PWA and maskable icons, linked from index.html.

Step-by-step: add a favicon in Vite

  1. Generate the icon set. Use Logo2Favicon to produce favicon.ico, the PNG sizes, the Apple touch icon, the PWA icons, a maskable icon, and the manifest - all in your browser, nothing uploaded.
  2. Add files to public/. Copy favicon.ico, favicon-32x32.png, apple-touch-icon.png, and site.webmanifest into the public folder. Vite copies these to dist/ at the root, untouched and unhashed.
  3. Link them in index.html. Open index.html at the project root (the entry HTML Vite processes) and add the icon, apple-touch-icon, and manifest link tags inside <head> with root-absolute paths.
  4. Build and check. Run npm run build then npm run preview, and verify the tab icon plus that /favicon.ico and /site.webmanifest return 200.
Add to index.html <head> (project root, processed by Vite):
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="manifest" href="/site.webmanifest">

Common mistakes to avoid

  • Importing icons from src/ - Vite hashes bundled assets, so the URL changes and /favicon.ico 404s. Use public/ instead.
  • Setting a non-default base in vite.config and then using root-absolute /favicon.ico, which breaks on subpath deploys; reference via the base or import.meta.env.BASE_URL.
  • Editing the wrong index.html (a copy in dist/) instead of the source one at the project root.
  • Assuming public/ files are cache-busted; they are not hashed, so update the filename or hard-refresh to dodge stale caches.
Free forever, no sign-up

Generate a complete icon set for Vite

One logo in, every file out: favicon.ico, the PNG sizes, the Apple touch icon, Android and PWA icons, a maskable icon, the web manifest, and a copy-paste snippet ready for Vite. Free, private, and generated in your browser.

Open the generator

Frequently asked questions

Where do I put the favicon in a Vite project?
In the public folder at your project root. Vite copies public/ to the build output root without renaming, so files like favicon.ico and site.webmanifest are served from / and referenced from index.html.
Are files in Vite's public folder hashed?
No. Vite copies public/ verbatim, so the filenames stay the same and are not cache-busted. That is why a root favicon belongs there, but it also means you should hard-refresh or rename to bypass browser caching.
Why does /favicon.ico break when I set a Vite base path?
A root-absolute /favicon.ico ignores the configured base. On a subpath deploy, reference assets through import.meta.env.BASE_URL or a relative path so they resolve under the base instead of the domain root.
Should I import the favicon or put it in public/?
Put it in public/. Importing an icon from src/ runs it through Vite's bundler, which hashes the output filename - fine for in-app images, but it breaks the predictable /favicon.ico URL browsers and tools expect.

Favicon guides for other platforms

New to favicons? Read the complete favicon guide and the icon size cheatsheet, or jump straight to the favicon generator.