Live SiPongi active hotspots ingestion and clustering #3

Closed
opened 2026-10-14 18:24:06 +00:00 by yuris · 0 comments
Owner

What to build

Create a server-side API route (/api/hotspots) that fetches active hotspot points from the KLHK SiPongi+ GeoJSON API, filters by satellite and confidence level, and delivers a typed lightweight GeoJSON response. Render active hotspots on the MapLibre canvas with dynamic clustering and glowing confidence badges.

Technical specifications

  1. Target files:

    • src/app/api/hotspots/route.ts: Server-side proxy and normalization handler with caching.
    • src/types/hotspot.ts: Domain models and GeoJSON FeatureCollection TypeScript interfaces.
    • src/lib/services/sipongi.ts: Upstream HTTP fetcher with gzip decompression and timeout handling.
    • src/components/map/layers/hotspots-layer.tsx: Clustered and unclustered circle layers.
    • src/components/map/popups/hotspot-hover-card.tsx: Rich hover card for single hotspots.
  2. Upstream contract & caching:

    • Endpoint: https://opsroom.sipongidata.my.id/api/hotspot/filtergeojson
    • Parameters: wilayah=IN, filterperiode=false, late=24, satelit=NASA-SNPP,NASA-NOAA20,NASA-MODIS, confidence=high,medium,low.
    • Caching: Server-side cache with 15-minute TTL (Cache-Control: public, s-maxage=900, stale-while-revalidate=60).
    • Normalization: Coordinates rounded to 5 decimal places; timestamps converted to ISO UTC and formatted WIB strings.
  3. MapLibre clustering configuration:

    • Source: map.addSource("hotspots", { type: "geojson", data: "/api/hotspots", cluster: true, clusterMaxZoom: 14, clusterRadius: 45 }).
    • Cluster circles sized and colored by count:
      • < 10 hotspots: radius 18px, color #eab308 (amber-500)
      • 10 - 50 hotspots: radius 24px, color #f97316 (orange-500)
      • > 50 hotspots: radius 30px, color #dc2626 (red-600)
    • Unclustered points: glowing circle marker colored by confidence (high: #ef4444, medium: #f97316, low: #eab308) with 2px white stroke.
    • Cluster click: triggers camera zoom expansion into cluster bounds via getClusterExpansionZoom().

Acceptance criteria

  • GET /api/hotspots?late=24 returns a valid, typed GeoJSON FeatureCollection.
  • MapLibre renders hotspots using clustered circle layers with smooth cluster split animations.
  • Clicking a cluster smoothly zooms into the constituent points.
  • Hovering a single hotspot displays confidence, satellite source, and detected time in WIB and UTC.

Blocked by

  • Issue 1: Project scaffold, toolchain verification, and WebGL map baseline.

### What to build Create a server-side API route (`/api/hotspots`) that fetches active hotspot points from the KLHK SiPongi+ GeoJSON API, filters by satellite and confidence level, and delivers a typed lightweight GeoJSON response. Render active hotspots on the MapLibre canvas with dynamic clustering and glowing confidence badges. ### Technical specifications 1. **Target files**: - `src/app/api/hotspots/route.ts`: Server-side proxy and normalization handler with caching. - `src/types/hotspot.ts`: Domain models and GeoJSON FeatureCollection TypeScript interfaces. - `src/lib/services/sipongi.ts`: Upstream HTTP fetcher with gzip decompression and timeout handling. - `src/components/map/layers/hotspots-layer.tsx`: Clustered and unclustered circle layers. - `src/components/map/popups/hotspot-hover-card.tsx`: Rich hover card for single hotspots. 2. **Upstream contract & caching**: - Endpoint: `https://opsroom.sipongidata.my.id/api/hotspot/filtergeojson` - Parameters: `wilayah=IN`, `filterperiode=false`, `late=24`, `satelit=NASA-SNPP,NASA-NOAA20,NASA-MODIS`, `confidence=high,medium,low`. - Caching: Server-side cache with 15-minute TTL (`Cache-Control: public, s-maxage=900, stale-while-revalidate=60`). - Normalization: Coordinates rounded to 5 decimal places; timestamps converted to ISO UTC and formatted WIB strings. 3. **MapLibre clustering configuration**: - Source: `map.addSource("hotspots", { type: "geojson", data: "/api/hotspots", cluster: true, clusterMaxZoom: 14, clusterRadius: 45 })`. - Cluster circles sized and colored by count: - `< 10 hotspots`: radius `18px`, color `#eab308` (amber-500) - `10 - 50 hotspots`: radius `24px`, color `#f97316` (orange-500) - `> 50 hotspots`: radius `30px`, color `#dc2626` (red-600) - Unclustered points: glowing circle marker colored by confidence (`high`: `#ef4444`, `medium`: `#f97316`, `low`: `#eab308`) with 2px white stroke. - Cluster click: triggers camera zoom expansion into cluster bounds via `getClusterExpansionZoom()`. ### Acceptance criteria - [x] `GET /api/hotspots?late=24` returns a valid, typed GeoJSON FeatureCollection. - [x] MapLibre renders hotspots using clustered circle layers with smooth cluster split animations. - [x] Clicking a cluster smoothly zooms into the constituent points. - [x] Hovering a single hotspot displays confidence, satellite source, and detected time in WIB and UTC. ### Blocked by - Issue 1: Project scaffold, toolchain verification, and WebGL map baseline. ---
yuris closed this issue 2026-10-14 20:01:52 +00:00
yuris changed title from Issue 3: Live SiPongi active hotspots ingestion and clustering to Live SiPongi active hotspots ingestion and clustering 2026-10-14 22:31:31 +00:00
Sign in to join this conversation.
No labels
backend
frontend
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
yuris/titik-gambut-next#3
No description provided.