# adamweaver/chlorosat architecture

> Architecture diagram of the GitHub repository adamweaver/chlorosat, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-10-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/adamweaver/chlorosat
- Repository: https://github.com/adamweaver/chlorosat

## Overview

Chlorosat’s live product is a static website where visitors open an interactive globe, choose a year and map view, adjust vegetation display, and search for places. In the browser, the globe engine obtains and styles map data from public services; search uses Photon. The repository also contains a separate, experimental offline Python pipeline for processing satellite bands into map outputs, explicitly not used by the live site. Pipeline connections are limited to those visible in the sampled source; README-documented live-site behavior is distinguished from implementation details not shown.

Main entry points: [`web/src/components/map/MapApp.js`](https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/MapApp.js) (Map interface), [`web/src/lib/map/chlorosatGlobeEngine.js`](https://github.com/adamweaver/chlorosat/blob/main/web/src/lib/map/chlorosatGlobeEngine.js) (Globe engine), [`pipeline/src/chlorosat/process.py`](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/process.py) (Raster processing), [`pipeline/src/chlorosat/export.py`](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/export.py) (PNG and manifest export)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_site["Website"]
  node_home["Home page<br/>[page.js]"]
  node_header["Site navigation<br/>[Header.js]"]
  node_mapentry["Map page<br/>[page.js]"]
  node_about["About page<br/>[page.js]"]
end

subgraph group_globe["Globe and controls"]
  node_persistent["Persistent map<br/>[PersistentMap.js]"]
  node_mapapp["Map interface<br/>[MapApp.js]"]
  node_engine["Globe engine"]
  node_year["Year selector<br/>[YearSelector.js]"]
  node_opacity["Vegetation controls<br/>[OpacitySlider.js]"]
  node_basemap["Basemap toggle<br/>[BaseMapToggle.js]"]
  node_sidecontrols["Navigation controls<br/>[SideControls.js]"]
  node_legend["Vegetation legend<br/>[Legend.js]"]
  node_search["Place search<br/>[SearchBar.js]"]
  node_hover["Panel interaction<br/>[useHoverExpand.js]"]
  node_geocode["Geocoding client<br/>[geocode.js]"]
  node_colors["Vegetation colors<br/>[heatColors.js]"]
  node_labels["Reference labels<br/>[referenceLabels.js]"]
end

subgraph group_services["Browser data sources"]
  node_nasa["NASA GIBS"]
  node_esri["Esri imagery"]
  node_openfreemap["OpenFreeMap tiles"]
  node_photon["Photon search"]
  node_browser[("Browser cache")]
end

subgraph group_pipeline["Offline pipeline"]
  node_cli["Pipeline CLI<br/>[cli.py]"]
  node_fetch["Band acquisition<br/>[fetch.py]"]
  node_config["Region configuration<br/>[config.py]"]
  node_process["Raster processing<br/>[process.py]"]
  node_ndvi["NDVI calculation<br/>[ndvi.py]"]
  node_methods["Method definitions<br/>[methods.py]"]
  node_visible["Visible-light method<br/>[visible.py]"]
  node_composite["Compositing<br/>[composite.py]"]
  node_stats["Regional statistics<br/>[stats.py]"]
  node_render["Raster rendering<br/>[render.py]"]
  node_export["PNG and manifest export<br/>[export.py]"]
end

node_visitor(("Visitor"))

node_visitor -->|"opens"| node_home
node_visitor -->|"opens"| node_mapentry
node_visitor -->|"opens"| node_about
node_home -.->|"shows navigation"| node_header
node_mapentry -.->|"displays map"| node_persistent
node_persistent -->|"hosts"| node_mapapp
node_mapapp -->|"creates engine"| node_engine
node_mapapp -->|"renders"| node_year
node_mapapp -->|"renders"| node_opacity
node_mapapp -->|"renders"| node_basemap
node_mapapp -->|"renders"| node_sidecontrols
node_mapapp -->|"renders"| node_legend
node_mapapp -->|"renders"| node_search
node_search -->|"searches places"| node_geocode
node_geocode -->|"queries"| node_photon
node_year -->|"uses panel logic"| node_hover
node_opacity -->|"uses panel logic"| node_hover
node_basemap -->|"uses panel logic"| node_hover
node_engine -->|"fetches NDVI tiles"| node_nasa
node_engine -->|"fetches water mask"| node_nasa
node_engine -->|"fetches imagery"| node_esri
node_engine -->|"loads map tiles"| node_openfreemap
node_engine -->|"caches raw tiles"| node_browser
node_engine -->|"uses colors"| node_colors
node_engine -->|"uses labels"| node_labels
node_cli -->|"invokes"| node_process
node_process -->|"reads regions"| node_config
node_process -->|"computes NDVI"| node_ndvi
node_process -->|"uses classes"| node_methods
node_process -->|"reprojects and colors"| node_render
node_process -->|"writes outputs"| node_export
node_export -->|"records methods"| node_methods
node_export -->|"saves PNG"| node_render

click node_home "https://github.com/adamweaver/chlorosat/blob/main/web/src/app/page.js"
click node_header "https://github.com/adamweaver/chlorosat/blob/main/web/src/components/Header.js"
click node_mapentry "https://github.com/adamweaver/chlorosat/blob/main/web/src/app/map/page.js"
click node_about "https://github.com/adamweaver/chlorosat/blob/main/web/src/app/about/page.js"
click node_persistent "https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/PersistentMap.js"
click node_mapapp "https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/MapApp.js"
click node_engine "https://github.com/adamweaver/chlorosat/blob/main/web/src/lib/map/chlorosatGlobeEngine.js"
click node_year "https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/YearSelector.js"
click node_opacity "https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/OpacitySlider.js"
click node_basemap "https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/BaseMapToggle.js"
click node_sidecontrols "https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/SideControls.js"
click node_legend "https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/Legend.js"
click node_search "https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/SearchBar.js"
click node_hover "https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/useHoverExpand.js"
click node_geocode "https://github.com/adamweaver/chlorosat/blob/main/web/src/lib/map/geocode.js"
click node_colors "https://github.com/adamweaver/chlorosat/blob/main/web/src/lib/map/heatColors.js"
click node_labels "https://github.com/adamweaver/chlorosat/blob/main/web/src/lib/map/referenceLabels.js"
click node_cli "https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/cli.py"
click node_fetch "https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/fetch.py"
click node_config "https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/config.py"
click node_process "https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/process.py"
click node_ndvi "https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/ndvi.py"
click node_methods "https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/methods.py"
click node_visible "https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/visible.py"
click node_composite "https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/composite.py"
click node_stats "https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/stats.py"
click node_render "https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/render.py"
click node_export "https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/export.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_home,node_header,node_mapentry,node_about toneBlue
class node_persistent,node_mapapp,node_engine,node_year,node_opacity,node_basemap,node_sidecontrols,node_legend,node_search,node_hover,node_geocode,node_colors,node_labels toneAmber
class node_nasa,node_esri,node_openfreemap,node_photon,node_browser toneMint
class node_cli,node_fetch,node_config,node_process,node_ndvi,node_methods,node_visible,node_composite,node_stats,node_render,node_export toneRose
class node_visitor toneIndigo
```

## Components

### Website

- [Home page](https://github.com/adamweaver/chlorosat/blob/main/web/src/app/page.js): `web/src/app/page.js`
- [Site navigation](https://github.com/adamweaver/chlorosat/blob/main/web/src/components/Header.js): `web/src/components/Header.js`
- [Map page](https://github.com/adamweaver/chlorosat/blob/main/web/src/app/map/page.js): `web/src/app/map/page.js`
- [About page](https://github.com/adamweaver/chlorosat/blob/main/web/src/app/about/page.js): `web/src/app/about/page.js`

### Globe and controls

- [Persistent map](https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/PersistentMap.js): `web/src/components/map/PersistentMap.js`
- [Map interface](https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/MapApp.js): `web/src/components/map/MapApp.js`
- [Globe engine](https://github.com/adamweaver/chlorosat/blob/main/web/src/lib/map/chlorosatGlobeEngine.js): `web/src/lib/map/chlorosatGlobeEngine.js`
- [Year selector](https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/YearSelector.js): `web/src/components/map/controls/YearSelector.js`
- [Vegetation controls](https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/OpacitySlider.js): `web/src/components/map/controls/OpacitySlider.js`
- [Basemap toggle](https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/BaseMapToggle.js): `web/src/components/map/controls/BaseMapToggle.js`
- [Navigation controls](https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/SideControls.js): `web/src/components/map/controls/SideControls.js`
- [Vegetation legend](https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/Legend.js): `web/src/components/map/controls/Legend.js`
- [Place search](https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/SearchBar.js): `web/src/components/map/controls/SearchBar.js`
- [Panel interaction](https://github.com/adamweaver/chlorosat/blob/main/web/src/components/map/controls/useHoverExpand.js): `web/src/components/map/controls/useHoverExpand.js`
- [Geocoding client](https://github.com/adamweaver/chlorosat/blob/main/web/src/lib/map/geocode.js): `web/src/lib/map/geocode.js`
- [Vegetation colors](https://github.com/adamweaver/chlorosat/blob/main/web/src/lib/map/heatColors.js): `web/src/lib/map/heatColors.js`
- [Reference labels](https://github.com/adamweaver/chlorosat/blob/main/web/src/lib/map/referenceLabels.js): `web/src/lib/map/referenceLabels.js`

### Browser data sources

- **NASA GIBS**
- **Esri imagery**
- **OpenFreeMap tiles**
- **Photon search**
- **Browser cache**

### Offline pipeline

- [Pipeline CLI](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/cli.py): `pipeline/src/chlorosat/cli.py`
- [Band acquisition](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/fetch.py): `pipeline/src/chlorosat/fetch.py`
- [Region configuration](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/config.py): `pipeline/src/chlorosat/config.py`
- [Raster processing](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/process.py): `pipeline/src/chlorosat/process.py`
- [NDVI calculation](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/ndvi.py): `pipeline/src/chlorosat/ndvi.py`
- [Method definitions](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/methods.py): `pipeline/src/chlorosat/methods.py`
- [Visible-light method](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/visible.py): `pipeline/src/chlorosat/visible.py`
- [Compositing](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/composite.py): `pipeline/src/chlorosat/composite.py`
- [Regional statistics](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/stats.py): `pipeline/src/chlorosat/stats.py`
- [Raster rendering](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/render.py): `pipeline/src/chlorosat/render.py`
- [PNG and manifest export](https://github.com/adamweaver/chlorosat/blob/main/pipeline/src/chlorosat/export.py): `pipeline/src/chlorosat/export.py`

### Other components

- **Visitor**

## Connections

- Visitor → Home page: opens (evidence: `README.md`)
- Visitor → Map page: opens (evidence: `README.md`)
- Visitor → About page: opens (evidence: `README.md`)
- Home page → Site navigation: shows navigation
- Map page → Persistent map: displays map
- Persistent map → Map interface: hosts (evidence: `web/src/components/map/PersistentMap.js`)
- Map interface → Globe engine: creates engine (evidence: `web/src/components/map/MapApp.js`)
- Map interface → Year selector: renders (evidence: `web/src/components/map/MapApp.js`)
- Map interface → Vegetation controls: renders (evidence: `web/src/components/map/MapApp.js`)
- Map interface → Basemap toggle: renders (evidence: `web/src/components/map/MapApp.js`)
- Map interface → Navigation controls: renders (evidence: `web/src/components/map/MapApp.js`)
- Map interface → Vegetation legend: renders (evidence: `web/src/components/map/MapApp.js`)
- Map interface → Place search: renders (evidence: `web/src/components/map/MapApp.js`)
- Place search → Geocoding client: searches places (evidence: `web/src/components/map/controls/SearchBar.js`)
- Geocoding client → Photon search: queries (evidence: `README.md`)
- Year selector → Panel interaction: uses panel logic (evidence: `web/src/components/map/controls/useHoverExpand.js`)
- Vegetation controls → Panel interaction: uses panel logic (evidence: `web/src/components/map/controls/useHoverExpand.js`)
- Basemap toggle → Panel interaction: uses panel logic (evidence: `web/src/components/map/controls/useHoverExpand.js`)
- Globe engine → NASA GIBS: fetches NDVI tiles (evidence: `README.md`)
- Globe engine → NASA GIBS: fetches water mask (evidence: `README.md`)
- Globe engine → Esri imagery: fetches imagery (evidence: `README.md`)
- Globe engine → OpenFreeMap tiles: loads map tiles (evidence: `README.md`)
- Globe engine → Browser cache: caches raw tiles (evidence: `README.md`)
- Globe engine → Vegetation colors: uses colors (evidence: `web/src/lib/map/chlorosatGlobeEngine.js`)
- Globe engine → Reference labels: uses labels (evidence: `web/src/lib/map/chlorosatGlobeEngine.js`)
- Pipeline CLI → Raster processing: invokes (evidence: `pipeline/src/chlorosat/cli.py`)
- Raster processing → Region configuration: reads regions (evidence: `pipeline/src/chlorosat/process.py`)
- Raster processing → NDVI calculation: computes NDVI (evidence: `pipeline/src/chlorosat/process.py`)
- Raster processing → Method definitions: uses classes (evidence: `pipeline/src/chlorosat/process.py`)
- Raster processing → Raster rendering: reprojects and colors (evidence: `pipeline/src/chlorosat/process.py`)
- Raster processing → PNG and manifest export: writes outputs (evidence: `pipeline/src/chlorosat/process.py`)
- PNG and manifest export → Method definitions: records methods (evidence: `pipeline/src/chlorosat/export.py`)
- PNG and manifest export → Raster rendering: saves PNG (evidence: `pipeline/src/chlorosat/export.py`)
