CNL-TN-2026-025 Technical Note

Your Ecological Address (YEA) — System Specification

Michael P. Hamilton , Ph.D.
Published: February 19, 2026 Version: 1

Your Ecological Address (YEA) — System Specification

A Multi-Source Ecological Profiling Engine for Any Location on Earth

Document ID: CNL-SP-2026-XXX Version: 1.1 Date: February 19, 2026 Author: Michael P. Hamilton, Ph.D.

AI Assistance Disclosure: This specification was developed with assistance from Claude (Anthropic, Opus 4.6). The AI contributed to system documentation, API reference compilation, and manuscript drafting based on the author's working codebase and architectural decisions. The author takes full responsibility for the content, accuracy, and conclusions.


Abstract

Your Ecological Address (YEA) is a single-page web application that transforms geographic coordinates into comprehensive ecological profiles by querying 17 or more geospatial and biodiversity APIs in parallel. Given any latitude and longitude on Earth, the system returns a structured ecological identity spanning terrain morphometry, climate classification, multi-decadal climate history, soil thermal regimes and water balance, ecoregion taxonomy, land cover characterization, real-time weather conditions, multi-taxon biodiversity inventories, seasonal phenology, recent avian field observations, and acoustic bird detections. The tool integrates data sources ranging from sub-meter terrain models [1] to 85-year reanalysis climate records [17,18,19,20] and citizen science platforms with hundreds of millions of observations [2,3], unified through a card-based progressive-disclosure interface designed for accessibility. A key architectural principle is silo independence: each data card owns its own API sources, and cross-silo ecological interpretation is delegated to a narrative LLM layer. A MySQL caching layer with source-appropriate time-to-live values manages API rate limits while preserving temporal fidelity. YEA serves as a standalone ecological reference tool, a metadata engine for the SCOPE panoramic photograph database, and a prototype component of the Macroscope integrated environmental observatory platform. This specification documents the complete system architecture, all API endpoints and data contracts, the frontend card system, database schema, caching strategy, and development conventions sufficient for independent reimplementation.


1. Introduction

1.1 Purpose and Concept

YEA computes an "ecological address" for any point on Earth. Where a postal address locates a person within a human administrative framework, an ecological address locates them within the planet's natural organization: what biogeographic realm, what biome, what ecoregion, what climate zone, what terrain, what species community. The tool answers the question: what would a naturalist tell you about this place?

The application accepts input via map click (Mapbox GL JS satellite imagery), place name search (dual iNaturalist and Mapbox Geocoding), direct coordinate entry, or browser geolocation. A single backend call orchestrates parallel queries to all data sources, returning a consolidated JSON response that the frontend renders as a set of eleven expandable data cards.

1.2 Context

YEA is a component of the Macroscope project at the Canemah Nature Laboratory [4]. It is standalone — no shared header, footer, or CSS with other projects. It is linked from the Coffee with Claude essay "Your Ecological Address" and designed as a future MacroscopeVR feature. A key secondary use is populating ecological metadata for 400+ panoramic photographs in the SCOPE database.

1.3 Design Philosophy

Five principles guide the system:

  1. Naturalist interpretation over raw data. Data is contextualized, not just displayed.
  2. Senior-friendly accessibility. 26px Georgia serif base font, high contrast warm parchment palette, large tap targets — informed by user feedback.
  3. Progressive disclosure. Snapshot cards (compact summary) expand to full detail on tap.
  4. Graceful degradation. US-only sources (EPA, NLCD) are skipped for international coordinates; global alternatives (RESOLVE, Esri Sentinel-2) are always available.
  5. Data richness over implementation complexity. Seventeen or more APIs unified into a coherent ecological narrative through straightforward parallel fetching and parsing.
  6. Silo independence. Each data card owns its own API sources. Cross-silo ecological interpretation is delegated to the narrative LLM layer, not embedded in the data pipeline.

2. Architecture

2.1 Deployment

Property Value
Server Production LAMP server (macOS, Apple Silicon)
Web server Apache 2
Backend PHP 8.3+, mysqli (no PDO)
Database MySQL 8.4+ (managed via phpMyAdmin)
Frontend Vanilla JavaScript, Mapbox GL JS 3.3.0
DEM processing ImageMagick CLI (convert)
URL https://canemah.org/projects/ecoADDRESS/
Project root ecoADDRESS/ (under Apache document root)

2.2 File Structure

ecoADDRESS/
  index.php          — Page shell: hero banner, search bar, map, results container
  address_api.php    — Backend orchestrator: validation, caching, API coordination, JSON response
  sources.php        — URL builders for all APIs + parallel fetch engine (curl_multi) + GraphQL client
  parsers.php        — Response parsers for all data sources + master parseAll() assembler
  database.php       — MySQL caching (lookup_cache), query logging (lookup_log), narrative cache scaffold
  address.js         — Map setup, dual place search, event handlers, fetch orchestration
  cards.js           — Card rendering module (EcoCards): placeholders, snapshots, expanded views, lightbox
  address.css        — Warm parchment palette, card grid, species thumbnails, lightbox modal

2.3 Credential Files (Outside Webroot)

Credential files are stored outside the webroot in a secure directory, not accessible via HTTP:

(secure credentials directory)/
  ai-config.php      — Defines WU_API_KEY, MAPBOX_TOKEN, EBIRD_API_KEY
  ecoaddress.php     — Database credentials: $db_host, $db_name, $db_user, $db_pass

2.4 Request Flow

The request lifecycle proceeds as follows:

  1. User clicks map, searches a place name, enters coordinates, or uses browser geolocation.
  2. address.js calls GET address_api.php?lat={lat}&lon={lon}.
  3. The orchestrator validates input and determines CONUS membership (US bounding box check).
  4. Mapbox tile coordinates are computed for zoom level 14.
  5. MySQL cache is checked for existing responses (cacheGetAll).
  6. URLs are built only for uncached sources (buildUrls in sources.php).
  7. All uncached sources are fetched in parallel via curl_multi (fetchAll in sources.php).
  8. New responses are cached (cacheSetAll).
  9. All responses are parsed (parseAll in parsers.php).
  10. Sequential Weather Underground station iteration finds an active personal weather station (PWS) within five miles.
  11. PWS temperature is validated against Open-Meteo baseline (±10 °F divergence rejection).
  12. Dynamic radius widening runs for iNaturalist (1 → 5 → 10 → 20 km if fewer than five species).
  13. Dynamic radius widening runs for eBird (same cascade).
  14. Dynamic radius widening runs for BirdWeather (same cascade, GraphQL POST with bounding box).
  15. BirdWeather station metadata is fetched via the Species.stations nested field.
  16. Open-Meteo Historical API is queried for 30-year climate normals (cached permanently; skipped if cache hit).
  17. Open-Meteo Historical ERA5-Land is queried for 30-year soil/ET₀ normals (cached permanently; skipped if cache hit).
  18. iNaturalist seasonal queries (month-filtered) run for all nine taxa using the same radius widening logic.
  19. Monthly summary statistics are computed server-side from historical daily records.
  20. Query is logged with timing and per-source status.
  21. Consolidated JSON is returned to the frontend.
  22. cards.js renders eleven data cards. Async bird photo backfill begins for eBird and BirdWeather species missing thumbnails.

3. Data Sources

YEA integrates 17 or more external data sources spanning terrain, climate, climate history, soil hydrology, ecoregion classification, land cover, weather, biodiversity, phenology, and avian monitoring. Each source is described below with its endpoint, scope, resolution, and cache policy.

3.1 Source Summary

# Source Data Scope Resolution Cache TTL
1 Mapbox Terrain-RGB DEM [1] Elevation, slope, aspect Global ~9.5 m (zoom 14) Permanent
2 Köppen Climate API [5] Climate zone + description Global ~28 km 90 days
3 Mapbox Reverse Geocoding [1] Place name, county, state Global Point Permanent
4 RESOLVE Ecoregions 2017 [6] Realm, biome, ecoregion Global Vector polygon Permanent
5 Esri Sentinel-2 10m LULC [7] 9-class land cover Global 10 m Permanent
6 EPA Omernik Ecoregions [8,9] Levels I–IV US only 1:250K Permanent
7 MRLC NLCD 2021 [10] 20-class land cover CONUS 30 m Permanent
8 USDA FIA Forest Atlas [11] Forest type group CONUS (forest) 250 m 1 year
9 Weather Underground [12] PWS current conditions Global Point 15 min
10 Open-Meteo [13] Modeled weather baseline Global Reanalysis grid 15 min
11 iNaturalist [2] Species counts (9 taxa) Global Point + radius 7 days
12 eBird API 2.0 [3,14] Recent + notable observations Global Point + radius 6 hours
13 BirdWeather [15,16] Acoustic detections + stations Global (station-dependent) Bounding box 6 hours
14 Open-Meteo Historical [17,18,20] 30-year climate normals (temperature, precipitation, wind, sunshine) Global 9–25 km Permanent
15 Open-Meteo Historical ERA5-Land [17,19,20] Soil temperature (4 depths), soil moisture (4 depths), ET₀ Global ~11 km (0.1°) Permanent
16 iNaturalist Seasonal [2] Month-filtered species counts (9 taxa, 3-month window) Global Point + radius 7 days

3.2 API Endpoints

3.2.1 Mapbox Terrain-RGB DEM [1]

https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{tx}/{ty}.pngraw?access_token={token}

Returns a raw PNG tile encoding elevation in the RGB channels. Elevation is decoded as: −10000.0 + ((R × 256 × 256 + G × 256 + B) × 0.1), yielding 0.1 m precision. Slope and aspect are computed from a 3×3 pixel neighborhood gradient using ImageMagick CLI to write a temporary PNG, crop a 3×3 region via convert -depth 8 -crop, and parse the text output (~100–200 ms overhead, no PHP extension dependencies). Requires MAPBOX_TOKEN.

3.2.2 Köppen Climate API [5]

http://climateapi.scottpinkelman.com/api/v1/location/{lat}/{lon}

Returns the Köppen-Geiger climate zone code and description. No API key required.

3.2.3 Mapbox Reverse Geocoding [1]

https://api.mapbox.com/geocoding/v5/mapbox.places/{lon},{lat}.json
  ?access_token={token}&types=place,region,district,locality

Returns place name, county, and state. Requires MAPBOX_TOKEN.

3.2.4 RESOLVE Ecoregions 2017 [6]

https://data-gis.unep-wcmc.org/server/rest/services/
  Bio-geographicalRegions/Resolve_Ecoregions/MapServer/identify
  ?geometry={lon},{lat}&geometryType=esriGeometryPoint&sr=4326
  &layers=all:0&tolerance=0
  &mapExtent={bbox ± 0.01°}&imageDisplay=800,600,96
  &returnGeometry=false&f=json

Returns realm, biome, ecoregion name, Nature Needs Half category. No API key required. The tight bounding box (± 0.01°) is critical for accuracy at ecotone boundaries.

3.2.5 Esri Sentinel-2 10m LULC [7]

https://ic.imagery1.arcgis.com/arcgis/rest/services/
  Sentinel2_10m_LandCover/ImageServer/identify
  ?geometry={"x":{x_merc},"y":{y_merc},"spatialReference":{"wkid":3857}}
  &geometryType=esriGeometryPoint&returnGeometry=false
  &returnCatalogItems=false&f=json

Requires Web Mercator projection. Nine land cover classes: Water (1), Trees (2), Flooded Vegetation (4), Crops (5), Built Area (7), Bare Ground (8), Snow/Ice (9), Clouds (10), Rangeland (11). No API key required.

3.2.6 EPA Omernik Ecoregions [8,9]

https://geodata.epa.gov/arcgis/rest/services/
  ORD/USEPA_Ecoregions_Level_III_and_IV/MapServer/identify
  ?geometry={lon},{lat}&geometryType=esriGeometryPoint&sr=4326
  &layers=all:7&tolerance=0
  &mapExtent={bbox ± 0.01°}&imageDisplay=800,600,96
  &returnGeometry=false&f=json

US only. Layer 7 = Level IV polygons, which return all four Omernik levels in a single query. The tight bounding box (± 0.01°) replaces the default global map extent, which caused incorrect polygon returns at mountain ecotone boundaries. No API key required.

3.2.7 MRLC NLCD 2021 [10]

https://www.mrlc.gov/geoserver/mrlc_display/
  NLCD_2021_Land_Cover_L48/ows
  ?service=WMS&version=1.1.1&request=GetFeatureInfo
  &layers=NLCD_2021_Land_Cover_L48
  &query_layers=NLCD_2021_Land_Cover_L48
  &info_format=application/json&x=50&y=50&width=101&height=101
  &srs=EPSG:4326&bbox={bbox ± 0.005°}

CONUS only. Twenty land cover classes at 30 m resolution. No API key required.

3.2.8 USDA FIA Forest Atlas [11]

https://imagery.geoplatform.gov/iipp/rest/services/Vegetation/
  USFS_EDW_FIA_ForestAtlas_ForestTypeGroups_109_CONUS/ImageServer/identify
  ?geometry={"x":{x_merc},"y":{y_merc},"spatialReference":{"wkid":3857}}
  &geometryType=esriGeometryPoint&returnGeometry=false&f=json

CONUS only, forested pixels only. Requires User-Agent header. Returns NoData for non-forested and urban-edge pixels. Web Mercator projection required. No API key required.

3.2.9 Weather Underground [12]

Nearby stations:

https://api.weather.com/v3/location/near
  ?geocode={lat},{lon}&product=pws&format=json&apiKey={key}

Current conditions (sequential, per station):

https://api.weather.com/v2/pws/observations/current
  ?stationId={id}&format=json&units=e&apiKey={key}

Requires WU_API_KEY. The orchestrator iterates through up to five nearest stations, querying each sequentially until one reports non-null temperature. PWS data is validated against the Open-Meteo baseline; temperature divergence exceeding ± 10 °F triggers station rejection.

3.2.10 Open-Meteo [13]

https://api.open-meteo.com/v1/forecast
  ?latitude={lat}&longitude={lon}
  &current=temperature_2m,relative_humidity_2m,wind_speed_10m,
           wind_direction_10m,surface_pressure
  &temperature_unit=fahrenheit&wind_speed_unit=mph

Global modeled weather baseline. Always queried regardless of PWS availability. No API key required.

3.2.11 iNaturalist [2]

https://api.inaturalist.org/v1/observations/species_counts
  ?lat={lat}&lng={lon}&radius={km}&per_page={n}
  [&iconic_taxa={taxon}]

Nine taxon groups are queried independently: Plantae, Fungi, Aves, Mammalia, Reptilia, Amphibia, Insecta, Arachnida, Mollusca. Plants return per_page=20; all others return per_page=10. A total species count query (no taxon filter) is also made. No API key required.

3.2.12 eBird API 2.0 [3,14]

Recent observations (30 days):

https://api.ebird.org/v2/data/obs/geo/recent
  ?lat={lat}&lng={lon}&dist={km}&back=30&sort=species&key={key}

Notable/rare species (14 days):

https://api.ebird.org/v2/data/obs/geo/recent/notable
  ?lat={lat}&lng={lon}&dist={km}&back=14&key={key}

Requires EBIRD_API_KEY.

3.2.13 BirdWeather GraphQL [15,16]

POST to https://app.birdweather.com/graphql. No API key required.

Species detections (7 days):

{
  topSpecies(
    ne: {lat: NE_LAT, lon: NE_LON},
    sw: {lat: SW_LAT, lon: SW_LON},
    period: {count: 7, unit: "day"},
    limit: 20
  ) {
    species {
      id commonName scientificName thumbnailUrl imageUrl
      ebirdCode ebirdUrl birdweatherUrl wikipediaSummary color
    }
    count
    breakdown { almostCertain veryLikely uncertain unlikely }
  }
}

Station metadata (via Species.stations nested field): The root stations GraphQL query returns HTTP 500 (broken server-side). Station metadata is recovered via the Species.stations nested field, which uses a different resolver. The system queries topSpecies(limit:3) with nested stations to discover PUC devices in the bounding box, then deduplicates by station ID.

{
  topSpecies(
    ne: {lat: NE_LAT, lon: NE_LON},
    sw: {lat: SW_LAT, lon: SW_LON},
    period: {count: 7, unit: "day"},
    limit: 3
  ) {
    species {
      commonName
      stations(ne: {lat: NE_LAT, lon: NE_LON},
               sw: {lat: SW_LAT, lon: SW_LON}) {
        count
        station { id name coords { lat lon } type location latestDetectionAt }
      }
    }
  }
}

Note: BirdWeather InputLocation uses {lat, lon} (not {lat, lng}).

3.2.14 Open-Meteo Historical API — Climate Normals [17,18,20]

Daily aggregates, 30-year baseline (1991–2020):

https://archive-api.open-meteo.com/v1/archive
  ?latitude={lat}&longitude={lon}
  &start_date=1991-01-01&end_date=2020-12-31
  &daily=temperature_2m_max,temperature_2m_min,temperature_2m_mean,
         precipitation_sum,wind_speed_10m_max,sunshine_duration,
         daylight_duration
  &temperature_unit=fahrenheit&wind_speed_unit=mph
  &precipitation_unit=inch&timezone=auto

Returns 10,950 daily records spanning 30 years. The response is processed server-side into monthly summary statistics (mean, min, max for temperature; total and monthly mean for precipitation; mean sunshine hours). Monthly summaries are cached permanently; raw daily data is not stored. The "Best Match" model is used by default, which seamlessly combines ECMWF IFS (9 km, 2017–present) with ERA5 and ERA5-Land for the earlier record.

No API key required for non-commercial use.

Trend detection: A secondary query for recent decades (2010–2024) compared against the 1991–2020 baseline enables detection of climate trends: warming, drying, lengthening growing seasons. Trend deltas are computed as differences between the recent and baseline monthly means.

3.2.15 Open-Meteo Historical API — Soils and ET₀ [17,19,20]

Daily soil and water balance, 30-year baseline (1991–2020):

https://archive-api.open-meteo.com/v1/archive
  ?latitude={lat}&longitude={lon}
  &start_date=1991-01-01&end_date=2020-12-31
  &daily=et0_fao_evapotranspiration,precipitation_sum,
         soil_temperature_0_to_7cm,soil_temperature_7_to_28cm,
         soil_temperature_28_to_100cm,soil_temperature_100_to_255cm,
         soil_moisture_0_to_7cm,soil_moisture_7_to_28cm,
         soil_moisture_28_to_100cm,soil_moisture_100_to_255cm
  &models=era5_land
  &temperature_unit=fahrenheit&precipitation_unit=inch
  &timezone=auto

Explicitly requests the ERA5-Land model for its higher spatial resolution on surface variables (0.1° / ~11 km versus ERA5's 0.25° / ~25 km). Returns soil temperature and moisture at four depth layers (0–7 cm, 7–28 cm, 28–100 cm, 100–255 cm) plus FAO-56 Penman-Monteith reference evapotranspiration (ET₀).

Monthly summaries computed server-side:

  • Soil thermal profile: Monthly mean temperature at each depth.
  • Soil moisture profile: Monthly mean volumetric water content at each depth.
  • Water balance: Monthly precipitation minus ET₀. Positive = surplus (recharge); negative = deficit (drought stress).
  • Growing degree days: Accumulated from soil temperature at 0–7 cm using a 5°C base.

No API key required for non-commercial use.

3.2.16 iNaturalist Seasonal (Month-Filtered) [2]

https://api.inaturalist.org/v1/observations/species_counts
  ?lat={lat}&lng={lon}&radius={km}&per_page={n}
  &month={prev},{current},{next}
  [&iconic_taxa={taxon}]

Same endpoint as the Biodiversity card (3.2.11) but with the month= parameter added. The month parameter accepts comma-separated month numbers (1–12) and returns observations from those months across all years in the database, collapsing interannual variation onto a 12-month calendar. This solves the episodic observation problem — a species photographed in October 2017, October 2020, and November 2022 correctly appears as an autumn organism regardless of gaps between observations.

The three-month window (current month ± 1) captures:

  • Species active in the current season.
  • Early and late seasonal transitions (arrivals, departures, first blooms, last fruiting).
  • Shoulder-season species that might be missed by a single-month filter.

Month wrapping is handled in PHP: for January, the query becomes month=12,1,2; for December, month=11,12,1.

The same nine taxon groups and radius widening logic apply. Species present in the Biodiversity card's all-time list but absent from the Seasonality card's month-filtered results are, by inference, not typically active in the current season — information the narrative engine uses without the Seasonality card needing to state it explicitly.

3.3 Coordinate Transformations

Web Mercator (EPSG:3857) is required by the Esri LULC and USDA FIA endpoints:

$x_merc = $lon * 20037508.34 / 180;
$y_merc = log(tan(M_PI / 4 + deg2rad($lat) / 2)) * 20037508.34 / M_PI;

CONUS detection for conditional US-only source queries:

$is_conus = ($lat >= 24.0 && $lat <= 50.0 && $lon >= -125.0 && $lon <= -66.0);

4. Dynamic Radius Widening

All three biodiversity sources (iNaturalist, eBird, BirdWeather) use the same progressive widening pattern to ensure adequate species coverage regardless of observation density:

  1. Initial query at 1 km radius.
  2. If species count is below the threshold (fewer than five species), widen progressively: 5 → 10 → 20 km.
  3. Accept the first radius meeting the threshold, or accept the maximum (20 km) result.
  4. BirdWeather uses a bounding box computed from radius_km / 111.1 latitude offset rather than a true radius parameter.

Each widened query is a fresh fetchAll() or fetchBirdWeather() call. The widening cascades run sequentially after the initial parallel fetch completes. The final radius used is recorded in the JSON response for display in the UI.


5. Weather Validation

Personal weather stations (PWS) from Weather Underground can report erroneous data due to sensor malfunction, poor siting, or communication failures. YEA implements a validation strategy:

  1. Open-Meteo is always queried as a global modeled baseline.
  2. WU stations are accepted only within five miles of the query point.
  3. The orchestrator iterates sequentially through up to five nearest WU stations until one reports non-null temperature.
  4. The PWS temperature is compared against the Open-Meteo baseline. If divergence exceeds ± 10 °F, the station is rejected as malfunctioning.
  5. On rejection or absence of any valid PWS, modeled Open-Meteo data is used as fallback and tagged as "modeled" in the UI.

6. Database Schema

Database: ecological_address

6.1 lookup_cache

Stores raw API responses keyed by rounded coordinates and source identifier. Composite unique key (coord_key, source). Coordinate key format: lat and lon rounded to four decimal places (~11 m precision), e.g., "45.3573,-122.6068". Terrain PNG data is base64-encoded for storage in MEDIUMTEXT.

CREATE TABLE lookup_cache (
  id int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  coord_key varchar(24) NOT NULL,
  source varchar(32) NOT NULL,
  response MEDIUMTEXT NOT NULL,
  created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uk_coord_source (coord_key, source),
  KEY idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

6.2 lookup_log

Records every query with timing and per-source cache status for monitoring and debugging.

CREATE TABLE lookup_log (
  id int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  coord_key varchar(24) NOT NULL,
  lat decimal(8,4) NOT NULL,
  lon decimal(9,4) NOT NULL,
  place_name varchar(128) DEFAULT NULL,
  duration_ms int UNSIGNED NOT NULL,
  source_status JSON NOT NULL,
  created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  KEY idx_coord (coord_key),
  KEY idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

6.3 narrative_cache (Scaffold — Not Yet Active)

Prepared for future LLM narrative generation. Keyed by coordinate + MD5 hash of parsed ecological data (excluding weather and eBird, which change too frequently). Functions narrativeHash(), narrativeCacheGet(), and narrativeCacheSet() are implemented in database.php.

CREATE TABLE narrative_cache (
  id int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  coord_key varchar(24) NOT NULL,
  data_hash char(32) NOT NULL,
  narratives MEDIUMTEXT NOT NULL,
  provider varchar(16) NOT NULL,
  model varchar(64) NOT NULL,
  created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uk_coord_hash (coord_key, data_hash),
  KEY idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

6.4 Cache TTL Strategy

Cache expiration is organized by the temporal behavior of each data source:

Temporal Class TTL Sources
Geological (permanent) 365 days terrain, ecoregion, resolve_eco, nlcd, esri_lulc, reverse_geo
Climate (static dataset) 90 days koppen
Climate normals (permanent) 365 days climate_history, climate_trend, soils_et
Annual dataset 365 days usda_fia
Seasonal accumulation 7 days all inat* sources, all season* sources
Daily activity 6 hours ebird_recent, ebird_notable, bw_species
Real-time 15 minutes wu_nearby, open_meteo
Narrative 30 days narrative_cache (keyed by data hash)

7. JSON Response Contract

The address_api.php endpoint returns a JSON object. All sections may be null if the corresponding source returned no data, errored, or is not applicable (e.g., EPA ecoregion for international coordinates). Key structural elements:

  • coordinates{lat, lon} as submitted
  • is_conus — Boolean, determines which conditional sources were queried
  • place{place_name, county, state} from Mapbox reverse geocoding
  • elevation{meters, feet, slope_degrees, aspect_degrees, aspect_label} from DEM
  • climate{zone, description} from Köppen
  • ecoregion — EPA Omernik Levels I–IV (US only, null internationally)
  • resolve_ecoregion{realm, biome_name, eco_name, nnh_name} (always present globally)
  • land_cover — NLCD class (US only, null internationally)
  • esri_lulc — Sentinel-2 class (always present globally)
  • forest_type — USDA FIA group (US forested pixels only)
  • weather{stations[], current{}} from WU (null if no valid PWS)
  • modeled_weather — Open-Meteo baseline (always present)
  • biodiversity{summary{total_species, radius_km}, taxa{plantae, fungi, aves, mammalia, reptilia, amphibia, insecta, arachnida, mollusca}} — each taxon contains {total, species[{name, sci_name, count, taxon_id, photo_url, photo_sq, iconic_taxa}]}
  • seasonality{summary{total_species, radius_km, months[int]}, taxa{plantae, fungi, aves, mammalia, reptilia, amphibia, insecta, arachnida, mollusca}} — same structure as biodiversity but month-filtered. months array indicates the 3-month window used (e.g., [1,2,3] for February lookup).
  • climate_history{baseline_period, months[{month, temp_mean, temp_high, temp_low, precip_mean_in, sunshine_hrs, wind_max_mph}], annual{temp_mean, precip_total_in, frost_free_days, wet_season_pct}, trend{period, temp_delta, precip_delta_pct}}
  • soils{baseline_period, months[{month, soil_temp_7cm, soil_temp_28cm, soil_temp_100cm, soil_temp_255cm, soil_moisture_7cm, soil_moisture_28cm, soil_moisture_100cm, soil_moisture_255cm, et0_in, precip_in, water_balance_in}], annual{total_et0_in, total_precip_in, surplus_months, deficit_months, gdd_total}}
  • ebird{recent[], notable[], notable_codes[], radius_km}
  • birdweather{species[{com_name, sci_name, detection_count, confident_count, thumb_url, image_url, ebird_code, breakdown{}}], stations[{id, name, lat, lon, type, location, latest_detection_at, distance_km}], radius_km}

8. Frontend Card System

8.1 Card Definitions

Eleven cards in a two-column CSS Grid (single column below 640 px; expanded cards span full width):

Card ID Title Primary Sources
place Your Place Mapbox DEM
climate Climate Zone Köppen
climate_history Climate History Open-Meteo Historical (30-year daily)
ecoregion Ecoregion and Biome EPA Omernik + RESOLVE 2017 + USDA FIA
land_cover Land Cover NLCD + Esri Sentinel-2
conditions Current Conditions WU PWS + Open-Meteo
soils Soils and Water Balance Open-Meteo Historical ERA5-Land (soil temps, moisture, ET₀)
biodiversity Biodiversity iNaturalist (9 taxa, all-time, unfiltered)
seasonality Seasonality iNaturalist (9 taxa, month-filtered)
recent_activity Recent Bird Activity eBird
birdweather Nearby Vocalizing Birds BirdWeather

Card ordering rationale: The environmental story flows from permanent identity (place, climate zone) through temporal context (climate history, ecoregion, land cover, current conditions, soils) to biological inventory (biodiversity, seasonality, recent birds, acoustic detections). This sequence mirrors the way a naturalist orients: geology first, climate second, biology third.

8.2 New Card Specifications

8.2.1 Climate History Card

Silo: Open-Meteo Historical API (archive endpoint), "Best Match" model. Independent of the Climate Zone card (Köppen) and Current Conditions card (Open-Meteo forecast + WU).

Ecological question: What is the long-term atmospheric character of this place? How is it changing?

Snapshot: One-line climate summary derived from 30-year normals, e.g., "Mild maritime — 52 °F mean, 47 in annual rain, 78% Oct–Mar."

Expanded view:

  • Temperature regime: 12-month display of mean daily high, mean daily low, and overall mean. Absolute record high/low per month from the 30-year record.
  • Precipitation pattern: Monthly mean totals. Wet season / dry season identification (months where precipitation exceeds the annual monthly mean). Annual total. Percent of annual precipitation falling in wettest 6 months.
  • Sunshine and day length: Monthly mean sunshine hours. Comparison to daylight hours gives cloud cover proxy.
  • Wind regime: Monthly mean of daily maximum wind speed. Prevailing wind note if dominant direction is consistent.
  • Trend indicators: If 2010–2024 data diverges meaningfully from the 1991–2020 baseline, display trend annotations: warming, drying, wetter, longer frost-free season. Presented as delta values (e.g., "+1.8 °F mean temperature, recent 15 years vs. 30-year normal").

Cache: Permanent. Climate normals for a coordinate do not change. The 30-year baseline query runs once per coordinate, and the derived monthly statistics are stored in lookup_cache under source key climate_history. Trend data uses source key climate_trend.

API calls: Two calls to archive-api.open-meteo.com — one for the 1991–2020 baseline, one for 2010–2024 trend comparison. Both are daily resolution. Total response: approximately 10,950 + 5,475 daily records, processed into 12 monthly summary objects each.

8.2.2 Soils and Water Balance Card

Silo: Open-Meteo Historical API (archive endpoint), ERA5-Land model explicitly. Independent of Climate History card despite sharing the same API base.

Ecological question: What is the below-ground character of this place? When does it have water, when does it not?

Snapshot: One-line water balance summary, e.g., "Seasonally moist — surplus Dec–Apr, deficit Jul–Sep."

Expanded view:

  • Soil thermal profile: Monthly mean temperature at four depths (0–7, 7–28, 28–100, 100–255 cm). The depth gradient reveals thermal buffering — surface soils may freeze while deep soils remain above zero, or surface soils may bake while depth stays cool. This drives root activity, germination timing, and invertebrate phenology.
  • Soil moisture profile: Monthly mean volumetric water content at four depths. Shows the seasonal wetting and drying front moving through the soil column.
  • Water balance: Monthly precipitation minus ET₀. Bar or sparkline showing surplus months (positive, recharge) and deficit months (negative, drought stress). This is the single most important ecological variable for vegetation — it determines what can grow.
  • Growing degree accumulation: Cumulative growing degree days (base 5 °C) from soil temperature at 0–7 cm, by month. Indicates when the soil is biologically active.

Cache: Permanent, source key soils_et. Same rationale as Climate History — 30-year normals do not change.

API calls: One call to archive-api.open-meteo.com with models=era5_land and the soil/ET₀ variable set. Approximately 10,950 daily records processed into 12 monthly summary objects.

8.2.3 Seasonality Card

Silo: iNaturalist API with month= parameter. Independent of the Biodiversity card despite querying the same API endpoint.

Ecological question: What is typically active at this place right now? What is the phenological moment?

Snapshot: One-line seasonal summary, e.g., "February: 34 species active — winter birds, early fungi, no insect activity."

Expanded view:

  • Seasonally active species by taxon group: Same nine-taxon display structure as Biodiversity, but filtered to the current three-month window. Species present here are those observed at this location during the current month (± 1 month) across all years in the iNaturalist database.
  • Seasonal contrast: Total species count from the Seasonality card compared to the Biodiversity card's all-time count, expressed as a fraction: "34 of 247 species typically active in this season." This single number tells the LLM whether this is a high-diversity season or a dormant one.
  • Taxon-level seasonality notes: For taxon groups where the seasonal count drops to zero (e.g., Insecta in February at a northern temperate site), the card explicitly states "No insect observations recorded in this season." This absence is ecological information — the narrator should say "insect activity is dormant" rather than silently omitting the group.
  • Month label: The card always displays which months define the current seasonal window, e.g., "Showing species observed in January, February, March (across all years)."

Cache: 7-day TTL, matching the Biodiversity card's iNat caching. Source keys: season_plantae, season_fungi, season_aves, etc. The month window rolls with the calendar — a query on January 31 and February 1 will produce different seasonal windows and different cache keys.

API calls: Same structure as Biodiversity — nine taxon queries plus one total count — but with the month= parameter appended. Same dynamic radius widening. Same per_page values (20 for plants, 10 for others). The only difference is the month filter.

8.3 Card States

Each card has three visual states:

  1. Placeholder — displayed before any search. Shows category title and explanatory text describing what data the card will contain.
  2. Snapshot — compact data summary after search. One-line key data value plus source attribution tag.
  3. Expanded — full detail view on card click. Card spans both grid columns, snapshot is hidden, all fields and species lists are rendered with collapsible sections.

8.4 Interactive Features

  • Card expand/collapse — click anywhere on a data card to toggle.
  • Open All Cards / Close All Cards toggle button above the grid.
  • Collapsible taxon groups — representative thumbnail, group label, species count. Click to expand the species list.
  • "Show all N species" button — fetches full species list (up to 200) from the iNaturalist API when the initial load was truncated.
  • Collapsible eBird sections — "Notable and Rare" and "Recent Sightings" toggle independently.
  • Collapsible BirdWeather sections — "Listening Stations" and "Detected Species."
  • Species lightbox modal — click any species item to see full image, common name, scientific name, count, and links to iNaturalist, eBird, BirdWeather, and Wikipedia.
  • Async bird photo backfill — eBird and BirdWeather species lacking thumbnails are queried against the iNaturalist taxa autocomplete API. Results are cached in a module-level _taxaPhotoCache object and applied to the DOM progressively in batches of three concurrent requests.
  • New Search button — resets to clean state: removes map marker, restores placeholder cards, resets map view.

8.5 Source Attribution

Every card displays data source attribution in both compact (snapshot) and full (expanded) states, identifying the originating dataset and, where applicable, linking to the source organization.


9. UI Design Specifications

9.1 Color Palette

The "warm parchment" palette uses earth tones:

Element Hex
Page background #f5f0e8
Primary text #2c2416
Card background #fffdf7
Card border #c4b99a
Accent / buttons #5c7a3a (forest green)
Section headers #5c7a3a (uppercase)
Secondary text #5a4e3a, #7a6e56
Muted text #9a8e76, #b0a690
Card hover border #7a8c5a

9.2 Typography

Property Value
Font family Georgia, 'Times New Roman', serif
Base font size 26 px (bumped for senior accessibility)
Mobile base 24 px
Line height 1.7
Coordinate display 'SF Mono', 'Fira Code', Consolas, monospace
Card titles 1.1 rem, bold, uppercase, letter-spacing 0.04 em
Hero title 2.5 rem, normal weight

9.3 Map Configuration

Mapbox GL JS 3.3.0 with satellite-streets-v12 style. Default center: Canemah [−122.6068, 45.3573], zoom 10. Red marker (#e74c3c). Navigation control top-right. Dual place search merges iNaturalist Places (reserves, parks, field stations) with Mapbox Geocoding (addresses, cities, POIs), tagging results by source.


10. Lookup Table Constants

10.1 NLCD 2021 Land Cover Classes [10]

Code Description Code Description
11 Open Water 42 Evergreen Forest
12 Perennial Ice/Snow 43 Mixed Forest
21 Developed, Open Space 51 Dwarf Scrub
22 Developed, Low Intensity 52 Shrub/Scrub
23 Developed, Medium Intensity 71 Grassland/Herbaceous
24 Developed, High Intensity 72 Sedge/Herbaceous
31 Barren Land 73 Lichens
41 Deciduous Forest 74 Moss
81 Pasture/Hay 90 Woody Wetlands
82 Cultivated Crops 95 Emergent Herbaceous Wetlands

10.2 Esri Sentinel-2 LULC Classes [7]

Code Description Code Description
1 Water 8 Bare Ground
2 Trees 9 Snow/Ice
4 Flooded Vegetation 10 Clouds
5 Crops 11 Rangeland
7 Built Area

10.3 USDA FIA Forest Type Groups [11]

Selected common groups: White/Red/Jack Pine (100), Spruce/Fir (120), Pinyon/Juniper (180), Douglas-fir (200), Ponderosa Pine (220), Fir/Spruce/Mountain Hemlock (260), Hemlock/Sitka Spruce (300), Redwood (340), California Mixed Conifer (370), Oak/Pine (400), Oak/Hickory (500), Elm/Ash/Cottonwood (700), Maple/Beech/Birch (800), Alder/Maple (910), Western Oak (920), Tanoak/Laurel (940).


11. Key Technical Decisions

Decision Rationale
Mapbox DEM over Open-Meteo elevation 0.1 m precision vs 90 m. Slope and aspect require fine resolution from 3×3 neighborhood.
ImageMagick CLI over PHP GD No GD/Imagick extensions on Galatea. convert handles DEM pixel extraction reliably.
EPA tight bounding box (± 0.01°) Default global map extent caused wrong polygon returns at mountain ecotone boundaries.
Dual place search (iNat + Mapbox) iNaturalist Places finds ecological sites (reserves, parks). Mapbox finds human places (addresses, cities).
Sequential WU station iteration Many PWS stations go offline or report null. Loop until finding one with valid temperature.
Open-Meteo as PWS validator ± 10 °F divergence threshold catches malfunctioning stations.
BirdWeather Species.stations path Root stations query returns HTTP 500. Nested field uses different resolver and works reliably.
Async bird photo backfill eBird returns no photos; BirdWeather sometimes lacks thumbnails. iNat taxa autocomplete provides photos. Batched in groups of three to avoid rate limiting.
iNat conservation data over IUCN API iNaturalist already embeds conservation status. Pragmatic over complex.
Open-Meteo Historical over Daymet Global coverage (Daymet is CONUS only). 85-year record. No API key. Daily resolution with multiple reanalysis models.
ERA5-Land for soil variables 0.1° resolution vs ERA5's 0.25°. Surface-focused model optimized for soil thermal and moisture dynamics.
"Best Match" for climate normals Seamlessly blends IFS 9 km (2017+) with ERA5/ERA5-Land for earlier decades. Avoids model transition artifacts.
Separate Climate History and Soils cards Silo independence. Different models (Best Match vs ERA5-Land), different ecological questions (atmosphere vs below-ground). LLM synthesizes across silos.
iNat month= for Seasonality Collapses interannual variation onto 12-month calendar. Solves episodic observation problem. API does the filtering.
3-month window for Seasonality Current month ± 1 captures shoulder-season transitions without over-broadening.
Biodiversity unfiltered, Seasonality filtered Two cards, same API, different ecological questions. Inventory vs calendar.
30-year monthly summaries cached, raw daily discarded YEA is on-demand; storing 10,950 raw records per coordinate is unnecessary. ecoSPLAT permanent sites will store full daily series separately.
mysqli over PDO Project convention for all Macroscope PHP code.
Vanilla JS, no frameworks No React/Vue build step. Editable in BBEdit. Simplicity over scaffolding.

12. Verified Test Sites

Site Lat Lon Key Characteristics
Canemah (home) 45.3573 −122.6068 Bluff, 23.8° slope, E-facing. Willamette Valley. Urban-edge (USDA FIA returns NoData).
Bellingham, WA 48.75 −122.48 Puget Lowland. 1,285 species. Tests WU station iteration.
Blue Oak Ranch, CA 37.3817 −121.7379 Central CA Foothills. 574 m. Rough coords can hit Open Water.
James/Idyllwild, CA 33.7456 −116.7146 Southern CA Mountains. Tests tight bbox for ecoregion accuracy.

13. Narrative System (Designed, Not Yet Active)

13.1 Concept

A server-side LLM call transforms structured ecological data into naturalist-quality prose for each card. The narrative should read like a field guide — interpreting what slope, aspect, climate zone, and species assemblage mean ecologically, not merely restating the numbers.

13.2 Infrastructure Status

All database infrastructure is in place: the narrative_cache table, narrativeHash(), narrativeCacheGet(), narrativeCacheSet(). CSS for the .synthesis block is styled. The cards.js synthesis section contains an empty hook (line ~1451). No LLM API calls are active.

13.3 Prior Experiments

Local Ollama with GPT-oss:20b successfully produced field guide-quality prose when fed the rich ecological data context. Key insight: "data is everything, and the context is so rich the prose just flows from it." Network issues prevented Claude API integration; Ollama code was later stripped due to timeout issues. The plan is to rebuild the narrative system from scratch.

13.4 Temporal Data Architecture (Planned)

Narrative caching should be organized by natural refresh cycle:

Temporal Class Examples Narrative Behavior
Geological time Elevation, ecoregion, land cover Cache narrative permanently
Climate normals 30-year temperature/precipitation/soil/ET₀ profiles Cache narrative permanently
Climate trend Recent-decade departures from 30-year baseline Cache narrative permanently
Seasonal accumulation iNat species lists (all-time), iNat seasonal (month-filtered) Refresh narrative weekly
Recent activity eBird sightings, BirdWeather detections Generate on demand
Real-time Weather conditions Always fresh, not cached

14. Planned Enhancements

14.1 Near-term

Rebuild narrative system using Claude API (server-side, single call with full data context). Progressive loading: render raw data cards immediately, add narratives when the LLM returns. On-demand narrative generation triggered by user interaction. Admin UI for usage monitoring and settings management. Cross-silo narrative synthesis: the LLM reads all eleven card data silos and produces naturalist-quality ecological interpretation that connects climate history to biodiversity patterns, soil conditions to phenology, and seasonal context to species presence.

14.2 Biodiversity API Expansion

GBIF for historical records and deeper temporal coverage. Map of Life for predicted species ranges.

14.3 UI Enhancements

Plant strata classification via LLM (canopy, shrub, herbaceous, non-vascular). PDF/image export of ecological address card set. Share button with social media card. Batch mode for classroom use. Monthly sparkline or bar chart visualizations for Climate History and Soils cards.

14.4 Data Enrichment

California-specific layers (fire hazard, WHR, CalVeg) when CA coordinate detected. Full 12-month phenological profiles for permanent Macroscope/ecoSPLAT sites (all months queried independently, species month-presence vectors computed).

14.5 ecoSPLAT Integration

The three new data sources (Open-Meteo Historical climate, ERA5-Land soils/ET₀, iNat seasonal) serve dual purposes. For YEA, they compute summary statistics on demand and cache the results. For ecoSPLAT permanent sites, the same APIs can be harvested via cron to build a local climate and phenology database with full daily resolution, analogous to the existing BirdWeather PUC acoustic sensor harvest. A shared PHP library module for Open-Meteo query construction serves both paths. eBird recent observations can similarly be harvested daily per site, treating citizen science observers as a distributed sensor network.


15. Development Conventions

15.1 Code Standards

  • Simplicity over cleverness — readable, maintainable, 200 lines or fewer per file.
  • Minimal changes — never reimplement from scratch without permission.
  • Style consistency — match existing code patterns.
  • Scope discipline — never make unrelated changes.
  • No filename prefixes (new, improved, updated_).
  • Complete files ready for BBEdit, never snippets.
  • File headers in comments: path, filename, change description.
  • Wait for "proceed" after each delivery.

15.2 Module Pattern

PHP uses separate files for sources, parsers, and database logic, with the orchestrator in address_api.php. JavaScript uses the IIFE module pattern (var EcoCards = (function() { ... })();) with a public API via the returned object. CSS is a single file with comment-delimited sections.

15.3 Error Handling

API failures return null — the orchestrator never crashes. The frontend shows "No data" for null sections, never blank cards. curl_multi treats non-2xx/3xx responses as null. Database connection failures return null or empty arrays without halting execution.

15.4 Naming Conventions

Context Convention Examples
PHP functions camelCase parseKoppen, fetchWuCurrent, buildInatUrls
JS functions camelCase renderCards, fetchAddress, buildBirdPhotoLookup
CSS classes kebab-case card-grid, species-thumb, taxon-group-header
Database columns snake_case coord_key, source_status, created_at
API response keys snake_case com_name, sci_name, detection_count
Source keys snake_case inat_plantae, ebird_recent, bw_species, climate_history, climate_trend, soils_et, season_plantae

Limitations

YEA depends on the availability and accuracy of 17 or more external APIs, each with its own coverage gaps, rate limits, and potential for change. US-specific sources (EPA, NLCD, USDA FIA) are unavailable internationally; the global alternatives (RESOLVE, Esri Sentinel-2) are coarser. Weather Underground PWS coverage is uneven, especially outside urban areas. iNaturalist observation density varies dramatically by region — heavily observed areas (Pacific Northwest, California) return rich species lists, while remote or under-observed areas may require maximum radius widening and still return sparse data. BirdWeather coverage depends entirely on PUC station deployment, which is concentrated in North America and Western Europe. The Köppen Climate API is a third-party service with no SLA. The BirdWeather GraphQL API has known instabilities (the root stations query returns HTTP 500). Open-Meteo Historical API responses for 30-year daily queries are large (10,000+ records); server-side computation of monthly summaries adds processing time to first-visit requests, but permanent caching ensures subsequent lookups are instant. ERA5-Land soil data resolution (~11 km) means soil variables represent grid-cell averages that may not capture microtopographic variation (e.g., ridgetop vs. swale) at the scale of a specific address. The iNaturalist month= parameter for seasonal filtering depends on adequate multi-year observation history at the location; recently documented or under-observed areas may have insufficient seasonal data to distinguish phenological patterns. Cache TTL values represent pragmatic compromises between data freshness and API load; they are not based on formal analysis of data change rates.


References

[1] Mapbox (2026). "Mapbox Terrain-RGB v1." https://docs.mapbox.com/data/tilesets/reference/mapbox-terrain-rgb-v1/ (accessed February 19, 2026).

[2] iNaturalist (2026). "iNaturalist: A Community for Naturalists." https://www.inaturalist.org (accessed February 19, 2026).

[3] Sullivan, B. L., Wood, C. L., Iliff, M. J., Bonney, R. E., Fink, D., & Kelling, S. (2009). "eBird: A Citizen-Based Bird Observation Network in the Biological Sciences." Biological Conservation, 142(10), 2282–2292.

[4] Hamilton, M. P. (2026). "Canemah Nature Laboratory." https://canemah.org (accessed February 19, 2026).

[5] Peel, M. C., Finlayson, B. L., & McMahon, T. A. (2007). "Updated World Map of the Köppen-Geiger Climate Classification." Hydrology and Earth System Sciences, 11, 1633–1644. https://doi.org/10.5194/hess-11-1633-2007

[6] Dinerstein, E., Olson, D., Joshi, A., Vynne, C., Burgess, N. D., Wikramanayake, E., et al. (2017). "An Ecoregion-Based Approach to Protecting Half the Terrestrial Realm." BioScience, 67(6), 534–545. https://doi.org/10.1093/biosci/bix014

[7] Karra, K., Kontgis, C., Statman-Weil, Z., Mazzariello, J. C., Mathis, M., & Brumby, S. P. (2021). "Global Land Use / Land Cover with Sentinel-2 and Deep Learning." 2021 IEEE International Geoscience and Remote Sensing Symposium IGARSS, 4704–4707. https://doi.org/10.1109/IGARSS47720.2021.9553499

[8] Omernik, J. M. (1987). "Ecoregions of the Conterminous United States." Annals of the Association of American Geographers, 77(1), 118–125.

[9] Omernik, J. M. & Griffith, G. E. (2014). "Ecoregions of the Conterminous United States: Evolution of a Hierarchical Spatial Framework." Environmental Management, 54(6), 1249–1266. https://doi.org/10.1007/s00267-014-0364-1

[10] Dewitz, J. (2023). "National Land Cover Database (NLCD) 2021 Products." U.S. Geological Survey data release. https://doi.org/10.5066/P9JZ7AO3

[11] USDA Forest Service (2026). "FIA Forest Atlas — Forest Type Groups, CONUS." U.S. Forest Service, Forest Inventory and Analysis Program. https://imagery.geoplatform.gov (accessed February 19, 2026).

[12] The Weather Company (2026). "Weather Underground API." https://www.wunderground.com/member/api-keys (accessed February 19, 2026).

[13] Open-Meteo (2026). "Open-Meteo Free Weather API." https://open-meteo.com (accessed February 19, 2026).

[14] Sullivan, B. L., Aycrigg, J. L., Barry, J. H., Bonney, R. E., Bruns, N., Cooper, C. B., et al. (2014). "The eBird Enterprise: An Integrated Approach to Development and Application of Citizen Science." Biological Conservation, 169, 31–40. https://doi.org/10.1016/j.biocon.2013.11.003

[15] Scribe Labs (2026). "BirdWeather: A Living Library of Bird Vocalizations." https://www.birdweather.com (accessed February 19, 2026).

[16] Kahl, S., Wood, C. M., Eibl, M., & Klinck, H. (2021). "BirdNET: A Deep Learning Solution for Avian Diversity Monitoring." Ecological Informatics, 61, 101236. https://doi.org/10.1016/j.ecoinf.2021.101236

[17] Zippenfenig, P. (2023). "Open-Meteo.com Weather API." Zenodo. https://doi.org/10.5281/ZENODO.7970649

[18] Hersbach, H., Bell, B., Berrisford, P., Biavati, G., Horányi, A., Muñoz Sabater, J., Nicolas, J., Peubey, C., Radu, R., Rozum, I., Schepers, D., Simmons, A., Soci, C., Dee, D., & Thépaut, J-N. (2023). "ERA5 Hourly Data on Single Levels from 1940 to Present." ECMWF, Copernicus Climate Change Service. https://doi.org/10.24381/cds.adbb2d47

[19] Muñoz Sabater, J. (2019). "ERA5-Land Hourly Data from 2001 to Present." ECMWF, Copernicus Climate Change Service. https://doi.org/10.24381/CDS.E2161BAC

[20] Open-Meteo (2026). "Historical Weather API." https://open-meteo.com/en/docs/historical-weather-api (accessed February 19, 2026).


Document History

Version Date Changes
0.1 2026-02-19 Initial draft from project study session
1.0 2026-02-19 CNL style guide compliance; formal references; abstract; AI disclosure
1.1 2026-02-19 Three new cards: Climate History, Soils & Water Balance, Seasonality. Open-Meteo Historical API endpoints. iNaturalist month-filtered seasonal queries. Silo independence principle. ecoSPLAT integration pathway. Security sanitization (server paths, hostnames). References [17–20] added.

Cite This Document

Michael P. Hamilton, Ph.D. (2026). "Your Ecological Address (YEA) — System Specification." Canemah Nature Laboratory Technical Note CNL-TN-2026-025. https://canemah.org/archive/CNL-TN-2026-025

BibTeX

@techreport{hamilton2026your, author = {Hamilton, Michael P., Ph.D.}, title = {Your Ecological Address (YEA) — System Specification}, institution = {Canemah Nature Laboratory}, year = {2026}, number = {CNL-TN-2026-025}, month = {february}, url = {https://canemah.org/archive/document.php?id=CNL-TN-2026-025}, abstract = {Your Ecological Address (YEA) is a single-page web application that transforms geographic coordinates into comprehensive ecological profiles by querying 17 or more geospatial and biodiversity APIs in parallel. Given any latitude and longitude on Earth, the system returns a structured ecological identity spanning terrain morphometry, climate classification, multi-decadal climate history, soil thermal regimes and water balance, ecoregion taxonomy, land cover characterization, real-time weather conditions, multi-taxon biodiversity inventories, seasonal phenology, recent avian field observations, and acoustic bird detections. The tool integrates data sources ranging from sub-meter terrain models [1] to 85-year reanalysis climate records [17,18,19,20] and citizen science platforms with hundreds of millions of observations [2,3], unified through a card-based progressive-disclosure interface designed for accessibility. A key architectural principle is silo independence: each data card owns its own API sources, and cross-silo ecological interpretation is delegated to a narrative LLM layer. A MySQL caching layer with source-appropriate time-to-live values manages API rate limits while preserving temporal fidelity. YEA serves as a standalone ecological reference tool, a metadata engine for the SCOPE panoramic photograph database, and a prototype component of the Macroscope integrated environmental observatory platform. This specification documents the complete system architecture, all API endpoints and data contracts, the frontend card system, database schema, caching strategy, and development conventions sufficient for independent reimplementation.} }

Permanent URL: https://canemah.org/archive/document.php?id=CNL-TN-2026-025