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>
3.0 KiB
3.0 KiB
Fase 2b — Sincronización en Tiempo Real y Modo Compra
Duración estimada: 2–3 semanas
Objetivo: el diferencial del producto. Es la fase más compleja técnicamente.
2b.1 Sincronización Realtime
- Suscripción a
Postgres Changesde Supabase Realtime sobreitems_comprafiltrada porlista_id - Suscripción a
Presencede 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_atremoto > 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_opsantes de llamar a Supabase - Service Worker (
@vite-pwa/sveltekit+ Workbox):- NOTA TÉCNICA: SvelteKit intercepta
src/service-worker.tsy bloquea imports externos (solo permite$service-workery$env/static/public). Para usar Workbox coninjectManifesthay que nombrar el ficherosrc/sw.ts(SvelteKit no lo reconoce como SW) y configurarstrategies: 'injectManifest',filename: 'sw.ts'envite.config.ts. Actualmente el plugin usagenerateSW(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_opsal recuperar conexión - Fallback manual
onlineevent (Safari no soporta Background Sync API)
- NOTA TÉCNICA: SvelteKit intercepta
- Fallback manual de sync: al detectar
onlineen 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óncuando 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.