PWA y push notifications
CÉNIT es una PWA instalable: el staff y los jugadores pueden agregarla a la pantalla de inicio en iOS, Android o Chrome desktop. El service worker maneja navegación offline básica y entrega push notifications del staff al jugador (mensajería interna, alertas). Toda la infraestructura es propia — no usa FCM ni APNs directos, sino Web Push estándar con claves VAPID.
Cómo lo usa el staff
Sección titulada «Cómo lo usa el staff»Instalación
Sección titulada «Instalación»- iOS: el jugador (o staff) abre
cenitams.comen Safari, “Compartir → Añadir a pantalla de inicio”. - Android / Chrome desktop: aparece un prompt nativo de instalación.
El hook
usePwaInstall(components/pwa/use-pwa-install.ts) detecta el eventobeforeinstallprompty expone un botón. - Una vez instalada, abre en modo
standalone(sin barra de navegador), con start URL/dashboardpara staff (configurable enapp/manifest.ts).
Push notifications — staff → jugador
Sección titulada «Push notifications — staff → jugador»- Suscripción: el jugador, desde
/player, toca “Activar notificaciones”. El componentepush-subscribe-button.tsxsolicita permiso, registra el endpoint y lo guarda en la tablapush_subscriptionsvíaPOST /api/push/subscribe. - Envío: cada vez que el staff manda un mensaje al jugador desde
staff-message-thread.tsx,sendStaffMessagedisparaPOST /api/push/send. La libreríaweb-pushfirma el payload con VAPID y lo entrega al endpoint del navegador del jugador. - El staff no decide manualmente cuándo notificar — es automático al enviar el mensaje. No hay broadcast masivo.
Configuración relacionada
Sección titulada «Configuración relacionada»- Variables de entorno requeridas en Workers Secrets:
NEXT_PUBLIC_VAPID_PUBLIC_KEY,VAPID_PRIVATE_KEY,VAPID_SUBJECT. - Si faltan, la suscripción y el envío fallan silenciosamente — revisar logs en Cloudflare Workers.
Cómo lo ve el jugador
Sección titulada «Cómo lo ve el jugador»El jugador instala la app desde su navegador. Después de habilitar
notificaciones, cada mensaje del staff llega como notificación
nativa del sistema operativo, con vibración corta ([100, 50, 100]) y
el ícono de CÉNIT. Tocar la notificación abre /player/mensajes
directamente — si la app ya está abierta, simplemente trae la ventana
al frente.
Datos y métricas
Sección titulada «Datos y métricas»Tablas DB
Sección titulada «Tablas DB»push_subscriptions(endpoint, p256dh, auth_key, user_id) — una entrada por dispositivo del jugador. No hay TTL — endpoints inválidos quedan hasta queweb-pushretorne 410 y el handler los borre.
Service worker — estrategias de caché
Sección titulada «Service worker — estrategias de caché»public/sw.js registra tres estrategias:
- Cache-first para assets inmutables (
/_next/static/, imágenes, fonts). Sirve sin red si ya están en caché. - Stale-while-revalidate para navegaciones (
request.mode === 'navigate'): sirve la versión cacheada y refresca en background. Si no hay caché y la red falla, redirige a/offline. - Network-first para todo lo demás (data fetches): si la red falla, intenta caché; si tampoco, 503.
Rutas autenticadas (/dashboard, /player, /superadmin, /admin,
/api/) están en NO_CACHE_PATHS — siempre network-only, nunca
cachean respuestas con datos sensibles.
Integraciones
Sección titulada «Integraciones»- Mensajería interna (
/player/mensajes,staff-message-thread.tsx) — dispara push automáticamente. - Cloudflare Workers — runtime para
web-push. El SW se sirve desde/public/sw.jscon scope/.
Limitaciones / roadmap
Sección titulada «Limitaciones / roadmap»- No hay broadcast a todo el plantel desde la UI — un mensaje, una notificación.
- iOS Safari soporta Web Push desde iOS 16.4, pero requiere que la PWA esté instalada en pantalla de inicio. En navegador normal no recibe push.
- Background sync (
syncevent con tagsend-messages) está registrado en el SW pero los clients flushean su propia cola IDB — no hay queue persistente del lado del SW. - No hay UI para que el jugador desuscriba un dispositivo específico — desactivar requiere bloquear notificaciones en el navegador.