Root cause: Zustand store resets to activeMap=null on every page load.
fetchMaps() only loaded the summary list — nodes were never reloaded
because the user had to manually re-select their map each time.
Fixes:
1. Persist last active map ID in localStorage (key: rackmapper:lastMapId)
- loadMap() saves the ID on successful load
- setActiveMap() saves/clears the ID
- deleteMap() clears the ID if the deleted map was active
2. Auto-restore on mount inside fetchMaps():
- If the saved map ID is still in the list, auto-load it
- If there is exactly one map, auto-load it as a convenience
3. Block spurious position saves during map load (blockSaveRef):
- fitView fires position NodeChanges for all nodes after load
- Without a guard these would overwrite stored positions with
React Flow's fitted coordinates immediately on every reload
- blockSaveRef is set true on activeMap change, cleared after 800ms
4. Tighten the position-change filter:
- Require dragging === false (strict equality, not just falsy)
- Require position != null before saving
- Both conditions must be true to queue a save
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Complete project scaffold with working auth, REST API, Prisma/SQLite
schema, Docker config, and React frontend for both Rack Planner and
Service Mapper modules. Both server and client pass TypeScript strict
mode with zero errors. Initial migration applied.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>