Laravel Favicon Generator
Laravel has no icon convention of its own. Files in public/ are served at the site root, and the link tags belong in your Blade layout's head. Getting the web server's document root wrong is the most common reason a perfectly placed favicon.ico still 404s.
public/ is the web root
In a correctly configured Laravel app the web server's document root is the public/ directory, not the project root. That means public/favicon.ico is requested as /favicon.ico, and anything you put next to artisan is not URL-addressable at all.
The tags themselves live in the Blade layout most pages extend, typically resources/views/layouts/app.blade.php or the welcome view if you have not built a layout yet. Vite bundles CSS and JS; it does not invent favicon tags for you.
Where the files go
- my-laravel-app/
- public/document root
- favicon.icoadd
- favicon-32x32.pngadd
- apple-touch-icon.pngadd180x180
- icon-192.pngadd
- icon-512.pngadd
- site.webmanifestadd
- index.php
- resources/
- views/
- layouts/
- app.blade.phplink tags go here
- vite.config.js
Keep icons in public/ with stable names. Putting them under resources/ and hashing them with Vite is optional cache-busting, not the default path.
Blade layout head
{{-- resources/views/layouts/app.blade.php --}}
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ config('app.name') }}</title>
<link rel="icon" href="{{ asset('favicon.ico') }}" sizes="any">
<link rel="icon" type="image/png" sizes="32x32" href="{{ asset('favicon-32x32.png') }}">
<link rel="apple-touch-icon" href="{{ asset('apple-touch-icon.png') }}">
<link rel="manifest" href="{{ asset('site.webmanifest') }}">
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>asset() prefixes the configured asset URL, which matters when the app is not served from the domain root. Hardcoding /favicon.ico skips that.
public/ vs Vite-processed icons
| Approach | Use when | Trade-off |
|---|---|---|
| Files in public/ | Almost every app | Stable URLs; bust cache by renaming |
| Vite::asset(...) from resources/ | You already version images through Vite | Hashed filenames; more moving parts |
| No link tags, only public/favicon.ico | Quick local check | Misses PNG, apple-touch-icon, manifest |
Laravel favicon FAQ
Do I need to rebuild Vite after changing the favicon?
Not if the files live in public/ and you referenced them with asset(). Vite only needs a rebuild when the icons are part of its input graph via Vite::asset or an imported URL in CSS/JS.
The tab still shows the old Laravel icon.
Browsers cache favicons aggressively. Confirm the published HTML points at your file, then load the site in a private window. If you replaced public/favicon.ico in place, rename it (favicon-v2.ico) or hard-refresh once so the URL itself changes.
Where does the default favicon come from?
Laravel's skeleton ships a favicon.ico in public/. Replace that file and add the rest of the set beside it. Nothing in the framework regenerates it on deploy.