Dejaste tu favicon.svg en la carpeta public de Vite, pulsaste guardar y la pestaña del navegador sigue mostrando un cuadrado blanco en blanco. El build funciona, el archivo está ahí mismo y, aun así, el navegador no lo encuentra. Esto ocurre cuando se trata la carpeta public de Vite como cualquier otra carpeta estática y se pasa por alto una regla clave sobre cómo Vite sirve esos archivos.
La carpeta public es la vía de escape de Vite para los assets que necesitan URLs estables y sin hash. Los favicons son el caso de libro: la razón más habitual de confusión entre quienes empiezan con Vite.
Por qué los favicons van en la carpeta public de Vite
Vite aplica un hash a los assets importados desde src/ para invalidar caché (piensa en assets/logo-a3f9c2.svg). Genial para JS y CSS, pero pésimo para favicons. Los navegadores cachean los favicons de forma agresiva y los buscadores necesitan una URL predecible para mostrar tu icono en los resultados.
Los archivos en public/ se saltan el bundler por completo. Según la documentación oficial de Vite, todo lo que esté en este directorio se copia a la raíz del build y se sirve desde la raíz. Así, public/favicon.svg termina siendo /favicon.svg, no /public/favicon.svg. Solo el nombre del archivo, precedido por una barra.
Requisitos previos
- Un proyecto Vite funcional (ejecuta
npm create vite@latest) - Archivos de favicon listos en SVG, PNG o ICO
- Acceso al
index.htmlen la raíz del proyecto
Paso 1: coloca los archivos de favicon en public/
Coloca tus archivos de icono directamente en el directorio public/ en la raíz del proyecto. La mayoría de los scaffolds de Vite crean esta carpeta automáticamente.
my-vite-app/
├── public/
│ ├── favicon.svg
│ ├── favicon.ico
│ └── apple-touch-icon.png
├── src/
├── index.html
└── package.json
Usa nombres de archivo simples y convencionales. Los navegadores encuentran favicon.svg, favicon.ico y apple-touch-icon.png en la raíz sin configuración extra.
Paso 2: referencia los archivos con rutas relativas a la raíz
Abre index.html en la raíz del proyecto (no public/index.html: ese archivo no existe en Vite). Añade etiquetas link dentro del <head> usando rutas absolutas que empiecen por /. Es el único punto del proyecto Vite donde se hardcodean rutas de assets, porque la carpeta public se salta a propósito el resolver de imports.
<head>
<link rel='icon' type='image/svg+xml' href='/favicon.svg'>
<link rel='icon' type='image/x-icon' href='/favicon.ico'>
<link rel='apple-touch-icon' href='/apple-touch-icon.png'>
</head>
El estándar HTML define rel='icon' como la forma estándar de declarar favicons (WHATWG HTML Living Standard). Los navegadores eligen la mejor opción según los atributos type y sizes.
Paso 3: añade una variante para modo oscuro
Los navegadores modernos admiten un segundo SVG que se activa automáticamente en temas oscuros. Añade otra etiqueta link con una media query para que los usuarios vean el icono correcto cuando su sistema cambie a modo oscuro.
<link rel='icon' type='image/svg+xml' href='/favicon.svg' media='(prefers-color-scheme: light)'>
<link rel='icon' type='image/svg+xml' href='/favicon-dark.svg' media='(prefers-color-scheme: dark)'>
Si quieres profundizar en los favicons SVG para modo oscuro, consulta nuestra guía de favicon en modo oscuro.
Paso 4: comprueba el resultado del build
Ejecuta npm run build e inspecciona dist/. Tus archivos de favicon deberían aparecer en la raíz, sin que ningún bundler los haya tocado.
dist/
├── assets/
├── favicon.svg
├── favicon.ico
└── index.html
También puedes arrancar npm run preview y abrir la pestaña Network en DevTools. Deberías ver peticiones a favicon.svg, favicon.ico y apple-touch-icon.png devolviendo 200, no 404.
Errores habituales
La mayoría de problemas con favicons en Vite vienen de uno de estos errores. Si la pestaña aparece en blanco o muestra un icono genérico, repasa antes esta lista.
- Usar
/public/favicon.svgen tu HTML. El segmentopublic/solo existe en el código fuente. El navegador pide/favicon.svg. - Importar el favicon en
main.js. Esto genera una URL con hash y rompe la caché del navegador. Deja que la etiqueta link del HTML se encargue. - Poner los archivos en
src/assets/. Acaban procesados y renombrados. Los favicons necesitan rutas predecibles para la caché y el SEO. - Olvidar la etiqueta link por completo. Algunos navegadores piden automáticamente
/favicon.ico, pero Chrome y Firefox exigen cada vez más declaraciones explícitas para soportar SVG.
Cuando la carpeta public no basta
La carpeta public es el lugar adecuado para favicons estáticos que no cambian. Te ofrece URLs estables que los navegadores cachean de forma fiable y los buscadores pueden indexar. Si más adelante necesitas favicons dinámicos (badges de notificación, avatares de usuario, indicadores de estado en vivo), necesitarás JavaScript para cambiar el atributo href en tiempo de ejecución. Nuestra guía sobre favicon dinámico con JavaScript cubre ese patrón en detalle.
¿Necesitas ayuda para generar antes los archivos de icono correctos? Mzu favicondl produce variantes SVG, PNG, ICO y Apple Touch a partir de una única imagen de origen. Suéltalos en public/, añade tus etiquetas link y tu app Vite tendrá una presencia profesional en la pestaña en cuestión de minutos.