Si has pegado etiquetas <link> de favicon directamente en app/root.tsx y has visto cómo Remix las deduplica o las descarta silenciosamente, el patrón correcto es el export links. Aquí es donde Remix v2 espera los descriptores de enlaces HTML, y el framework los renderiza en el head del documento por ti. (Consulta la documentación oficial de route links en Remix para ver la superficie completa de la API.)
Requisitos previos
Necesitas un proyecto de Remix v2 en funcionamiento y un conjunto de archivos de favicon. Para el set moderno completo, prepara:
/public/favicon.svg— fuente vectorial, soporta modo oscuro/public/favicon.ico— fallback legacy para navegadores antiguos/public/apple-touch-icon.png— 180×180 para la pantalla de inicio de iOS/public/site.webmanifest— para el comportamiento de instalación PWA
Todo lo que coloques en public/ se sirve desde la raíz del sitio, así que /public/favicon.svg se resuelve en https://yoursite.com/favicon.svg sin enrutamiento adicional.
Paso 1: Construye el export links en root.tsx
El export links es una función que devuelve un array de descriptores <link>. Remix mapea cada descriptor a una etiqueta HTML real en el head del documento. Usa LinksFunction desde @remix-run/node (o el paquete específico de tu runtime) para un tipado correcto.
import type { LinksFunction } from '@remix-run/node';
export const links: LinksFunction = () => [
{ rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' },
{ rel: 'alternate icon', href: '/favicon.ico', type: 'image/x-icon' },
];
Los valores de rel se mapean directamente a la especificación HTML — consulta la definición de rel=icon del whatwg para ver el vocabulario completo. Los navegadores eligen el primer icono que coincida con su contexto actual, así que lista tu SVG nítido antes del fallback ICO.
Paso 2: Añade las entradas de Apple Touch y manifest
Remix trata cada descriptor de la misma forma independientemente del tipo de recurso. Apílalos en el mismo array:
export const links: LinksFunction = () => [
{ rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' },
{ rel: 'alternate icon', href: '/favicon.ico', type: 'image/x-icon' },
{ rel: 'apple-touch-icon', href: '/apple-touch-icon.png', sizes: '180x180' },
{ rel: 'manifest', href: '/site.webmanifest' },
];
El atributo sizes es informativo — los navegadores lo consultan al elegir el mejor ajuste para un contexto de renderizado dado. Para patrones más amplios de etiquetas link de favicon más allá del export de Remix, consulta nuestros ejemplos de código HTML para favicon.
Paso 3: Publica SVGs de modo oscuro de forma limpia
Los navegadores sí respetan media en las etiquetas link de iconos. Puedes publicar dos SVGs y dejar que el navegador elija el correcto según el esquema de color del usuario. Guarda un segundo archivo como /public/favicon-dark.svg y luego añade ambos descriptores:
{
rel: 'icon',
href: '/favicon.svg',
type: 'image/svg+xml',
media: '(prefers-color-scheme: light)',
},
{
rel: 'icon',
href: '/favicon-dark.svg',
type: 'image/svg+xml',
media: '(prefers-color-scheme: dark)',
},
La especificación HTML soporta explícitamente descriptores media en los enlaces de iconos, así que este es un patrón de primera clase — no un hack. Para la configuración del lado del SVG que hace que estos archivos cambien correctamente, nuestra guía de favicon en modo oscuro explica la sintaxis de media query en detalle.
Paso 4: Rompe la caché cuando actualices los iconos
Los navegadores cachean favicon.ico de forma agresiva, y Remix no añade un content hash a los assets de public/ por defecto. Añade una cadena de versión cuando publiques un nuevo diseño:
{ rel: 'icon', href: '/favicon.svg?v=2', type: 'image/svg+xml' }
Incrementa el valor de v en cada release de iconos. Las cachés vinculadas a URLs se refrescarán y tus usuarios verán el nuevo gráfico en la pestaña de inmediato.
Errores comunes
Ten cuidado con esto cuando conectes iconos a través del export links de Remix:
- Poner las etiquetas en JSX crudo. Las etiquetas escritas dentro de
<head>enroot.tsxse renderizan, pero la deduplicación y el orden del SSR en Remix pueden descartarlas silenciosamente. El export es el camino documentado. - Olvidar
type. Sin una pista de MIME, Safari a veces elige el formato incorrecto.image/svg+xmlyimage/x-iconson valores seguros por defecto. - Usar
shortcut icon. Este atributo legacy no forma parte de la especificación HTML — los navegadores modernos lo ignoran. Usaalternate iconen su lugar. - Omitir el
reldel manifest. Las instalaciones PWA leen desdesite.webmanifest, no desde los enlaces de iconos. Haz referencia al mismo arraylinks. - Icono obsoleto tras el deploy. Las cachés del navegador sobreviven a los despliegues. Siempre rompe la caché en actualizaciones de iconos.
Cierre
El export links de Remix es el lugar más limpio para cablear las etiquetas HTML de favicon. Obtienes seguridad de tipos, salida SSR predecible y un único archivo que editar cuando actualices tu stack de iconos. Combínalo con una fuente vectorial nítida de Mzu favicondl, añade una query de cache-busting y tu app Remix lucirá profesional en cada pestaña del navegador.