Prerequisites
Problem Statement
On every page load, the node list stays empty until the full wantConfigId → config-complete handshake finishes (see packages/sdk/src/core/client/MeshClient.ts, configure()). On slow radio links (LongSlow presets, distant nodes over MQTT bridging) this takes a while, and the UI shows nothing to work with in the meantime.
Other client state is already persisted: messages via sqlocal (sdk-storage-sqlocal) and per-device data (traceroutes, waypoints, neighborInfo) via the zustand persist tree in apps/web/src/core/stores/deviceStore/index.ts (partialize). The node list itself is the only thing that always starts from zero.
Proposed Solution
Persist the NodesStore node data into the existing deviceStore persist tree (same IndexedDB storage mechanism merged in #536):
- On rehydrate, render the cached node list immediately, so users can browse nodes while the handshake runs.
- After the handshake completes, reconcile the cached entries with fresh device data (merge by node num, update
lastHeard, drop stale entries per current retention rules).
This would make reconnects feel instant and keep the node list useful across reloads. Scope-wise I'd keep it to the existing persist infrastructure — no new dependencies, no transport changes.
Current Alternatives
None today: a reload always requires waiting for the full handshake before the node list appears. (A previous, broader attempt at connection persistence was #645 — closed after the author stepped away, not because the direction was rejected.)
Importance
Nice to have
Additional Context
Happy to take this on. Opening this first to align on the preferred layer: should the persistence live in the apps/web deviceStore persist tree (smallest change, follows the #536 pattern), or should it be surfaced at the SDK layer (packages/sdk) so other consumers benefit? Any guidance from maintainers appreciated.
Prerequisites
Problem Statement
On every page load, the node list stays empty until the full
wantConfigId→ config-complete handshake finishes (seepackages/sdk/src/core/client/MeshClient.ts,configure()). On slow radio links (LongSlow presets, distant nodes over MQTT bridging) this takes a while, and the UI shows nothing to work with in the meantime.Other client state is already persisted: messages via sqlocal (
sdk-storage-sqlocal) and per-device data (traceroutes, waypoints, neighborInfo) via the zustand persist tree inapps/web/src/core/stores/deviceStore/index.ts(partialize). The node list itself is the only thing that always starts from zero.Proposed Solution
Persist the
NodesStorenode data into the existing deviceStore persist tree (same IndexedDB storage mechanism merged in #536):lastHeard, drop stale entries per current retention rules).This would make reconnects feel instant and keep the node list useful across reloads. Scope-wise I'd keep it to the existing persist infrastructure — no new dependencies, no transport changes.
Current Alternatives
None today: a reload always requires waiting for the full handshake before the node list appears. (A previous, broader attempt at connection persistence was #645 — closed after the author stepped away, not because the direction was rejected.)
Importance
Nice to have
Additional Context
Happy to take this on. Opening this first to align on the preferred layer: should the persistence live in the
apps/webdeviceStore persist tree (smallest change, follows the #536 pattern), or should it be surfaced at the SDK layer (packages/sdk) so other consumers benefit? Any guidance from maintainers appreciated.