Files
collective-lists/plan/fase-2b-realtime-modo-compra.md
Oier Bravo Urtasun b297d253d9 fix(auth+pwa): resolve stuck-loading race condition and PWA build error
Auth: `getSession()` in a SvelteKit load function races with Supabase's async
localStorage init and can return null for a valid session, triggering a spurious
login() redirect. Moved auth redirect to (app)/+layout.svelte via $effect, which
correctly waits for onAuthStateChange to fire. Also fixed collective data never
loading on page refresh (INITIAL_SESSION event, not SIGNED_IN).

PWA: SvelteKit blocks Workbox imports in src/service-worker.ts, preventing
@vite-pwa/sveltekit from finding the compiled SW output. Switched to generateSW
strategy (plugin auto-generates the SW). Custom SW deferred to Fase 2b using
src/sw.ts (a filename SvelteKit does not intercept).

Docs: added gotchas 6–8 to CLAUDE.md covering both root causes so they are not
reintroduced. Updated plan/fase-2b with the sw.ts workaround note.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 21:44:14 +02:00

3.0 KiB
Raw Blame History

Fase 2b — Sincronización en Tiempo Real y Modo Compra

Duración estimada: 23 semanas
Objetivo: el diferencial del producto. Es la fase más compleja técnicamente.

2b.1 Sincronización Realtime

  • Suscripción a Postgres Changes de Supabase Realtime sobre items_compra filtrada por lista_id
  • Suscripción a Presence de Supabase Realtime para indicador de miembros presentes en lista
  • Store Svelte realtimeSync:
    • Gestiona el ciclo de vida de las suscripciones (subscribe/unsubscribe al entrar/salir de la lista)
    • Aplica cambios remotos al estado local sin causar bucles
    • Detecta conflicto last-write-wins: si el updated_at remoto > local, aplica remoto y muestra aviso visual

2b.2 Offline-First

  • Instalación y configuración de idb (wrapper de IndexedDB)
  • Esquema local en IndexedDB: pending_ops, listas_cache, items_cache
  • Cola de operaciones pendientes: cada mutación se escribe en pending_ops antes de llamar a Supabase
  • Service Worker (@vite-pwa/sveltekit + Workbox):
    • NOTA TÉCNICA: SvelteKit intercepta src/service-worker.ts y bloquea imports externos (solo permite $service-worker y $env/static/public). Para usar Workbox con injectManifest hay que nombrar el fichero src/sw.ts (SvelteKit no lo reconoce como SW) y configurar strategies: 'injectManifest', filename: 'sw.ts' en vite.config.ts. Actualmente el plugin usa generateSW (SW auto-generado, precaching básico).
    • Cache-first para assets estáticos
    • Network-first con fallback a caché para rutas de la app
    • Background sync para flush de pending_ops al recuperar conexión
    • Fallback manual online event (Safari no soporta Background Sync API)
  • Fallback manual de sync: al detectar online en el evento del navegador, flush de la cola (cubre Safari que no soporta Background Sync API)
  • Indicador de estado de sincronización en la UI: sincronizado | sincronizando | sin conexión

2b.3 Modo Compra

  • Ruta /listas/[id]/compra — UI dedicada al Modo Compra:
    • Ítems en formato grande (mínimo 64px de altura), optimizado para pulsar con el pulgar
    • Reordenamiento automático al marcar: pendientes arriba, marcados abajo (animación fluida con flip)
    • Indicador de presencia: avatares de miembros que tienen la lista abierta simultáneamente
    • Banner sin conexión cuando no hay red (los cambios se guardan en local)
    • Botón prominente "Finalizar compra" — confirmación modal → lista pasa a completada
    • Notificación push (si el usuario ha dado permiso) a otros miembros al finalizar
  • Rendimiento: 60fps en gama media, tap < 100ms (validar en Chrome DevTools con throttling)
  • Prueba de sincronización: dos dispositivos, misma lista, cambios visibles en < 1 segundo

Criterio de aceptación: dos personas en el mismo supermercado, con cobertura inestable, pueden marcar ítems desde sus móviles y verse los cambios mutuamente en tiempo real. Si se pierde la conexión, los cambios locales se sincronizan al recuperarla.