v2.2.0 — Centralized Config & Live Map Interactivity
New Features
- Clickable nodes on live map — click any node marker to see a slide-in detail panel with name, role, status, location, stats, heard-by observers, recent packets, and links to full detail/analytics
- Observers as map markers — purple star markers on the map with computed locations from node data
- Centralized configuration (
roles.js) — single source of truth for role colors, labels, shapes, emoji, health thresholds, tile URLs, SNR/distance thresholds, and result limits. All overridable via config.json (#104) - Regions from API — new
/api/config/regionsendpoint, no more hardcoded region lists in frontend - CI validation gate —
scripts/validate.shruns syntax checks + undefined reference detection before every deploy
Bug Fixes
- Live map legend colors now match actual marker colors (were hardcoded and wrong)
- Observer locations — case-insensitive pubkey matching, direct join instead of packet iteration
- Spark bars — rewritten as inline
<span>elements, immune tomax-width:0table cell crush - escapeHtml() — handles numbers and non-strings without crashing (
String(s)before.replace()) esc is not defined— live.js now uses globalescapeHtml()instead of nonexistentesc()- MQTT topics — region-specific subscriptions (
meshcore/SJC/#) instead of wildcards, saves bandwidth - CI deploy workflow — config.json volume mount was missing, causing auth failures on auto-deploy
Infrastructure
- Added MRY (Monterey) to lincomatic MQTT topics
- Pre-deploy validation blocks broken JS from reaching production