NASA publishes fire data. Global Forest Watch tracks deforestation. OpenWeather knows the humidity. GBIF catalogs species. None of them talk to each other, and none of them work from a browser without a proxy. Terra turns five isolated data sources into one coherent geospatial dashboard.

The Problem Space

Public environmental APIs are powerful but fragmented. NASA FIRMS requires API keys and returns CSV. Global Forest Watch has its own authentication model. OpenWeather needs server-side key protection. GBIF uses different schemas. None support browser CORS directly. A researcher who wants a unified view of forest health has to build their own data aggregation layer.

Engineering the Solution

I built a Cloudflare Worker as the API gateway — it owns CORS handling, secret management, response caching, and data normalization for all five upstream APIs. The React frontend talks to one endpoint and gets unified data. The Worker handles the reality that public APIs fail unpredictably: it supports a "no-mock" strict mode for verification and a graceful fallback mode for demos. I chose Workers over a traditional server because the operational cost of a proxy should be near-zero.

A React 18 + Vite geospatial dashboard with Leaflet maps, Recharts analytics, and a Cloudflare Worker API layer. The Worker proxies NASA FIRMS fire alerts, Global Forest Watch deforestation data, OpenWeather conditions, GBIF biodiversity metadata, and NASA GIBS satellite imagery URLs. The frontend service layer implements a three-tier data strategy: prefer Worker, fallback to browser direct calls, then mock data. User-configurable API keys through localStorage enable stricter data modes.

Impact & Outcomes

Deployed at forest.nicx.me with the Worker handling cross-origin API aggregation. The dashboard presents fire alerts, deforestation signals, biodiversity data, weather context, and satellite imagery in a single interface. The configurable mock/live data toggle makes the project honest about data source availability.

Reflections & Takeaways

Key observations from building this system:

  • Public API aggregation is mostly error handling. The happy path is trivial — the real work is graceful degradation when three of five upstream services are down.
  • Cloudflare Workers are excellent API proxies but the caching model requires careful thought. Runtime cache is ephemeral, so expensive upstream calls need explicit cache headers.
  • Honest data labeling matters. Showing "generated data" when an API fails is more trustworthy than silently serving mock results.
In hindsight: I would separate the Worker into individual route modules instead of a single switch statement. The monolithic worker file got unwieldy as I added more API integrations.
Next iteration: Adding historical alert persistence through Durable Objects and building a notification system for fire alert thresholds.