---
id: task-12
title: Fix stale participant sessions showing on map
status: Done
assignee: []
created_date: '2025-12-19 18:00'
updated_date: '2026-01-02 14:29'
labels:
  - bug
  - ux
dependencies: []
priority: high
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
When opening rMaps, old participant sessions from previous visits are still showing on the map as "ghost" locations. This happens because:
1. Each session generates a new participantId via nanoid()
2. Old participants are persisted in localStorage
3. No cleanup of stale sessions occurs on reload

Fix: Clean up stale participants on room load and use a persistent participant ID per browser.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [x] #1 Old participant sessions are cleaned up on room load
- [x] #2 Same user keeps consistent participant ID across sessions
- [x] #3 No ghost duplicates appear on the map
- [x] #4 Build compiles successfully
<!-- AC:END -->

## Implementation Notes

<!-- SECTION:NOTES:BEGIN -->
## Implementation

1. **Added stale participant cleanup** (`src/lib/sync.ts:133-160`)
   - `cleanupStaleParticipants()` removes participants not seen in last hour
   - Runs automatically when loading room state from localStorage
   - Logs how many stale participants were removed

2. **Persistent participant ID** (`src/hooks/useRoom.ts:30-54`)
   - `getOrCreateParticipantId()` stores a consistent ID per room in localStorage
   - Same user returning to a room gets the same participant ID
   - Prevents creating duplicate ghost entries on each page reload
   - Falls back to temporary ID if localStorage unavailable

## Update (2026-01-02)

Added visual indicator for stale locations:
- Locations older than 5 minutes are greyed out (#6b7280) with 60% opacity
- Hover tooltip shows "[name] - last seen X min ago"
- Dynamically updates existing markers when they become stale
- Helps users distinguish fresh vs old location data
<!-- SECTION:NOTES:END -->
