Skip to content

Latest commit

 

History

History
199 lines (156 loc) · 7.13 KB

File metadata and controls

199 lines (156 loc) · 7.13 KB

Architecture Documentation

Satellite Data Viewer is a hybrid React app with client-side viewing and optional serverless backend for downloads. Queries Microsoft Planetary Computer's STAC API and renders COG tiles via TiTiler. Built on a config-driven pattern with centralized collection metadata.

System Flow

flowchart TD
    User([User Browser]) --> SearchBar[SearchBar Component]
    
    SearchBar --> AppState[App State Manager]
    
    subgraph Configuration
        Config[collections.js]
    end
    
    subgraph Data Layer
        AppState --> StacApi[stacApi.js]
        StacApi --> Config
    end
    
    subgraph External Services
        StacApi --> STAC[Microsoft STAC API]
        MapComponent --> TiTiler[Microsoft TiTiler]
    end
    
    STAC --> Results[Search Results]
    Results --> AppState
    
    AppState --> ImageList[ImageList Component]
    ImageList --> Selection[User Selection]
    
    Selection --> AppState
    AppState --> MapComponent[MapLeaflet Component]
    
    Config --> MapComponent
    TiTiler --> Tiles[COG Tiles]
    
    Tiles --> Display([Rendered Map])
    Display --> User
Loading

Project Structure

sat-data-viewer/
├── src/
│   ├── components/
│   │   ├── MapLeaflet.jsx       # Leaflet map with tile overlays and measurements
│   │   ├── Map.css              # Map styling, legends, and controls
│   │   ├── SearchBar.jsx        # Search form with collection selector
│   │   ├── SearchBar.css        # Search bar styling
│   │   ├── ImageList.jsx        # Results list with band selectors
│   │   ├── ImageList.css        # Image list and band button styling
│   │   └── DownloadModal.jsx    # Download modal with Turnstile verification
│   ├── config/
│   │   └── collections.js       # Centralized satellite collection config
│   ├── utils/
│   │   ├── stacApi.js           # STAC API integration & formatting
│   │   └── downloadApi.js       # Backend download API client
│   ├── App.jsx                  # Main application & state management
│   ├── App.css                  # App layout with Earth background
│   ├── main.jsx                 # React entry point
│   └── index.css                # Global styles and CSS variables
├── public/
│   └── earth_clean.png          # Background image
├── vite.config.js               # Vite configuration
├── package.json                 # Dependencies
├── README.md
├── ARCHITECTURE.md              # This file
├── LICENSE.md
└── CONTRIBUTING.md

Components

App.jsx

Main state container. Manages search results, selected images, band selections, and coordinate ranges. Orchestrates data flow between child components.

SearchBar.jsx

Collection selector and search parameters. Dynamically shows/hides filters based on collection type (cloud cover for optical, date range for temporal data, etc.). Reads from collections.js config.

ImageList.jsx

Displays search results with thumbnails and metadata. Band selector layout is driven by config. Handles image selection and band switching.

MapLeaflet.jsx

Leaflet map with COG tile rendering, legends, measurement tools, and base layer switching. Uses buildTileUrl() from config to construct TiTiler URLs. Measurement tools use leaflet-draw + Turf.js for geodesic calculations.

DownloadModal.jsx

Download modal with band selection and Cloudflare Turnstile bot protection. Communicates with serverless backend (AWS Lambda) to process and download full-resolution GeoTIFF files. Files auto-delete after 10 minutes.

collections.js

Single source of truth for all satellite collections. Defines bands, rescale values, colormaps, legends, filters, and metadata display options. Components read this config instead of hardcoding collection logic.

stacApi.js

Handles STAC API queries. Reads collection config to determine which filters to include (datetime, cloud cover). Formats raw STAC items for app consumption.

downloadApi.js

Backend API client for downloads. Sends requests to AWS Lambda with Turnstile tokens. Handles file downloads and error states.

Component Hierarchy

App (state management)
├── SearchBar (collection selector, date range, filters, sliders)
├── ImageList (results with band selectors, metadata, action buttons)
├── MapLeaflet (Leaflet map with COG tile overlays, legends, measurements)
└── DownloadModal (download UI with Turnstile, band selection)

Data Flow

  1. User clicks "Set Search Point" → Map places blue rectangle
  2. User selects collection and parameters → SearchBar controls
  3. User submits search → App queries STAC API with collection filter
  4. Results returned → App formats items and updates ImageList
  5. User selects images and bands → App passes to MapLeaflet
  6. Map renders COG tiles → TiTiler serves tiles with band/colormap parameters
  7. User adjusts ranges → Map re-renders with new rescale values
  8. User clicks info button → Map displays STAC metadata overlay
  9. User clicks download → DownloadModal opens with Turnstile verification
  10. User completes Turnstile and submits → Backend processes and returns GeoTIFF
  11. File auto-deleted from S3 after 10 minutes

STAC API Integration

The app queries different collections based on user selection. Example for Sentinel-2:

POST https://planetarycomputer.microsoft.com/api/stac/v1/search
{
  "collections": ["sentinel-2-l2a"],
  "bbox": [minLon, minLat, maxLon, maxLat],
  "datetime": "2024-01-01/2024-12-31",
  "query": { "eo:cloud_cover": { "lt": 20 } },
  "limit": 10
}

Collection values: sentinel-2-l2a, landsat-c2-l2, sentinel-1-rtc, modis-13Q1-061, cop-dem-glo-30

Response is a GeoJSON FeatureCollection with STAC items.

Tile Rendering

TiTiler URLs are built from config:

https://planetarycomputer.microsoft.com/api/data/v1/item/tiles/
  WebMercatorQuad/{z}/{x}/{y}@1x?
  collection={collection}&
  item={item_id}&
  assets={band}&
  rescale={min},{max}&
  colormap_name={colormap}

Visual (TCI) bands have no rescale/colormap. Single bands (NIR, SWIR, etc.) use rescale and colormap from config.

Adding a Collection

Edit src/config/collections.js:

'new-collection-id': {
  name: 'Collection Name',
  displayName: 'Dropdown Label',
  type: 'optical',
  hasCloudFilter: true,
  hasDateFilter: true,
  defaultBand: 'visual',
  bands: {
    'band-id': {
      label: 'Button Label',
      assets: ['asset-name'],
      rescale: '0,4000',
      colormap: 'inferno',
      legend: { title: 'Title', min: '0', max: '4000', gradient: '...' }
    }
  },
  bandLayout: 'grid',
  metadata: { showCloudCover: true, showTileId: true }
}

The UI automatically updates. No component code changes needed.

Dependencies

  • React 19 + Vite 7.2.4
  • Leaflet + leaflet-draw
  • Turf.js (@turf/area, @turf/length)
  • Axios 1.13.4
  • Cloudflare Turnstile (for bot protection)
  • CSS custom properties for theming

Backend (serverless):