¿Te ha pasado que instalas una PWA en tu móvil y, al ver el icono en la pantalla de inicio, parece un borrón pixelado de los años 90? Seguramente el problema no es tu diseño, sino que tus site webmanifest icon sizes están mal configurados. Android no se limita a reducir tu imagen más grande; la recorta, la escala y le aplica máscaras de forma agresiva según lo que declares en tu manifest.json.

Lo sufrí en mis propias carnes hace poco. Tenía una app que se veía nítida en mi Pixel, pero en un Samsung de un colega el icono aparecía minúsculo y descentrado. El problema no era la calidad del archivo, sino la configuración del manifest.

Si necesitas repasar los conceptos básicos del manifest, échale un ojo a nuestra guía de favicon site.webmanifest para developers. Aquí vamos a ir directo al grano: al array de iconos y las dimensiones exactas que deves declarar.

Requisitos previos

Vas a necesitar una imagen de alta resolución (como mínimo 512x512 píxeles) y tu editor de código favorito. Si no tienes un archivo fuente a mano, pásate por Mzu favicondl y genera uno a partir de un logo o imagen existente.

Paso a paso: configurando los iconos del manifest

Vamos a montar un array de icons a prueba de balas. Nos centraremos en las tres entradas que de verdad importan para el soporte moderno de PWA en Android.

1. El PNG estándar de 192x192

Esta es tu línea base. Android utiliza este tamaño para el icono del launcher en la mayoría de pantallas estándar. Debes declararlo explícitamente, sin excepciones.

No te fíes del navegador para que reduzca tu imagen de 512x512. El motor de renderizado de Android a veces aplica una interpolación rara al escalar hacia abajo, dejando tu icono con un aspecto borroso. Proporciona un PNG de 192x192 dedicado.

2. El PNG de alta resolución de 512x512

Este es el icono del splash screen. Cuando tu PWA arranca, Android muestra esta imagen sobre un fondo blanco mientras el service worker carga. Si solo declaras un icono en tu manifest, que sea este ( aunque te recomiendo no conformarte con uno solo).

3. El icono Maskable (Crucial)

Android 13+ y las versiones modernas de Chrome OS usan iconos adaptativos. Si no declaras un icono maskable, el sistema operativo mete tu icono estándar dentro de un círculo blanco. El resultado es de lo más cutre.

Los iconos maskable requieren una 'safe zone' en el centro. Tienes que añadir padding a tu diseño para que el sistema operativo pueda recortarlo en cualquier forma (círculo, squircle, cuadrado redondeado) sin cortar tu logo. Explicamos el lado del diseño en nuestra guía de iconos maskable.

El código completo

Aquí tienes el array de icons exacto que deberías pegar en tu manifest.json ahora mismo:

{
  "name": "My Awesome App",
  "icons": [
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "/icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "/icons/icon-maskable-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ]
}

Fíjate en el campo purpose. Esto le dice al sistema operativo exactamente cómo debe usar el archivo. Si lo omites, el navegador asume any, lo que significa que tu icono maskable podría usarse como icono estándar y verse con un padding raro.

Errores comunes

Incluso con el código correcto, las cosas se pueden romper. Aquí van los fallos que veo más a menudo.

Usar un único icono 'any maskable'

Algunos developers intentan ahorrar bytes declarando un solo icono con "purpose": "any maskable". No hagas esto. Un icono maskable lleva padding integrado. Si el navegador usa ese mismo archivo para una petición estándar any, tu icono se verá diminuto dentro del launcher. Siempre sepáralos en archivos distintos.

Olvidar la Safe Zone

Diseñaste un icono precioso de 512x512. Lo subes como maskable. El sistema operativo lo recorta en un círculo y la mitad de tu logo desaparece. Debes mantener tu artwork dentro del 80% central del canvas (la safe zone) para iconos maskable.

Atributo sizes que no coincide

Si tu archivo realmente tiene 512x512 píxeles pero en el manifest escribes "sizes": "192x192", Android se hace un lío. El sistema operativo se fía más de lo que declaras en el manifest que de las dimensiones reales del archivo. Verifica siempre que las dimensiones de tu imagen coinciden con el string.

Lo que hacen los pros

Fíjate en cómo gestiona GitHub su PWA. No incluyen 15 tamaños distintos de PNG. Solo envían el de 192 y 512 estándar, más una versión maskable dedicada. Ese es el estándar moderno. Puedes comprobarlo tú mismo abriendo DevTools y revisando su manifest.

Si quieres inspeccionar cómo otras webs gestionan sus iconos, usa Mzu favicondl para descargar y analizar sus configuraciones de manifest. Te ahorra tener que rastrear el HTML minificado.

En resumen

Deja de generar decenas de archivos de iconos. Solo necesitas tres entradas en tu array de site webmanifest icon sizes: 192x192, 512x512 y una versión maskable de 512x512. Mantén tu código limpio, respeta la safe zone y tu PWA se verá nativa en cualquier dispositivo.