## 1. Batch resolveCollaborator (N+1 fix) - [x] 1.1 Lire `src/services/session-queries.ts` et identifier toutes les occurrences de `resolveCollaborator` appelées en boucle - [x] 1.2 Créer une fonction `batchResolveCollaborators(userIds: string[])` qui fait un seul `prisma.user.findMany({ where: { id: { in: userIds } } })` - [x] 1.3 Remplacer les boucles N+1 par collect des IDs → batch query → mapping en mémoire - [x] 1.4 Vérifier que les pages sessions/weather/etc. chargent correctement ## 2. Debounce router.refresh() dans useLive - [x] 2.1 Lire `src/hooks/useLive.ts` et localiser l'appel à `router.refresh()` - [x] 2.2 Ajouter un `useRef>` pour le timer de debounce - [x] 2.3 Wrapper l'appel `router.refresh()` avec `clearTimeout` + `setTimeout` à 300ms - [x] 2.4 Ajouter un `clearTimeout` dans le cleanup de l'effet pour éviter les leaks mémoire ## 3. Purge automatique des événements SSE - [x] 3.1 Lire `src/services/session-share-events.ts` et localiser `createEvent` et `cleanupOldEvents` - [x] 3.2 Ajouter un appel fire-and-forget à `cleanupOldEvents` à la fin de `createEvent` (après l'insert) - [x] 3.3 Wrapper l'appel dans un try/catch pour logger l'erreur sans bloquer ## 4. Ajout des loading.tsx sur les routes principales - [x] 4.1 Créer `src/app/sessions/loading.tsx` avec un skeleton de liste de sessions - [x] 4.2 Créer `src/app/weather/loading.tsx` avec un skeleton de tableau météo - [x] 4.3 Créer `src/app/users/loading.tsx` avec un skeleton de liste utilisateurs - [ ] 4.4 Vérifier que le skeleton s'affiche bien à la navigation (ralentir le réseau dans DevTools) ## 5. Lazy-load des modals avec next/dynamic - [x] 5.1 Identifier tous les composants qui importent `ShareModal` directement - [x] 5.2 Remplacer chaque import statique par `next/dynamic(() => import(...), { ssr: false })` - [ ] 5.3 Vérifier que les modals s'ouvrent correctement après lazy-load - [ ] 5.4 Vérifier dans les DevTools Network que le chunk modal n'est pas dans le bundle initial