feat(hotspots): ingest live SiPongi hotspots with clustering and hover cards (Issue 3) #12
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/issue-3-sipongi-hotspots"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implements Issue 3: Live SiPongi active hotspots ingestion and clustering.
/api/hotspotsAPI route proxying KLHK SiPongi+ active fires with gzip decompression and 15-minute server caching (s-maxage=900).HotspotFeatureCollectionandHotspotPropertieswith normalized coordinates (5 decimal places), formatted timestamps (WIB and UTC), and confidence levels.<10: amber,10-50: orange,>50: red).getClusterExpansionZoom).HotspotHoverCard) displaying satellite, province, district, village, and timestamps.LayerToggles.Closes #3
Review: Issue 3 - Live SiPongi active hotspots ingestion and clustering
Verdict: APPROVE
Five-Axis Review Summary
1. Correctness
0x1f 0x8bheader detection) and JSON parsing work reliably. Coordinates correctly normalized to 5 decimal places and filtered to Indonesia bounds.getClusterExpansionZoomand smoothly zooms into constituent points.2. Readability & Simplicity
src/types/hotspot.ts.src/lib/services/sipongi.ts.hotspots-layer.tsx.3. Architecture
src/app/api/hotspots/route.tswith in-memory caching (15-minute TTL) and stale-while-revalidate fallback if upstream is unreachable.page.tsxcleanly propagates toMapViewwithout canvas recreation.4. Security & Hardening
latequery parameter validated and clamped (1–72 hours).AbortControllerprevents hanging serverless instances.5. Performance
X-Cache: HIT/MISS/STALEheaders.Considerations for Polish (Non-blocking)
In
src/components/map/layers/hotspots-layer.tsx:158,createRoot(popupNode)is called on every hotspotmouseenter. Onmouseleave,activePopup.remove()removes the DOM node, butroot.unmount()is not called. Reusing a persistent root or trackinglet activeRoot: Root | null = nullwithactiveRoot?.unmount()will prevent detached React root memory retention during rapid map hovering.In
src/components/map/popups/hotspot-hover-card.tsx:41, consider replacinganimate-pingwithmotion-safe:animate-pulseto respect user motion preferences.Ponytail Audit
node:zlib(gunzipSync) and existingmaplibre-gl.Verification
vp check: All 83 files formatted; 0 lint errors, 0 type errors.next build: Standalone production build succeeded in 9.3s with/api/hotspotsregistered.