Vite Favicon Complete Guide

Master favicon setup in Vite: public folder configuration, PWA plugin, asset optimization, and best practices for lightning-fast builds.

Vite Favicon Quick Facts

  • Location: /public folder
  • Auto-served: At root URL
  • Hot Reload: Requires page refresh
  • Build: Copied to dist/
  • PWA: vite-plugin-pwa
  • Speed: Instant (no bundling)

Step 1: Public Folder Setup

File Structure

my-vite-app/
  public/               ? Place all favicons here
    favicon.ico
    favicon-16x16.png
    favicon-32x32.png
    favicon-96x96.png
    apple-touch-icon.png
    android-chrome-192x192.png
    android-chrome-512x512.png
    site.webmanifest
  src/
    main.js
    App.jsx
  index.html          ? Root level (not in public/)
  vite.config.js
  package.json
Important: Files in /public are served at root URL. /public/favicon.ico becomes https://yoursite.com/favicon.ico

Step 2: Update index.html

Root index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    
    <!-- Favicons -->
    <link rel="icon" type="image/x-icon" href="/favicon.ico" />
    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
    <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
    <link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png" />
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
    
    <!-- Android/Chrome -->
    <link rel="icon" type="image/png" sizes="192x192" href="/android-chrome-192x192.png" />
    <link rel="icon" type="image/png" sizes="512x512" href="/android-chrome-512x512.png" />
    
    <!-- Web App Manifest -->
    <link rel="manifest" href="/site.webmanifest" />
    
    <!-- Theme Color -->
    <meta name="theme-color" content="#646cff" />
    
    <title>Vite App</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>
Note: Use absolute paths starting with /. Don't use ./ or relative paths.

Step 3: Vite PWA Plugin (Optional)

Progressive Web App Support

1. Install Plugin

npm install -D vite-plugin-pwa

2. Configure vite.config.js

import { defineConfig } from 'vite'
import { VitePWA } from 'vite-plugin-pwa'
import react from '@vitejs/plugin-react' // or vue, svelte, etc.

export default defineConfig({
  plugins: [
    react(),
    VitePWA({
      registerType: 'autoUpdate',
      includeAssets: ['favicon.ico', 'apple-touch-icon.png'],
      manifest: {
        name: 'My Vite Application',
        short_name: 'Vite App',
        description: 'My awesome Vite application',
        theme_color: '#646cff',
        background_color: '#ffffff',
        display: 'standalone',
        icons: [
          {
            src: '/android-chrome-192x192.png',
            sizes: '192x192',
            type: 'image/png',
            purpose: 'any'
          },
          {
            src: '/android-chrome-512x512.png',
            sizes: '512x512',
            type: 'image/png',
            purpose: 'any'
          },
          {
            src: '/android-chrome-512x512.png',
            sizes: '512x512',
            type: 'image/png',
            purpose: 'maskable'
          }
        ]
      },
      workbox: {
        globPatterns: ['**/*.{js,css,html,ico,png,svg}']
      }
    })
  ]
})
Benefits: Automatic service worker, offline support, app manifest generation, and PWA optimization.

SVG Favicons & Dark Mode

Modern SVG Support

Add to index.html

<!-- SVG favicon with dark mode support -->
<link 
  rel="icon" 
  href="/favicon-light.svg" 
  type="image/svg+xml" 
  media="(prefers-color-scheme: light)" 
/>
<link 
  rel="icon" 
  href="/favicon-dark.svg" 
  type="image/svg+xml" 
  media="(prefers-color-scheme: dark)" 
/>

Example SVG (public/favicon.svg)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  <style>
    circle { fill: #646cff; }
    @media (prefers-color-scheme: dark) {
      circle { fill: #747bff; }
    }
  </style>
  <circle cx="16" cy="16" r="14"/>
</svg>

Build & Deploy

Production Build

Build Commands

# Development
npm run dev
# Favicons served from /public

# Production build
npm run build
# Files copied to dist/

# Preview production build
npm run preview
# Test at http://localhost:4173

Verify Build Output

  1. Check dist/ folder contains all favicon files
  2. Open dist/index.html and verify favicon links
  3. Run npm run preview and test
  4. Check browser DevTools ? Network tab

Deployment Platforms

  • Vercel: Zero-config, auto-detects Vite
  • Netlify: Build command: npm run build, Publish: dist
  • Cloudflare Pages: Native Vite support
  • GitHub Pages: Use gh-pages package

Vite Favicon Best Practices

? Best Practices

  • Place all favicons in /public
  • Use absolute paths (/favicon.ico)
  • Include manifest for PWA
  • Use vite-plugin-pwa for offline support
  • Provide multiple sizes and formats
  • Test production build before deploy
  • Use SVG for modern browsers
  • Configure theme-color meta tag

? Common Mistakes

  • Placing favicons in /src folder
  • Using relative paths (./favicon.ico)
  • Importing favicons in JS/TS files
  • Forgetting to test production build
  • Missing manifest.json/webmanifest
  • Not clearing browser cache
  • Wrong paths in production
  • Assuming dev = production behavior

Generate Vite-Ready Favicons

Create optimized favicon packages for Vite projects

Generate Favicons

Related Articles

An unhandled error has occurred. Reload 🗙