Inspiration
I grew up walking under Model Town's canopy. The old, tree-lined sections are still noticeably cooler in June than the newly built plots down the road. Same city, same afternoon, different air. Everyone in Lahore feels this every summer. Temperatures now regularly cross 48°C, the city has repeatedly ranked the world's most polluted, and the tree cover keeps disappearing under new construction. But nobody has the local map that shows exactly where the gap is worst, or a ranked list of where planting a tree would actually help the most people.
Existing climate dashboards stop at "here is the problem." We wanted to build the next step: not just show the heat, but tell a planner, an NGO, or the EPA exactly where to plant, what to plant, and what it is worth.
What it does
Chhaon is a small-scale digital twin for five Lahore neighbourhoods: Model Town, Gulberg, DHA, Johar Town, and Iqbal Town. It:
- Measures the real heat cost of lost shade from free satellite imagery, cell by cell, at 60m resolution
- Ranks 600 planting sites (120 per region) by heat need, canopy absence, and population served
- Matches each site to a Lahore-native tree species by land use, drought tolerance, and water proximity, actively diversified so no single species dominates a street
- Classifies every cell into a Low / Medium / High / Critical heat-and-shade risk band
- Estimates the CO₂ and PM2.5 benefit of each recommended tree once mature, tying planting directly to Lahore's smog crisis
- Lets a user draw a box around any area (a ward, a corridor, a school block) and recompute the numbers for just that patch
- Exports ranked sites as CSV/GeoJSON and full measured layers as GeoJSON or a georeferenced image, so a department's own GIS team can pull the analysis into QGIS or ArcGIS
The core finding it is built on: bare ground in Model Town runs 3.2°C hotter at the surface than well-vegetated ground, in the same satellite pass. A correlation of −0.65 across 4,680 measured cells. That is a within-scene comparison, so it needs no multi-year trend to hold up.
How we built it
The pipeline pulls Sentinel-2 L2A imagery (via Element 84's Earth Search) for canopy/NDVI and Landsat 8/9 thermal data (via Microsoft Planetary Computer) for surface temperature, both read anonymously over HTTP with no API key and no Google Earth Engine account. OpenStreetMap (via Overpass) identifies genuinely plantable public land, and WorldPop 2020 gives population density. A Python pipeline (rasterio, pyproj, numpy) composites multiple scenes per year to reject cloud and haze, scores every plantable cell, and writes everything to static JSON committed into the repo.
The frontend is React, TypeScript, and Vite, with Zustand for state and MapLibre GL JS rendering the basemap, the interpolated data layers, and the ranked sites natively in one canvas. No deck.gl, no Kepler.gl, because MapLibre 5+ broke the API those libraries relied on.
The single most load-bearing engineering decision: everything is precomputed once and committed, so the live app makes zero runtime API calls. Nothing can time out during a demo.
Challenges we ran into
The vector basemap silently rendered blank in production. MapLibre 6 builds its worker's filename from a runtime ternary, which Vite cannot statically analyse, so the worker file was never emitted in the build. The browser requested it, got the SPA's index.html back instead, and the vector map just drew nothing. No console error, no failed request. Only the satellite (raster) basemap worked, because it never touches the worker. We fixed it with a small Vite plugin that copies the worker into assets/ under the exact name MapLibre expects, and added a script that checks a real production build for this failure mode going forward.
Our species recommendations were 91–100% one tree. The original matcher returned the first species in a list that cleared a land-use and width bar. Since roadside verges are 91–100% of every region's plantable land, and Neem needs only a 3m width (the lowest bar of any species), it won almost every site by default. Recommending the same tree for an entire neighbourhood is a real urban-forestry failure mode, because one pest sweep takes the whole avenue. We rebuilt it as a scored best-fit matcher (canopy delivered, drought/water fit against the site's own NDVI) with an explicit diversity term that actively caps any species below 40% share. Top-species share dropped to 37–45%.
We expected to find canopy loss. We did not. Model Town's vegetated share swings between 24% and 49% year to year across 2017–2025, tracking winter rainfall far more than construction. Rather than force a "the city is losing its trees" narrative the data does not support, we rebuilt the whole pitch around the number that does hold up under scrutiny: the within-scene heat gap.
NASA POWER could not tell our regions apart. Our original plan was to match species using live climate data per coordinate. NASA POWER's grid turned out to be ~50km, so Model Town, Gulberg, and DHA all return byte-identical temperature and wind. A climate-driven matcher would have recommended the same tree everywhere. We switched to matching on what actually varies site to site: land use, width, and water proximity.
Accomplishments that we're proud of
- A finding that survives a technical judge's first question, because we ask it ourselves first. The Method screen states our honest limits before anyone has to demand them
- Turning a real bug (species monocropping) into a stated design feature: an explicit anti-monoculture constraint
- A demo that cannot fail from a flaky network, because there is not one
- Tools built for the person who would actually act on this: a cost estimator, GIS exports, risk bands in the language a department already writes reports in
What we learned
Real satellite data is messier and more honest than a clean hackathon narrative wants it to be, and saying so, first, is what makes the parts that do hold up believable. We also learned that a "first match wins" algorithm can silently encode bias (our own monoculture bug) in a way that looks fine until someone actually counts the output.
What's next for Chhaon
Full coverage of all of Lahore, a live AQI overlay, green-corridor analysis, PDF report generation per site, a formal partnership with Punjab EPA and the Parks & Horticulture Authority to ground-truth our sites, and a rollout of the same city-agnostic pipeline to Karachi, Multan, and Peshawar.
Built With
- css
- geojson
- github
- landsat
- maplibre-gl-js
- node.js
- numpy
- openstreetmap
- python
- rasterio
- react
- sentinel-2
- shapely
- typescript
- vercel
- vite
- worldpop
- zustand

Log in or sign up for Devpost to join the conversation.