Svelte & SvelteKit Favicon Guide

Master favicon setup in Svelte: SvelteKit static directory, svelte:head component, app.html configuration, Vite setup, and optimization for modern reactive framework.

Svelte Favicon Setup

SvelteKit

Place in static/ folder

Vite/Svelte

Place in public/ folder

Custom Head

Use svelte:head

SvelteKit Setup (Recommended)

Static Directory Method

File Structure

my-sveltekit-app/
  static/
    favicon.ico           ? Place here
    favicon.png
    favicon-16x16.png
    favicon-32x32.png
    apple-touch-icon.png
    android-chrome-192x192.png
    android-chrome-512x512.png
    site.webmanifest
  src/
    routes/
      +layout.svelte
      +page.svelte
    app.html
  svelte.config.js

app.html Configuration

File: src/app.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    <!-- Favicons -->
    <link rel="icon" type="image/x-icon" href="%sveltekit.assets%/favicon.ico" />
    <link rel="icon" type="image/png" sizes="32x32" href="%sveltekit.assets%/favicon-32x32.png" />
    <link rel="icon" type="image/png" sizes="16x16" href="%sveltekit.assets%/favicon-16x16.png" />
    <link rel="apple-touch-icon" sizes="180x180" href="%sveltekit.assets%/apple-touch-icon.png" />
    <link rel="manifest" href="%sveltekit.assets%/site.webmanifest" />
    <meta name="theme-color" content="#ffffff" />
    
    %sveltekit.head%
  </head>
  <body data-sveltekit-preload-data="hover">
    <div style="display: contents">%sveltekit.body%</div>
  </body>
</html>
Note: %sveltekit.assets% automatically resolves to correct path, supporting adapter-specific deployments.

Dynamic Favicon with svelte:head

File: src/routes/+layout.svelte

<script>
  import { page } from '$app/stores';
  
  $: isDarkMode = $page.data.theme === 'dark';
</script>

<svelte:head>
  <link 
    rel="icon" 
    type="image/png" 
    href={isDarkMode ? '/favicon-dark.png' : '/favicon.png'} 
  />
</svelte:head>

<slot />

Vite + Svelte Setup

Non-SvelteKit Projects

File Structure

my-svelte-app/
  public/
    favicon.ico           ? Place here
    favicon-16x16.png
    favicon-32x32.png
    apple-touch-icon.png
  src/
    App.svelte
    main.js
  index.html
  vite.config.js

index.html Configuration

<!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="icon" type="image/png" sizes="512x512" href="/favicon-512x512.png" />
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
    
    <title>Svelte App</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

vite.config.js (Optional)

import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'

export default defineConfig({
  plugins: [svelte()],
  publicDir: 'public', // Default, ensures favicons are copied
  build: {
    assetsInlineLimit: 0, // Don't inline favicons
  },
})

Component-Based Favicon

Reusable Component

Create Favicon Component

File: src/lib/Favicon.svelte

<script>
  export let theme = 'light';
  export let basePath = '';
  
  $: faviconPath = theme === 'dark' 
    ? `${basePath}/favicon-dark.png` 
    : `${basePath}/favicon.png`;
</script>

<svelte:head>
  <link rel="icon" type="image/x-icon" href="{basePath}/favicon.ico" />
  <link 
    rel="icon" 
    type="image/png" 
    sizes="32x32" 
    href="{basePath}/favicon-32x32.png" 
  />
  <link 
    rel="icon" 
    type="image/png" 
    sizes="16x16" 
    href="{basePath}/favicon-16x16.png" 
  />
  <link 
    rel="apple-touch-icon" 
    sizes="180x180" 
    href="{basePath}/apple-touch-icon.png" 
  />
  <link rel="manifest" href="{basePath}/site.webmanifest" />
  
  {#if theme === 'dark'}
    <meta name="theme-color" content="#1a1a1a" />
  {:else}
    <meta name="theme-color" content="#ffffff" />
  {/if}
</svelte:head>

Use in Layout

File: src/routes/+layout.svelte

<script>
  import Favicon from '$lib/Favicon.svelte';
  import { writable } from 'svelte/store';
  
  const theme = writable('light');
  
  function toggleTheme() {
    theme.update(t => t === 'light' ? 'dark' : 'light');
  }
</script>

<Favicon theme={$theme} />

<button on:click={toggleTheme}>
  Toggle Theme
</button>

<slot />

Web App Manifest

PWA Configuration

site.webmanifest

File: static/site.webmanifest (SvelteKit) or public/site.webmanifest (Vite)

{
  "name": "My Svelte App",
  "short_name": "SvelteApp",
  "icons": [
    {
      "src": "/android-chrome-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/android-chrome-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "theme_color": "#FF3E00",
  "background_color": "#ffffff",
  "display": "standalone",
  "start_url": "/"
}

Svelte Favicon Best Practices

? Recommendations

  • Use static/ folder in SvelteKit
  • Use %sveltekit.assets% for paths
  • Place favicons in app.html for global use
  • Use svelte:head for dynamic favicons
  • Include web manifest for PWA support
  • Test with different adapters (node, static, vercel)
  • Optimize images before adding to project
  • Use stores for theme-based favicon switching

? Common Mistakes

  • Placing favicons in src/ instead of static/
  • Not using %sveltekit.assets% placeholder
  • Hardcoding paths (breaks with adapters)
  • Forgetting to add favicon to app.html
  • Not testing after build
  • Missing manifest file
  • Using public/ in SvelteKit (wrong directory)
  • Not clearing browser cache when testing

Deployment Considerations

Adapter-Specific Notes

@sveltejs/adapter-static

  • Static files copied to build output
  • Deploy entire build/ folder
  • Favicons accessible at root level

@sveltejs/adapter-vercel

  • Static assets automatically served via CDN
  • Cache headers optimized automatically
  • No additional configuration needed

@sveltejs/adapter-node

  • Static files served by Node.js server
  • Configure cache headers in server if needed
  • Assets available at / path

Generate Svelte-Ready Favicons

Create optimized favicon packages for SvelteKit and Vite projects

Generate Favicons

Related Articles

An unhandled error has occurred. Reload 🗙