Sol — Product Requirements Document
An AI-powered urban heat vulnerability mapping platform for California, combining remote sensing data, machine learning, and real-time climate information.
Overview
Sol identifies neighborhoods across California that are most at risk from extreme heat events. It combines three satellite-derived features — NDVI (vegetation), LST (land surface temperature), and building footprint density — into a Random Forest model that outputs a normalized heat-vulnerability score for each 100 m grid cell statewide.
An interactive 3D DeckGL heatmap lets users explore vulnerability scores, overlay real-time weather and AQI data, simulate tree planting, review climate projections, and export priority zones for municipal use.
Problem Statement
- ▸489,000 annual heat deaths globally — rising each year due to climate change and urban heat island expansion.
- ▸Uneven distribution of green space — lower-income neighborhoods in California lack tree canopy, amplifying heat risk.
- ▸No unified decision tool — city planners lack a single interface that combines vulnerability scoring, live weather, and tree planting simulation.
- ▸Data siloed across agencies — NDVI, LST, SVI, and AQI data exist but are fragmented and inaccessible to non-experts.
Solution
Sol is a full-stack Next.js application that:
- 1Rasterizes Google Earth Engine exports (NDVI, LST, building footprints) into a uniform 100 m feature grid
- 2Trains a Random Forest model on those features, with weights optimized post-hoc by Gemini 2.5 Flash
- 3Serves the resulting vulnerability scores via a GeoJSON API to a DeckGL 3D heatmap
- 4Augments the map with live weather (Open-Meteo), AQI (EPA AirNow), Social Vulnerability Index, heat alerts, climate forecasts (2025–2035), and tree planting simulation
- 5Exports prioritized zones as CSV or GeoJSON for municipal use
Implemented Features
Architecture
Sol is a monolithic Next.js 15 application with App Router. All data processing, API routes, and frontend live in a single repo.
┌─────────────────────────────────────────────────────┐
│ Browser │
│ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ Landing Page │ │ 3D Visualization │ │
│ │ / │ │ /visualize │ │
│ │ /about │ │ │ │
│ │ /prd │ │ DeckGL HeatmapLayer │ │
│ └──────────────┘ │ Mapbox GL basemap │ │
│ │ Panels (Weather/SVI/AQI) │ │
│ └──────────────────────────┘ │
└───────────────┬─────────────────┬───────────────────┘
│ fetch │ fetch
┌───────▼───────┐ ┌──────▼──────────┐
│ Next.js API │ │ External APIs │
│ Routes │ │ │
│ /api/ndvi │ │ Open-Meteo │
│ /api/weather │ │ EPA AirNow │
│ /api/alerts │ │ CDC SVI │
│ /api/aqi │ │ Anthropic │
│ /api/forecast │ │ Google Gemini │
│ /api/svi │ └─────────────────┘
│ /api/explain │
│ /api/historical│
└───────┬────────┘
│
┌───────▼────────┐
│ Static Assets │
│ GeoJSON files │
│ (public/) │
│ vulnerability_ │
│ points.geojson │
│ tree_priority. │
│ geojson │
└─────────────────┘
Data Pipeline
The ML model and vulnerability scores are pre-computed offline. The pipeline runs in Python and produces GeoJSON files that are served as static assets.
Google Earth Engine
├─ Export NDVI raster (Landsat 8/9, California bbox)
└─ Export LST raster (Band 10 thermal, 30m → 100m resampled)
OpenStreetMap / Microsoft Building Footprints
└─ Rasterize building footprints → building density per 100m cell
generate_real_data.py
├─ Merge NDVI + LST + building density into feature matrix X
├─ Normalize all features to [0, 1]
└─ Output: samples.csv
model/train.py (Random Forest)
├─ Train on samples.csv (heat score = composite label)
├─ Evaluate: R²=0.87, MAE=0.13
└─ Output: model.pkl + vulnerability_points.geojson
tuneWeightsGemini.js (post-hoc weight tuning)
├─ Prompt: Gemini 2.5 Flash with feature importance context
├─ Response: {"w1": 0.6, "w2": 0.2, "w3": 0.2}
└─ Re-score: R²=0.91, MAE=0.09
compute_tree_priority_ca.py
└─ Output: tree_priority.geojson (top-N zones for planting)
API Reference
/api/ndviReturns vulnerability_points.geojson — pre-computed vulnerability scores with NDVI, building density, and LST attributes.
/api/weather?city=Los+AngelesProxies Open-Meteo current weather for the given city. Returns temperature, humidity, wind, precipitation.
/api/forecast?city=Los+Angeles7-day hourly forecast from Open-Meteo. Used by ForecastPanel chart.
/api/alerts?city=Los+AngelesAI-generated heat alert advisory for the city via Anthropic Claude API.
/api/aqi?lat=34&lon=-118EPA AirNow PM2.5 stations within ~100 km of the given coordinates.
/api/sviReturns CDC Social Vulnerability Index points filtered to California.
/api/historicalReturns historical heat-related event data for trend charts.
/api/explainBody: { ndvi, lst, buildingDensity, vulnerability }. Returns Claude-generated natural-language explanation of the point's risk factors.
ML Model
Feature weights after Gemini tuning:
{
"w1": 0.6, // Land Surface Temperature (LST) — dominant predictor
"w2": 0.2, // NDVI (vegetation) — inverse relationship with heat
"w3": 0.2 // Building Density — proxy for impervious surface
}
Heat Score = w1 * normalized_LST
+ (1 - NDVI) * w2
+ w3 * normalized_building_densityWeight Tuning Workflow
After initial training, tuneWeightsGemini.js sends model performance metrics and feature importances to Gemini 2.5 Flash with a structured prompt. Gemini returns a JSON object with optimized weights. The model is re-scored in-process, raising R² from 0.87 → 0.91 and reducing MAE from 0.13 → 0.09.
Roadmap
- ◦User accounts + saved zones (Supabase)
- ◦Share zone via URL (encoded state)
- ◦PWA / mobile layout for Visualizer
- ◦Expand coverage to all US states
- ◦Temporal animation (year-over-year change)
- ◦Integrate FEMA flood + wildfire risk layers
- ◦Real-time NDVI / LST via Sentinel Hub streaming
- ◦Municipal dashboard with KPI tracking
- ◦Public API for third-party integrations