CNL-TN-2026-025 Technical Note Viewing v2 — View latest (v4)

Your Ecological Address (YEA) — System Specification

Michael P. Hamilton , Ph.D.
Published: February 19, 2026 Version: 2 This version: February 22, 2026

Your Ecological Address (YEA) — System Specification

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

Document ID: CNL-TN-2026-025 Version: 2.0 Date: February 22, 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 web application that transforms geographic coordinates into comprehensive ecological profiles by querying 15+ geospatial and biodiversity APIs in parallel. Given any latitude and longitude on Earth, the system returns a structured ecological identity spanning terrain morphometry, bedrock geology and stratigraphy, climate classification, multi-decadal climate history, water balance and evapotranspiration, ecoregion taxonomy, land cover characterization, vegetation community classification, conservation-listed species, multi-taxon biodiversity inventories, seasonal phenology, recent avian field observations, and acoustic bird detections. Place context enrichment via Mapbox POI lookup and Wikipedia geosearch provides narrative grounding for named ecological features. An AI narrative system using Anthropic's Claude Haiku generates interpretive prose from three personas — Naturalist, Scientist, and Teacher — with anti-hallucination constraints that restrict all claims to the data profile.

The interface is organized as a field guide with four thematic panels — Identity, Physical Place, Ecological Setting, and Living Systems — plus a Field Notebook panel for AI-generated narratives. Each panel contains cards that display snapshot summaries and expand to full detail via drawer interaction. A modular JavaScript frontend (ten modules on the FG namespace) communicates with a PHP backend using parallel API fetching (curl_multi) and MySQL caching with source-appropriate TTL values organized by temporal ecology: permanent for geological data, weekly for species inventories, six-hour for bird activity, and fifteen-minute for weather conditions.

A privacy-respecting analytics system tracks usage patterns without IP logging or cookies, and an administrative dashboard provides API health monitoring, cache management, and a MapBox globe visualization of all queried locations worldwide. The cache coordinate resolution of three decimal places (~111 m) was chosen to match the coarsest common spatial resolution of the underlying data sources.

YEA serves as a standalone ecological reference tool at yea.earth, a metadata engine for the SCOPE panoramic photograph database, and a prototype component of the Macroscope integrated environmental observatory platform.


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 bedrock geology, what terrain, what vegetation community, what species assemblage. 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 thematic panels with expandable data cards.

1.2 Context

YEA is a component of the Macroscope project at the Canemah Nature Laboratory. It is standalone — with its own header, footer, navigation, and CSS. The application is the homepage of yea.earth. A key secondary use is populating ecological metadata for 400+ panoramic photographs in the SCOPE database.

1.3 Design Philosophy

Six principles guide the system:

  1. Naturalist interpretation over raw data. Data is contextualized, not just displayed. AI narratives interpret ecological relationships.
  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 via drawer interaction.
  4. Graceful degradation. US-only sources (EPA, NLCD, LANDFIRE) are skipped for international coordinates; global alternatives (RESOLVE, Esri Sentinel-2, Macrostrat) are always available.
  5. Data richness over implementation complexity. Multiple 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 Galatea — Mac Mini M4 Pro, 1Gb fiber (production)
Web server Apache 2 (WebMon managed)
Backend PHP 8.3+, mysqli (no PDO)
Database MySQL 8.4+ (managed via phpMyAdmin)
Frontend Vanilla JavaScript (FG namespace), Mapbox GL JS 3.3.0
DEM processing ImageMagick CLI (convert)
Narrative AI Anthropic Claude Haiku 4.5 (server-side)
URL https://yea.earthhttps://canemah.org/projects/ecoADDRESS/
Project root ecoADDRESS/ (under Apache document root)

2.2 File Structure

ecoADDRESS/
├── index.php               — Page shell: search bar, map, results container
├── address_api.php         — Backend orchestrator: validation, caching, API coordination, JSON response
├── narrative_api.php       — On-demand AI narrative generation (Anthropic Claude Haiku)
├── about.php               — About page
├── contact.php             — Contact page
├── sources.php             — Data sources page (public-facing)
├── css/
│   ├── fieldguide.css      — Base styles: typography, color palette, shared patterns
│   ├── layout.css          — Page layout: hero, nav, search, map, controls
│   ├── panels.css          — Panel and card system: headers, bodies, status dots
│   ├── drawers.css         — Drawer expansion, info modals, lightbox overlay
│   ├── species.css         — Species lists, taxon groups, thumbnails, photo backfill
│   └── responsive.css      — Breakpoints at 850px and 500px
├── js/
│   ├── fg-config.js        — Module 1: FG namespace, Mapbox setup, DOM refs, constants, card info
│   ├── fg-analytics.js     — Module 2: Privacy-respecting session tracking, event logging
│   ├── fg-icons.js         — Module 3: Lucide SVG icon library (inline generation)
│   ├── fg-helpers.js       — Module 4: Shared utilities (escaping, formatting, radius labels)
│   ├── fg-species.js       — Module 5: Species list rendering, taxon groups, photo backfill
│   ├── fg-snapshots.js     — Module 6: Snapshot summaries for all cards (compact one-line views)
│   ├── fg-drawers.js       — Module 7: Drawer content builders for all card types
│   ├── fg-search.js        — Module 8: Dual place search (iNaturalist + Mapbox Geocoding)
│   ├── fg-map.js           — Module 9: Map interaction, API calls, coordinate handling
│   └── fg-init.js          — Module 10: Master renderer, panel builders, event handlers, auto-init
├── lib/
│   ├── sources.php         — URL builders, parallel fetch engine (curl_multi), GraphQL client
│   ├── parsers.php         — Parser coordinator: loads sub-parsers, provides parseAll()
│   ├── database.php        — MySQL caching, query logging, event logging, narrative cache
│   ├── place_context.php   — Mapbox POI + Wikipedia geosearch enrichment
│   └── parsers/
│       ├── terrain.php             — parseTerrain(), compassLabel()
│       ├── geology.php             — parseMacrostrat()
│       ├── climate.php             — parseKoppen(), parseClimateArchive()
│       ├── geography.php           — parseReverseGeo(), parseEcoregion(), parseResolveEcoregion()
│       ├── landcover.php           — parseNlcd(), parseEsriLulc(), parseLandfireEvt()
│       ├── landfire_evt_lookup.php — LANDFIRE EVT code-to-name table (1,068 entries)
│       ├── weather.php             — parseWuNearby(), formatWuCurrent(), parseOpenMeteo()
│       ├── biodiversity.php        — parseInatTotal(), parseInatTaxon()
│       ├── birds.php               — parseEbirdRecent(), parseEbirdNotable(),
│       │                             parseBirdWeatherSpecies(), parseBirdWeatherStations()
│       └── conservation.php        — parseConservation()
├── includes/
│   ├── header.php          — Shared HTML head, hero banner, site navigation
│   └── footer.php          — Shared footer, external links
├── admin/                  — Administrative dashboard (password-protected)
│   ├── index.php           — Dashboard home: API health, cache stats, recent queries
│   ├── analytics.php       — Usage analytics: sessions, devices, engagement, referrers
│   ├── globe.php           — MapBox globe visualization of all queried locations
│   ├── globe_data.php      — GeoJSON endpoint for globe (aggregated by coordinate)
│   ├── events_api.php      — POST handler for frontend usage events
│   └── includes/
│       └── header.php      — Admin navigation
├── img/                    — Favicons, hero banner, author photo, logo
├── deprecated/             — Earlier experimental versions (address.js, cards.js, classic.php)
└── docs/                   — Documentation, SQL schema, workplans

2.3 Credential Files (Outside Webroot)

/Library/WebServer/secure/credentials/ecoaddress/
  ai-config.php      — Defines WU_API_KEY, MAPBOX_TOKEN, EBIRD_API_KEY,
                        OPEN_METEO_API_KEY, ANTHROPIC_API_KEY
  ecoaddress.php     — Database credentials: $db_host, $db_name, $db_user, $db_pass

2.4 Request Flow

The primary lookup lifecycle:

  1. User clicks map, searches a place name, enters coordinates, or uses browser geolocation.
  2. fg-map.js calls GET address_api.php?lat={lat}&lon={lon}&sid={session_id}.
  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. PWS temperature is validated against Open-Meteo baseline (±10°F divergence rejection).
  11. Dynamic radius widening runs for iNaturalist (1 → 5 → 10 → 20 km if fewer than five species).
  12. Conservation status queries run at the final iNaturalist radius.
  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. LANDFIRE vegetation type is fetched with 30m grid-snapped coordinates (standalone curl, CONUS only).
  17. Open-Meteo Historical archive is queried for 1991–2025 climate + water balance (cached permanently; skipped if cache hit). Single request with 6 variables feeds both Climate History and Water Balance cards.
  18. iNaturalist seasonal queries (month-filtered) run for all nine taxa with radius widening.
  19. Place context enrichment: Mapbox POI reverse lookup + Wikipedia geosearch + ecoregion Wikipedia fallback.
  20. POI name promotion: if within 200m of a named ecological place (park, reserve, trail), promote to primary identity.
  21. Query is logged with timing, per-source status, user agent, referer, and session ID.
  22. Consolidated JSON is returned to the frontend.
  23. fg-init.js renders field guide panels. Async bird photo backfill begins for species missing thumbnails.
  24. Analytics module sends session_start event and tracks subsequent interactions.

3. Data Sources

YEA integrates 15+ external data sources spanning terrain, geology, climate, climate history, water balance, ecoregion classification, land cover, vegetation community, weather, biodiversity, conservation status, phenology, avian monitoring, and place context. Each source is described below.

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 Macrostrat [21] Bedrock geology, lithology, formation, age Global Vector polygon Permanent
3 Köppen Climate API [5] Climate zone + description Global ~28 km 90 days
4 Mapbox Reverse Geocoding [1] Place name, county, state Global Point Permanent
5 RESOLVE Ecoregions 2017 [6] Realm, biome, ecoregion Global Vector polygon Permanent
6 Esri Sentinel-2 10m LULC [7] 9-class land cover Global 10 m Permanent
7 EPA Omernik Ecoregions [8,9] Levels I–IV US only 1:250K Permanent
8 MRLC NLCD 2021 [10] 20-class land cover CONUS 30 m Permanent
9 LANDFIRE LF2024 EVT [22] Vegetation community (1,068 NatureServe ecological systems) CONUS 30 m Permanent
10 Weather Underground [12] PWS current conditions Global Point 15 min
11 Open-Meteo Pro [13] Modeled weather baseline Global Reanalysis grid 15 min
12 iNaturalist [2] Species counts (9 taxa) Global Point + radius 7 days
13 iNaturalist Conservation [2] Threatened/IUCN-listed species Global Point + radius 7 days
14 eBird API 2.0 [3,14] Recent + notable observations Global Point + radius 6 hours
15 BirdWeather [15,16] Acoustic detections + stations Global (station-dependent) Bounding box 6 hours
16 Open-Meteo Historical Pro [17,18,20] 1991–2025 climate normals + water balance (6 variables) Global 9–25 km Permanent
17 iNaturalist Seasonal [2] Month-filtered species counts (9 taxa, 3-month window) Global Point + radius 7 days
18 Mapbox Search Box [1] Nearby POIs (parks, reserves, landmarks) Global Point + radius Permanent
19 Wikipedia Geosearch [23] Geotagged articles with summaries Global Point + radius Permanent

Removed sources: USDA FIA Forest Atlas (GeoPlatform identify endpoint returns HTTP 400 since Kubernetes migration, February 2026; vegetation type coverage now provided by LANDFIRE EVT at 30m).

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 Macrostrat Geologic Map [21]

https://macrostrat.org/api/v2/geologic_units/map?lat={lat}&lng={lon}&response=long

Returns bedrock geology at multiple map scales. The parser selects the most detailed unit (richest description, narrowest age range) and returns: formation name, lithology (major and minor rock types), stratigraphic name, geologic age (top/bottom in Ma), period, best interval, map color, and source reference. No API key required. CC-BY 4.0 license. Global coverage from 225+ integrated geological survey maps.

3.2.3 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.4 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.5 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.6 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.7 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.8 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.9 LANDFIRE LF2024 Existing Vegetation Type [22]

https://lfps.usgs.gov/arcgis/rest/services/Landfire_LF230/
  US_230EVT/ImageServer/identify
  ?geometry={"x":{lon},"y":{lat},"spatialReference":{"wkid":4326}}
  &geometryType=esriGeometryPoint&returnGeometry=false&f=json

CONUS only. 30 m resolution. Requires User-Agent header. Returns a numeric EVT code (e.g., 7039) that maps to one of 1,068 NatureServe ecological system classifications via a generated PHP lookup table. Each entry provides: ecological system name, lifeform (tree/shrub/herbaceous), physiognomy, group name, order, class, and subclass. Standalone curl call with 30m grid-snapped coordinates (not part of the parallel fetchAll batch) to ensure consistent pixel selection regardless of GPS jitter.

Grid-snapping math: Coordinates are snapped to the center of the nearest 30m LANDFIRE pixel before the API call. lat_step = 30.0 / 111111.0 (~0.00027°); lon_step adjusted by cos(latitude) for meridian convergence. This ensures that GPS jitter within a single pixel always resolves to the same query coordinate and cache key.

3.2.10 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.11 Open-Meteo Pro [13]

https://customer-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
  &apikey={key}

Global modeled weather baseline. Always queried regardless of PWS availability. Requires OPEN_METEO_API_KEY (commercial Pro API subscription).

3.2.12 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.13 iNaturalist Conservation [2]

https://api.inaturalist.org/v1/observations/species_counts
  ?lat={lat}&lng={lon}&radius={km}&threatened=true&per_page=100

Two queries at the final biodiversity radius: (1) threatened=true&per_page=0 for total count of all conservation-listed species (NatureServe + IUCN + state listings), and (2) threatened=true&per_page=100 for full details. Species are grouped by conservation severity: Critically Endangered, Endangered, Vulnerable, Near Threatened, NatureServe Imperiled.

3.2.14 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.15 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.

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

3.2.16 Open-Meteo Historical Pro — Climate Archive [17,18,20]

Unified daily aggregates, 1991–2025 (6 variables):

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

A single request with 6 variables feeds both the Climate History card and the Water Balance card, replacing the original three separate requests (48% API cost reduction). Returns ~12,400 daily records processed server-side into monthly summary statistics via a single-pass parser with dual accumulators:

  • Baseline (1991–2020): 30-year climate normals per month — temperature (mean, high, low), precipitation totals, sunshine hours.
  • Trend (2010–2024): Delta comparison against baseline — warming, drying, wetter, longer frost-free season.
  • Water balance: Monthly precipitation minus ET₀ (FAO Penman-Monteith reference evapotranspiration). Surplus months (recharge) and deficit months (drought stress).
  • Growing degree days: Cumulative from mean temperature using 5°C base.

The "Best Match" model is used by default, seamlessly blending ECMWF IFS (9 km, 2017–present) with ERA5 and ERA5-Land for the earlier record. Requires OPEN_METEO_API_KEY. Results cached permanently — historical normals do not change.

Dropped from v1.1: wind_speed_10m_max (grid-modeled wind is ecologically meaningless), daylight_duration (pure astronomy, computed from latitude), separate ERA5-Land soil temperature/moisture queries (soil variables were found to add complexity without proportionate ecological insight at the screen-display level).

3.2.17 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.12) 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.

The three-month window (current month ± 1) captures species active in the current season, early and late seasonal transitions, and shoulder-season species. Month wrapping is handled in PHP: for January, the query becomes month=12,1,2; for December, month=11,12,1.

3.2.18 Place Context: Mapbox POI + Wikipedia [1,23]

Mapbox Search Box reverse:

https://api.mapbox.com/search/searchbox/v1/reverse
  ?longitude={lon}&latitude={lat}&access_token={token}
  &types=poi&limit=5&language=en

Wikipedia geosearch:

https://en.wikipedia.org/w/api.php
  ?action=query&list=geosearch&gscoord={lat}|{lon}
  &gsradius=2000&gslimit=5&format=json

Wikipedia extracts (for articles found by geosearch):

https://en.wikipedia.org/w/api.php
  ?action=query&prop=extracts&exintro&explaintext
  &pageids={ids}&format=json

Place context enrichment provides narrative grounding. POIs within 200m of ecological categories (parks, reserves, natural areas, trails, campgrounds) can be promoted to primary place identity. Wikipedia articles provide contextual summaries for the narrative AI prompt. A tiered fallback system queries: (1) nearby POIs, (2) nearby Wikipedia articles, (3) Wikipedia article for the RESOLVE ecoregion name.

3.3 Coordinate Transformations

Web Mercator (EPSG:3857) is required by the Esri LULC endpoint:

$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 biodiversity sources (iNaturalist, eBird, BirdWeather) use the same progressive widening pattern:

  1. Initial query at 1 km radius.
  2. If species count is below the threshold (fewer than five species, or three for seasonal), 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. Conservation status queries run after biodiversity widening completes, using the final iNaturalist radius. 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. 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.

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;

Coordinate key format: Lat and lon rounded to three decimal places (~111 m precision), e.g., "45.357,-122.607". This resolution was chosen to match the ecological resolution of the data sources — the finest actual data source is 10m (Esri Sentinel-2 LULC) and the majority are 30m or coarser, while radius-searched biodiversity APIs query in circles measured in kilometers. Two points within ~111m will share a single cache entry, improving cache hit rates without losing meaningful ecological variation.

6.2 lookup_log

Records every query with timing, per-source cache status, and privacy-respecting session metadata.

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,
  user_agent varchar(512) DEFAULT NULL,
  referer varchar(512) DEFAULT NULL,
  session_id char(12) DEFAULT 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

Stores LLM-generated narratives keyed by coordinate and data hash. Multiple narrative tiers (teaser, naturalist, scientist, teacher) accumulate in a single JSON object per coordinate+hash. The data hash is an MD5 of the parsed ecological data excluding weather and eBird (which change too frequently); if the underlying data changes, the hash changes and fresh narratives are generated.

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 usage_events

Frontend interaction tracking for analytics. No IP logging, no cookies, no persistent identifiers.

CREATE TABLE usage_events (
  id int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  session_id char(12) NOT NULL,
  event_type varchar(32) NOT NULL,
  event_data JSON DEFAULT NULL,
  created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  KEY idx_session (session_id),
  KEY idx_type (event_type),
  KEY idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

6.5 Cache TTL Strategy

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

Temporal Class TTL Sources
Geological (permanent) 365 days terrain, macrostrat, ecoregion, resolve_eco, nlcd, esri_lulc, landfire_evt, reverse_geo, place_context
Climate (static dataset) 90 days koppen
Climate normals (permanent) 365 days climate_history, water_balance
Seasonal accumulation 7 days all inat* sources, all season* sources, inat_threatened, inat_conservation
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 — invalidated when source data changes)

7. Frontend Architecture

7.1 Panel Structure

The interface is organized as a field guide with five thematic panels. Each panel (except Identity and Field Notebook) contains expandable data cards.

Panel Subtitle Cards
Identity The identity of this place Place name, coordinates, ecological address summary
Physical Place The abiotic foundation Terrain, Geology, Climate, Current Conditions, Climate History, Water Balance
Ecological Setting Biogeographic context Ecoregion & Biome, Land Cover, Vegetation Type, Conservation Status
Living Systems What lives here Biodiversity, Seasonality, Recent Bird Activity, Acoustic Detections
Field Notebook Ecological interpretation AI-generated narratives from three personas

Panel ordering rationale: The environmental story flows from permanent identity (place, geology, climate zone) through temporal context (climate history, ecoregion, land cover, conditions, water balance) to biological inventory (biodiversity, seasonality, birds, acoustics), culminating in synthesized interpretation (narratives). This mirrors the way a naturalist orients: geology first, climate second, biology third.

7.2 Card States

Each card has three visual states:

  1. Placeholder — displayed before any search. Shows category title and explanatory text.
  2. Snapshot — compact data summary after search. One-line key data value plus source attribution and status indicator (green dot = data received, red dot = error).
  3. Drawer — full detail view on card click. Card expands below the snapshot with all fields, species lists, charts, and interactive elements.

An info button (ℹ) on each card opens a modal explaining the data source, what it shows, and its ecological interpretation. Info content is defined in FG.CARD_INFO in fg-config.js.

7.3 JavaScript Module Architecture

Ten modules load in dependency order on the FG namespace (all 'use strict'):

Load Order Module Responsibility
1 fg-config.js Namespace creation, Mapbox setup, DOM refs, constants, card info definitions, placeholder text, progress messages, CARD_SOURCE_MAP
2 fg-analytics.js Session ID generation (12-char random, tab-scoped), FG.track(event, data), sendBeacon/fetch transport
3 fg-icons.js Lucide SVG icon library — FG.icon(name) returns inline SVG markup
4 fg-helpers.js Shared utilities: FG.esc(), FG.formatNum(), radius labels, taxon display helpers
5 fg-species.js Species list rendering, taxon group headers with representative thumbnails, photo backfill via iNaturalist taxa autocomplete API
6 fg-snapshots.js Snapshot summary builders for all 14 card types
7 fg-drawers.js Drawer content builders for all card types, including species lightbox, eBird sections, BirdWeather sections, climate charts, geology details
8 fg-search.js Dual place search merging iNaturalist Places (reserves, parks, field stations) with Mapbox Geocoding (addresses, cities, POIs), tagged by source
9 fg-map.js Map click handler, coordinate input, geolocation, API fetch orchestration, analytics event emission
10 fg-init.js Master renderer, panel builders, placeholder rendering, card click handlers, info modal, persona narrative handlers

7.4 Field Notebook — AI Narrative System

The Field Notebook panel provides AI-generated ecological narratives from three personas:

Persona Voice Target Audience Length
Naturalist Story-driven, sensory, interpretive prose General public, curious visitors 150–200 words
Scientist Technical, precise, research-oriented with Markdown formatting Graduate students, researchers 200–300 words
Teacher Wonder-driven, age-appropriate, ends with activity prompt Classrooms, field trips, young learners 150–200 words

Additionally, a teaser narrative (50 words maximum, 2 sentences) is generated automatically for the Identity panel, providing a brief data-driven synthesis without requiring the user to click into the Field Notebook.

Anti-hallucination architecture: Every narrative prompt includes the complete ecological data profile as the sole source of truth, with explicit instructions: "Every factual claim must come directly from the data profile below. Do NOT draw on outside knowledge about named places, water bodies, landmarks, or history not in the data." Absent data categories are explicitly flagged so the model does not infer missing information.

Urban-context awareness: The prompt system detects developed/urban land cover and instructs the narrative to interpret the location as urban or suburban ecology — managed landscapes, edge habitats, species navigating human-built environments — rather than describing it as wild.

Model: Anthropic Claude Haiku 4.5 (claude-haiku-4-5-20251001) for all four tiers. Teaser uses 150 max tokens; Naturalist and Teacher use 400; Scientist uses 600. Temperature 0.6.

Caching: Narratives are cached by coordinate + MD5 hash of the ecological data (excluding weather and eBird). Multiple tiers accumulate in a single JSON object. If the underlying data changes (e.g., new species observed, cache refresh), the hash changes and fresh narratives are generated on next request.


8. Analytics System

8.1 Design Principles

The analytics system is privacy-respecting by design: no IP addresses are logged, no cookies are set, and no persistent user identifiers exist. Session identity is a 12-character random alphanumeric string generated client-side in a JavaScript variable that dies when the browser tab closes. Sessions cannot be linked to individuals or across visits.

8.2 Tier 1 — Enriched Lookup Log (Server-Side)

Every API lookup records: coordinates, place name, response time, per-source cache status (hit/cached/error), user agent string, HTTP referer, and session ID. This enables device detection (mobile vs desktop, browser identification) and referrer analysis without any client-side tracking beyond the session parameter.

8.3 Tier 2 — Frontend Event Tracking

The fg-analytics.js module tracks seven event types via POST to events_api.php:

Event Payload Trigger
session_start viewport dimensions, touch capability, language Page load
lookup lat, lon, place name, method (map/search/coords/geolocate) API call
map_click lat, lon Map click
search_select query string, source (inat/mapbox) Search selection
geolocate lat, lon Geolocation button
drawer_open card ID Card expansion
narrative_request persona (naturalist/scientist/teacher) Persona click

Transport uses navigator.sendBeacon when available, falling back to fetch with keepalive: true.

8.4 Administrative Dashboard

Password-protected admin interface at /admin/ providing:

  • Dashboard: API health summary, cache statistics, recent queries with timing
  • Analytics: 14-day session overview, daily activity trends, entry method breakdown, card engagement, narrative persona usage, device/browser distribution, referrer analysis, recent session browser
  • Globe: MapBox globe visualization with satellite-streets basemap, showing all queried locations as GPU-rendered circle layers. Time filter (7d/30d/90d/All). Sidebar with sortable location list. Click-to-fly interaction. Geographically accurate circle size (~111m diameter at street-level zoom matching the cache coordinate resolution).

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

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 with Mapbox Geocoding, tagging results by source.

9.4 Responsive Breakpoints

Breakpoint Behavior
> 850 px Full desktop layout, side-by-side elements where applicable
500–850 px Tablet — single column, reduced padding
< 500 px Mobile — stacked layout, 24px base font, touch-optimized tap targets

10. 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.
Macrostrat for geology Global coverage from 225+ integrated maps, CC-BY license, rich metadata. No API key required.
LANDFIRE EVT replacing USDA FIA 30m NatureServe ecological system classifications vs 250m forest type groups. FIA endpoint broken since Feb 2026.
LANDFIRE 30m grid-snapping GPS jitter across devices can place same location in different 30m pixels. Snap to pixel center ensures cache consistency.
3-decimal coordinate rounding (~111 m) Matches ecological resolution of data sources. Coarsest common resolution is 10m (Esri LULC), most sources are 30m+, and biodiversity APIs search in km-scale radii. Two points within ~111m return identical data from all sources.
Unified climate archive (6 vars) Single request for both Climate History and Water Balance cards. 48% API cost reduction vs three separate requests.
Open-Meteo Pro API Commercial subscription enables higher rate limits and priority access for production use.
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 over IUCN API iNaturalist already embeds conservation status. Pragmatic over complex.
Separate Climate History and Water Balance cards Silo independence. Different ecological questions (atmosphere vs below-ground water budget).
iNat month= for Seasonality Collapses interannual variation onto 12-month calendar. Solves episodic observation problem.
Claude Haiku 4.5 for narratives Cost-effective at scale; data-rich prompts produce high-quality prose even from smaller models.
Anti-hallucination prompt architecture Repeated constraints: "the data is your only source of truth." Explicitly flags absent data categories.
POI name promotion with category filtering Only ecological places (parks, reserves, trails) promoted; schools, businesses, historic buildings blocked.
Tab-scoped session ID (no cookies) Privacy-respecting analytics. Session dies with tab. Cannot link across visits or to individuals.
sendBeacon for analytics Reliable delivery even on page unload. Fallback to fetch with keepalive.
GPU-rendered circle layers for globe MapBox circle layers render on GPU. Handles 10,000+ points without lag. Zero DOM overhead.
Globe circles at true geographic scale circle-pitch-alignment: 'map' renders ~111m footprint at street zoom, honest about data resolution.
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.

11. Verified Test Sites

Site Lat Lon Key Characteristics
Canemah (home) 45.357 −122.607 Bluff, 23.8° slope, E-facing. Willamette Valley. Urban-edge habitat.
Bellingham, WA 48.75 −122.48 Puget Lowland. 1,285 species. Tests WU station iteration.
Blue Oak Ranch, CA 37.382 −121.738 Central CA Foothills. 574 m. Rough coords can hit Open Water.
James/Idyllwild, CA 33.746 −116.715 Southern CA Mountains. Tests tight bbox for ecoregion accuracy.

12. Limitations

YEA depends on the availability and accuracy of 15+ external APIs, each with its own coverage gaps, rate limits, and potential for change. US-specific sources (EPA, NLCD, LANDFIRE) 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 the unified 35-year query (1991–2025, 6 variables) are large (~12,400 daily records); server-side computation of monthly summaries adds processing time to first-visit requests, but permanent caching ensures subsequent lookups are instant. The fetchClimateArchive function implements retry logic (up to 2 attempts with 2-second pause) to handle intermittent timeouts.

LANDFIRE vegetation data covers CONUS only. Locations outside the contiguous US show "CONUS only" for vegetation type. Macrostrat geology has global coverage but resolution varies by region depending on available source maps.

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. The 3-decimal coordinate rounding (~111m) means that two users standing 120 meters apart will receive different ecological profiles; users closer than ~111m will share the same cached result.

Narrative generation depends on the Anthropic API and incurs per-token costs. The anti-hallucination constraints are effective but not infallible — the prompt instructs the model not to fabricate, but LLMs can occasionally introduce plausible-sounding details not present in the source data. The teaser narrative (50-word limit) occasionally exceeds the word count target.


13. Planned Enhancements

13.1 Biodiversity API Expansion

GBIF for historical records and deeper temporal coverage. Map of Life for predicted species ranges. IUCN Red List API for authoritative global conservation status.

13.2 Sensor Integration Layers

Custom API layers for Macroscope sensors, ecoSPLAT 360° panoramas, and small aerial drone imagery. The globe visualization infrastructure already supports multiple GeoJSON layers that could serve as spatial indices for these data types.

13.3 Organelle Convergence Architecture

Integration with the broader Macroscope platform as described in Hamilton (2026), "Organelle Convergence Architecture." Shared spatiotemporal index, event bus, and STRATA synthesis layer connecting YEA, MEO, ecoSPLAT, and Macroscope Nexus. See CNL-FN-2026-026 for architectural details.

13.4 Additional Enhancements

  • Climate projection data to 2050 for forward-looking ecological context
  • "Deep Dive" narratives using Sonnet for integrated media content
  • Species lightbox modals with comprehensive external resource links
  • "Guide" introduction page for new visitors
  • "Data Sources, Organizations & Sponsors" recognition page
  • Batch mode for classroom use
  • PDF/image export of ecological address profile

14. Development Conventions

14.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.

14.2 Module Pattern

PHP uses separate files organized into lib/ (sources, parsers, database, place_context) and lib/parsers/ (domain sub-parsers), with the orchestrator in address_api.php. JavaScript uses the FG namespace pattern — fg-config.js creates window.FG = {}, and subsequent modules attach functions and state to FG. IIFEs are used in modules that need private scope. CSS is split across six files by concern: base typography (fieldguide.css), page layout (layout.css), panel/card system (panels.css), drawer expansion (drawers.css), species display (species.css), and responsive breakpoints (responsive.css).

14.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. The LANDFIRE standalone curl call has an 18-second timeout to accommodate intermittent USGS server slowness. The climate archive fetch implements retry logic with 2-second pauses.

14.4 Naming Conventions

Context Convention Examples
PHP functions camelCase parseKoppen, fetchClimateArchive, buildInatUrls
JS functions camelCase renderFieldGuide, fetchAddress, buildBirdPhotoLookup
JS namespace FG.* FG.track, FG.esc, FG.icon, FG.currentData
CSS classes kebab-case fg-panel, card-drawer, species-thumb, taxon-group-header
Database columns snake_case coord_key, source_status, created_at, session_id
API response keys snake_case com_name, sci_name, detection_count
Source keys snake_case inat_plantae, ebird_recent, bw_species, climate_history, water_balance, landfire_evt, macrostrat

References

[1] Mapbox (2026). "Mapbox GL JS, Terrain-RGB v1, Geocoding v5, Search Box v1." https://docs.mapbox.com/ (accessed February 22, 2026).

[2] iNaturalist (2026). "iNaturalist: A Community for Naturalists." https://www.inaturalist.org (accessed February 22, 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 22, 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., 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., et al. (2021). "Global Land Use / Land Cover with Sentinel-2 and Deep Learning." 2021 IEEE 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

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

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

[14] Sullivan, B. L., Aycrigg, J. L., Barry, J. H., 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 22, 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., et al. (2023). "ERA5 Hourly Data on Single Levels from 1940 to Present." ECMWF, Copernicus Climate Change Service. https://doi.org/10.24381/cds.adbb2d47

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

[21] Peters, S. E., Husson, J. M., & Czaplewski, J. (2018). "Macrostrat: A Platform for Geological Data Integration and Deep-Time Earth Crust Research." Geochemistry, Geophysics, Geosystems, 19(4), 1393–1409. https://doi.org/10.1029/2018GC007467

[22] LANDFIRE (2024). "LANDFIRE LF2024 Existing Vegetation Type (EVT)." U.S. Department of Agriculture and U.S. Department of the Interior. https://landfire.gov (accessed February 22, 2026).

[23] Wikipedia (2026). "MediaWiki API: Geosearch." https://www.mediawiki.org/wiki/API:Geosearch (accessed February 22, 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. References [17–20] added.
2.0 2026-02-22 Complete rewrite reflecting field guide architecture. New: modular JS frontend (10 modules on FG namespace), 6 CSS files, PHP sub-parser architecture, LANDFIRE LF2024 EVT (replacing USDA FIA), Macrostrat geology, conservation status card, place context enrichment (Mapbox POI + Wikipedia), narrative AI system (4 tiers via Anthropic Claude Haiku), admin dashboard with analytics and globe visualization, privacy-respecting session tracking, unified climate archive (6 vars, 48% API cost reduction), 3-decimal coordinate rounding (~111m ecological resolution), POI name promotion, updated file structure, updated database schema (usage_events table, enriched lookup_log). Removed USDA FIA (broken endpoint). Updated all references.

Cite This Document

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

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 web application that transforms geographic coordinates into comprehensive ecological profiles by querying 20+ geospatial and biodiversity APIs in parallel. Given any latitude and longitude on Earth, the system returns a structured ecological identity spanning terrain morphometry, bedrock geology and stratigraphy, climate classification, multi-decadal climate history, water balance and evapotranspiration, ecoregion taxonomy, land cover characterization, vegetation community classification, conservation-listed species, land protection status, multi-taxon biodiversity inventories, seasonal phenology, recent avian field observations, and acoustic bird detections. The interface is organized as a field guide with six thematic panels — Identity, Curated Discovery, Physical Place, Ecological Setting, Living Systems, and Field Notebook — each containing expandable data cards. A Curated Places layer provides enriched ecological profiles for 1,000+ field stations, nature reserves, and research sites across six continents, drawn from OBFS, UC NRS, LTER, NEON, ILTER, and The Nature Conservancy networks. Vision-enabled narratives combine 3D terrain screenshots with ecological data scaffolds, enabling Claude Sonnet to synthesize interpretive prose that integrates spatial reasoning with factual grounding. A modular JavaScript frontend (twelve modules on the `FG` namespace) communicates with a PHP backend using parallel API fetching (`curl\_multi`) and MySQL caching with source-appropriate TTL values. A monitoring widget system displays live sensor data from Tempest weather stations, BirdWeather acoustic monitors, Ecowitt sensors, panoramic cameras (Pannellum), and stratification arrays. An AI enrichment pipeline uses Claude with web\_search to research and populate curated place profiles. A privacy-respecting analytics system tracks usage patterns without IP logging or cookies. **Planned near-term extensions** add an Atmosphere panel (satellite sky imagery from GOES/Himawari geostationary platforms + 72-hour forecast arc) as a fifth panel between Physical Place and Ecological Setting. A four-layer platform architecture is in design: the existing field guide (Guide), a new data science workbench (Lab), a place-based publication layer (Journal), and the existing document archive (Archive). YEA serves as a standalone ecological reference tool at yea.earth, a place-enriched discovery platform for natural areas worldwide, a metadata engine for the SCOPE panoramic photograph database, and a prototype component of the Macroscope integrated environmental observatory platform.} }

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