Your Ecological Address (YEA) — System Specification
Your Ecological Address (YEA) — System Specification
A Multi-Source Ecological Profiling Engine for Any Location on Earth
Document ID: CNL-TN-2026-025
Version: 3.0
Date: March 5, 2026
Author: Michael P. Hamilton, Ph.D.
AI Assistance Disclosure: This technical note was developed with assistance from Claude (Anthropic). The AI contributed to system documentation, API reference compilation, file structure analysis, 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 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.
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.
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, and what conservation designations protect the land. 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 with 3D globe projection), 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 rendered as thematic panels with expandable data cards.
1.2 Context and Evolution
YEA was conceived as a citizen science environmental context engine — a way to provide ecological metadata for any coordinate in the SCOPE panoramic photography database. Within three weeks of initial development it had evolved into a significantly broader platform: a curated natural area discovery system, a vision-enabled AI interpretation engine, and a live monitoring integration layer. Six major capabilities not present in the initial design are now integrated:
- Curated Places — 1,000+ enriched ecological profiles with AI-assisted research narratives
- Vision Narratives — 3D terrain screenshot + data scaffold sent to Claude Sonnet for spatial-ecological interpretation
- Land Protection — PAD-US (CONUS) and WDPA (global) conservation designation overlay
- Monitoring Widgets — live sensor display for Tempest, STRATA, BirdWeather, Ecowitt, Pannellum panoramas
- AI Enrichment Pipeline — automated place research agent using Claude with web_search
- Panorama Integration — Pannellum viewer with OBFS 360-degree video import pipeline
1.3 Design Philosophy
Seven principles guide the system:
- Naturalist interpretation over raw data. Data is contextualized, not just displayed. AI narratives interpret ecological relationships, not inventory them.
- Senior-friendly accessibility. 26px Georgia serif base font, high-contrast warm parchment palette, large tap targets — informed by user feedback.
- Progressive disclosure. Snapshot cards expand to full detail via drawer interaction.
- Graceful degradation. US-only sources (EPA, NLCD, LANDFIRE, PAD-US) are skipped for international coordinates; global alternatives are always available.
- Data richness over implementation complexity. Multiple APIs unified through straightforward parallel fetching and parsing.
- Silo independence. Each data card owns its own API sources. Cross-silo interpretation is delegated to the narrative LLM layer, not embedded in the data pipeline.
- Place-based ecological intelligence. Curated natural areas carry accumulated knowledge — field notes, photographs, sensor streams — that deepens interpretation at known research sites.
2. Architecture
2.1 Deployment
Table 1. Deployment configuration.
| 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) |
| Panorama viewer | Pannellum 2.5.x |
| AI Narrative | Anthropic Claude Haiku 4.5 (text) / Sonnet 4.6 (vision) |
| AI Enrichment | Anthropic Claude Haiku/Sonnet/Opus + web_search |
| URL | https://yea.earth → https://canemah.org/projects/ecoADDRESS/ |
| Project root | ecoADDRESS/ (under Apache document root) |
2.2 File Structure
Core application:
ecoADDRESS/
├── index.php — Page shell: rotating globe, search bar, map, field guide
├── address_api.php — Backend orchestrator: caching, API coordination, JSON response
├── narrative_api.php — Vision+text narrative generation (Haiku + Sonnet)
├── enrich.php — AI enrichment agent (place research + narrative via Claude)
├── about.php / contact.php — Static pages
└── sources.php — Public data sources page
CSS (6 core + admin):
css/
├── fieldguide.css — Base styles: typography, color palette
├── 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
├── gallery.css — Gallery/media grid
├── responsive.css — Breakpoints at 850px and 500px
├── admin.css — Admin dashboard shared styles
├── admin_places.css — Places admin styles
├── monitoring-widgets.css — Live monitoring widget display
├── monitoring-manager.css — Monitoring source management admin
├── media-manager.css — Media management admin
├── sources-manager.css — Place source management
└── categories-manager.css — Category management
JavaScript (12 FG modules + monitoring):
js/
├── fg-config.js — Module 1: FG namespace, Mapbox globe, DOM refs, constants
├── fg-analytics.js — Module 2: Privacy-respecting session tracking
├── fg-icons.js — Module 3: Lucide SVG icon library
├── fg-helpers.js — Module 4: Shared utilities
├── fg-species.js — Module 5: Species list rendering, photo backfill
├── fg-snapshots.js — Module 6: Snapshot summaries for all card types
├── fg-drawers.js — Module 7: Drawer content builders
├── fg-search.js — Module 8: Dual place search (iNat + Mapbox)
├── fg-gallery.js — Module 9: Media gallery for curated places
├── fg-places.js — Module 10: Curated places overlay, Natural Area detail panels
├── fg-map.js — Module 11: Map interaction, terrain, camera transitions
├── fg-init.js — Module 12: Master renderer, panel builders, event handlers
└── monitoring/
├── core.js — Monitoring widget initialization and orchestration
├── mw-tempest.js — Tempest weather station widget
├── mw-strata.js — Stratification array widget
├── mw-birdweather.js — BirdWeather acoustic monitor widget
├── mw-ecowitt.js — Ecowitt sensor widget
├── mw-pano.js — Pannellum panorama widget
└── mw-pano-video.js — Pannellum 360-degree video widget
PHP library (lib/):
lib/
├── sources.php — URL builders, parallel fetch engine (curl_multi)
├── 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
├── places.php — Full CRUD for yea_places schema (v3.1)
├── place_sources.php — Place source management
├── padus.php — Protected Area Database (CONUS land protection)
├── wdpa.php — World Database on Protected Areas (global)
└── 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(), parseOpenMeteo()
├── biodiversity.php — parseInatTotal(), parseInatTaxon()
├── birds.php — parseEbirdRecent(), parseBirdWeatherSpecies()
└── conservation.php — parseConservation()
Admin (admin/):
admin/
├── index.php — Dashboard: API health, cache stats, recent queries
├── analytics.php — Usage analytics: sessions, devices, engagement
├── globe.php — MapBox globe visualization of all queried locations
├── globe_data.php — GeoJSON endpoint for globe
├── events_api.php — POST handler for frontend usage events
├── monitoring.php — Cross-place monitoring instruments overview
├── places.php — Places management
├── people.php — People management
├── organizations.php — Organizations management
├── media.php — Media management
├── media-browse.php — Media browser
├── types.php — Place type management
├── categories.php — Category management
└── includes/header.php — Admin navigation
Panorama tools:
pano-add.php / pano-import.php — Still panorama upload and import
pano-video-add.php / pano-video-import.php — Video panorama upload and import
import-obfs-panos.php — Bulk OBFS Virtual Field panorama import
lib/pannellum.js / pannellum.css — Pannellum equirectangular viewer
videojs-pannellum-plugin.js — 360-degree video support
video_min.js / video-js_min.css — Video.js player
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 ecological address lookup lifecycle:
- User clicks map, searches a place name, enters coordinates, or uses browser geolocation.
fg-map.jscallsGET address_api.php?lat={lat}&lon={lon}&sid={session_id}.- Orchestrator validates input and determines CONUS membership (US bounding box check).
- Mapbox tile coordinates computed for zoom level 14.
- MySQL cache checked for existing responses (
cacheGetAll). - URLs built only for uncached sources (
buildUrlsinsources.php). - All uncached sources fetched in parallel via
curl_multi. - New responses cached (
cacheSetAll). All responses parsed (parseAll). - Sequential Weather Underground station iteration finds active PWS within 5 miles; validated against Open-Meteo ±10°F baseline.
- Dynamic radius widening for iNaturalist (1→5→10→20 km), eBird (same cascade), BirdWeather (bounding box).
- Conservation status queries run at final iNaturalist radius.
- LANDFIRE EVT fetched with 30m grid-snapped coordinates (CONUS only).
- Open-Meteo Historical archive queried for 1991–2025 climate + water balance (6 variables, permanent cache).
- iNaturalist seasonal queries (month-filtered, 3-month window) run for all nine taxa.
- PAD-US (CONUS) and WDPA (global) queried for land protection status.
- Place context enrichment: Mapbox POI + Wikipedia geosearch + ecoregion fallback. POI name promotion within 200m of ecological categories.
- Nearby curated places from
yea_placeschecked (Haversine proximity query). - Query logged with timing, per-source status, user agent, referer, session ID.
- Consolidated JSON returned to frontend.
fg-init.jsrenders field guide panels including Curated Discovery panel. Async bird photo backfill begins.
3. Data Sources
3.1 Source Summary
Table 2. External data sources integrated by YEA.
| # | Source | Data | Scope | Cache TTL |
|---|---|---|---|---|
| 1 | Mapbox Terrain-RGB DEM [1] | Elevation, slope, aspect | Global (~9.5m) | Permanent |
| 2 | Macrostrat [19] | Bedrock geology, lithology, formation, age | Global | Permanent |
| 3 | Köppen Climate API [5] | Climate zone + description | Global (~28km) | 90 days |
| 4 | Mapbox Reverse Geocoding [1] | Place name, county, state | Global | Permanent |
| 5 | RESOLVE Ecoregions 2017 [6] | Realm, biome, ecoregion | Global | Permanent |
| 6 | Esri Sentinel-2 10m LULC [7] | 9-class land cover | Global (10m) | Permanent |
| 7 | EPA Omernik Ecoregions [8,9] | Levels I–IV | US only | Permanent |
| 8 | MRLC NLCD 2021 [10] | 20-class land cover | CONUS (30m) | Permanent |
| 9 | LANDFIRE LF2024 EVT [20] | 1,068 NatureServe ecological systems | CONUS (30m) | Permanent |
| 10 | Weather Underground [12] | PWS current conditions | Global (point) | 15 min |
| 11 | Open-Meteo Pro [13] | Modeled weather baseline | Global | 15 min |
| 12 | iNaturalist [2] | Species counts (9 taxa) | Global | 7 days |
| 13 | iNaturalist Conservation [2] | Threatened/IUCN-listed species | Global | 7 days |
| 14 | eBird API 2.0 [3,14] | Recent + notable observations | Global | 6 hours |
| 15 | BirdWeather GraphQL [15,16] | Acoustic detections + stations | Station-dependent | 6 hours |
| 16 | Open-Meteo Historical Pro [17,18] | 1991–2025 climate normals + water balance (6 vars) | Global | Permanent |
| 17 | iNaturalist Seasonal [2] | Month-filtered species counts (3-month window) | Global | 7 days |
| 18 | Mapbox Search Box [1] | Nearby POIs (parks, reserves, landmarks) | Global | Permanent |
| 19 | Wikipedia Geosearch [21] | Geotagged articles with summaries | Global | Permanent |
| 20 | PAD-US 3.0 [11] | Federal/state/local/tribal protected areas | CONUS | Permanent |
| 21 | WDPA (UNEP-WCMC) [11] | Internationally designated protected areas | Global | Permanent |
Removed: 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 RGB channels. Elevation decoded as: −10000.0 + ((R × 256 × 256 + G × 256 + B) × 0.1), yielding 0.1m precision. Slope and aspect computed from a 3×3 pixel neighborhood gradient using ImageMagick CLI. Requires MAPBOX_TOKEN.
3.2.2 Macrostrat Geologic Map [19]
https://macrostrat.org/api/v2/geologic_units/map?lat={lat}&lng={lon}&response=long
Returns bedrock geology at multiple map scales. Parser selects the most detailed unit and returns: formation name, lithology, 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 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. The tight bounding box (± 0.01°) is critical for accuracy at ecotone boundaries. No API key required.
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&f=json
Requires Web Mercator projection. Nine land cover classes. 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 returns all four Omernik levels in a single query. The tight bounding box (± 0.01°) prevents 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 30m resolution. No API key required.
3.2.8 LANDFIRE LF2024 Existing Vegetation Type [20]
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, 30m resolution. Requires User-Agent header. Returns a numeric EVT code mapping to one of 1,068 NatureServe ecological system classifications. Standalone curl call with 30m grid-snapped coordinates (not part of the parallel fetchAll batch) to ensure consistent pixel selection.
Grid-snapping: Coordinates are snapped to the center of the nearest 30m pixel before the API call. lat_step = 30.0 / 111111.0 (~0.00027°); lon_step adjusted by cos(latitude). This ensures GPS jitter within a single pixel always resolves to the same query coordinate and cache key.
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. Orchestrator iterates through up to five nearest stations until one reports non-null temperature. PWS data is validated against the Open-Meteo baseline; divergence exceeding ±10°F triggers station rejection.
3.2.10 Open-Meteo Pro [13]
https://customer-api.open-meteo.com/v1/forecast
?latitude={lat}&longitude={lon}
¤t=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.
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 queried independently: Plantae, Fungi, Aves, Mammalia, Reptilia, Amphibia, Insecta, Arachnida, Mollusca. Plants return per_page=20; others return per_page=10. A total species count query (no taxon filter) is also made. No API key required.
3.2.12 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) count only, (2) full details up to 100 species. Results grouped by conservation severity: Critically Endangered, Endangered, Vulnerable, Near Threatened, NatureServe Imperiled.
3.2.13 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.14 BirdWeather GraphQL [15,16]
POST to https://app.birdweather.com/graphql. No API key required.
{
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 }
}
}
Note: 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 and works reliably. BirdWeather InputLocation uses {lat, lon} (not {lat, lng}).
3.2.15 Open-Meteo Historical Pro — Climate Archive [17,18]
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&precipitation_unit=inch
&timezone=auto&apikey={key}
A single request with 6 variables feeds both the Climate History card and the Water Balance card (48% API cost reduction vs. three separate requests). 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.
- Trend (2010–2024): Delta comparison against baseline — warming, drying, wetter, longer frost-free season.
- Water balance: Monthly precipitation minus ET₀ (FAO Penman-Monteith). Surplus and deficit months.
- Growing degree days: Cumulative from mean temperature using 5°C base.
Results cached permanently. Requires OPEN_METEO_API_KEY.
3.2.16 iNaturalist Seasonal [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}]
The month= parameter accepts comma-separated month numbers and returns observations from those calendar months across all years, collapsing interannual variation onto a 12-month phenological window. Month wrapping handled in PHP: for January, the query becomes month=12,1,2.
3.2.17 Place Context: Mapbox POI + Wikipedia [1,21]
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
POIs within 200m of ecological categories (parks, reserves, natural areas, trails, campgrounds) can be promoted to primary place identity. A tiered fallback queries: (1) nearby POIs, (2) nearby Wikipedia articles, (3) Wikipedia article for the RESOLVE ecoregion name.
3.2.18 PAD-US and WDPA [11]
PAD-US 3.0 (CONUS): Queried via ArcGIS MapServer identify endpoint. Returns federal, state, local, and tribal protected area designations, managing agency, GAP status (1–4), and public access. No API key required.
WDPA (global): Queried for non-CONUS coordinates and as a supplemental layer. Returns IUCN category, designation type, status, and managing authority for internationally designated protected areas. Both sources cached permanently.
4. Dynamic Radius Widening
All biodiversity sources (iNaturalist, eBird, BirdWeather) use the same progressive widening pattern:
- Initial query at 1 km radius.
- If species count is below threshold (<5 species, or <3 for seasonal), widen progressively: 1→5→10→20 km.
- Accept the first radius meeting the threshold, or accept the 20 km result.
- BirdWeather uses a bounding box computed from
radius_km / 111.1latitude offset rather than a true radius parameter. - Conservation status queries run after biodiversity widening completes, using the final iNaturalist radius.
The final radius used is recorded in the JSON response and displayed in the UI.
5. Weather Validation
Personal weather stations (PWS) from Weather Underground can report erroneous data. YEA implements a multi-stage validation strategy:
- Open-Meteo is always queried as a global modeled baseline.
- WU stations are accepted only within 5 miles of the query point.
- Orchestrator iterates sequentially through up to 5 nearest stations until one reports non-null temperature.
- PWS temperature is compared against the Open-Meteo baseline; divergence exceeding ±10°F triggers station rejection.
- On rejection or absence of a valid PWS, modeled Open-Meteo data is used as fallback, 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 3 decimal places (~111m precision), e.g., "45.357,-122.607". Binary sources (terrain PNG) stored base64-encoded.
6.2 lookup_log
Records every query with timing, per-source cache status, and privacy-respecting session metadata. No IP addresses stored.
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 persona tiers accumulate in a single JSON object per coordinate+hash. The data hash is an MD5 of parsed ecological data excluding weather and eBird; data changes invalidate the cache.
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. No IP, 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
Table 3. Cache expiration organized by temporal behavior of each source.
| Temporal Class | TTL | Sources |
|---|---|---|
| Geological (permanent) | 365 days | terrain, macrostrat, ecoregion, resolve_eco, nlcd, esri_lulc, landfire_evt, reverse_geo, place_context, padus, wdpa |
| Climate (static dataset) | 90 days | koppen |
| Climate normals | 365 days | climate_archive (historical normals do not change) |
| 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 (invalidated on data hash change) |
7. Frontend Architecture
7.1 Panel Structure
Table 4. Field guide panel organization.
| Panel | Subtitle | Cards |
|---|---|---|
| Identity | The identity of this place | Place name, coordinates, ecological summary, AI teaser |
| Curated Discovery | Natural areas near this location | Network badges, nearby place cards, distance/description |
| 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, Land Protection |
| Living Systems | What lives here | Biodiversity, Seasonality, Recent Bird Activity, Acoustic Detections |
| Field Notebook | Ecological interpretation | Naturalist, Scientist, Teacher AI narratives (vision-enabled) |
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 to an unfamiliar place.
Natural Area Detail Panel: When a curated place is selected from the Curated Discovery panel, a full-width Natural Area detail panel replaces the standard field guide. It contains: identity header, site abstract, monitoring widgets (live sensor feeds), media gallery, Pannellum photopoints viewer, field log entries, associated people/staff, and source links. Rendered by fg-places.js.
7.2 Map: Globe and 3D Visualization
The map opens as a rotating globe (Mapbox GL JS globe projection) that spins slowly until a location is queried. On first lookup, the globe transitions to a satellite-streets 3D terrain view. Four map controls are provided:
- 3D/Nadir toggle — switches between oblique 3D (60° pitch, −15° bearing) and straight-down nadir view.
- Orbit mode — slow continuous bearing rotation for cinematic exploration; stops on user interaction.
- Labels toggle — shows or hides Mapbox place names and road labels.
- Natural Area pins — shows or hides curated place markers on the map.
Globe zoom is computed from container dimensions using logarithmic scaling so the globe fits at all responsive breakpoints. Terrain DEM (exaggeration 1.3) loads on first 3D perspective activation.
7.3 JavaScript Module Architecture
Table 5. JavaScript module responsibilities and load order.
| # | Module | Responsibility |
|---|---|---|
| 1 | fg-config.js |
FG namespace, Mapbox globe setup, DOM refs, constants, CARD_SOURCE_MAP, CONUS_ONLY_CARDS |
| 2 | fg-analytics.js |
Session ID generation (12-char, tab-scoped), FG.track(event, data), sendBeacon/fetch |
| 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, photo backfill via iNaturalist taxa API |
| 6 | fg-snapshots.js |
Snapshot summary builders for all 15 card types |
| 7 | fg-drawers.js |
Drawer content builders, species lightbox, climate charts, geology details, land protection |
| 8 | fg-search.js |
Dual place search merging iNaturalist Places + Mapbox Geocoding |
| 9 | fg-gallery.js |
Media gallery grid for curated place photos and photopoints |
| 10 | fg-places.js |
Curated places overlay, proximity detection, Natural Area detail panels, network badges |
| 11 | fg-map.js |
Map click, coordinate input, geolocation, API fetch orchestration, terrain transitions |
| 12 | fg-init.js |
Master renderer, panel builders, placeholder rendering, card click handlers, info modal |
Load order matters: fg-config.js creates window.FG = {} and the Mapbox map instance; all subsequent modules attach to FG. fg-init.js must load last. Monitoring modules (core.js, mw-*.js) load after fg-init.js.
7.4 Card States
Each card has three visual states:
- Placeholder — displayed before any search. Shows category title and descriptive text.
- Snapshot — compact data summary after search. One-line key value, source attribution, and status indicator (green dot = data received, red dot = error).
- Drawer — full detail on click. Card expands below snapshot with all fields, species lists, charts, and interactive elements.
CARD_SOURCE_MAP in fg-config.js maps each card ID to the source_status keys it depends on, driving the status indicators. CONUS_ONLY_CARDS marks cards (vegetation) that are skipped outside the contiguous US.
8. AI Systems
8.1 Field Notebook Narratives
Table 6. AI narrative personas and configuration.
| Persona | Voice | Target Audience | Model | Max Tokens |
|---|---|---|---|---|
| Teaser | Brief 2-sentence data-driven synthesis | Identity panel, all users | Haiku 4.5 | 150 |
| Naturalist | Story-driven, sensory, interpretive prose | General public, visitors | Haiku 4.5 / Sonnet 4.6 (vision) | 400 |
| Scientist | Technical, research-oriented, Markdown formatted | Researchers, grad students | Haiku 4.5 / Sonnet 4.6 (vision) | 600 |
| Teacher | Wonder-driven, age-appropriate, ends with activity prompt | Classrooms, field trips | Haiku 4.5 / Sonnet 4.6 (vision) | 400 |
Temperature 0.6 for all personas.
8.2 Vision-Enabled Narratives
When the user requests a narrative persona, the frontend captures a screenshot of the current 3D terrain view (Mapbox getCanvas().toDataURL()) and sends it alongside the full ecological data scaffold to narrative_api.php. If an image is present, the API uses Claude Sonnet 4.6 with a vision-enabled message that includes the terrain image as a base64-encoded image block.
The architecture has three components: vision provides spatial pattern recognition of the rendered landscape; scaffold provides factual grounding from 20+ scientific databases; persona places the model in a specific interpretive frame. The resulting narrative integrates observations that exist in neither the image alone nor the data alone but emerge from their intersection. This is the "tricorder architecture" first described in Hamilton (2026) [22].
Anti-hallucination constraints: The system prompt instructs the model that every factual claim must come directly from the ecological data profile. Absent data categories are explicitly flagged. For vision calls, the model may describe what it sees in the terrain image but is instructed not to name specific landmarks, water bodies, or historical features not in the data scaffold.
Urban-context awareness: Developed/urban land cover triggers an alternative prompt frame orienting the narrative toward urban ecology — managed landscapes, edge habitats, species navigating human-built environments.
Curated place enrichment: If the coordinate falls within a curated place, the prompt receives the site_abstract, stewardship description, and history context from the yea_places record, providing narrative grounding for known research sites.
8.3 AI Enrichment Pipeline (enrich.php)
Admin-only tool for populating curated place profiles. Three action modes:
- research — calls Claude (configurable model) with
web_searchenabled to autonomously research a place and populate all enrichment fields:site_abstract,place_description,stewardship_description,history_description,facilities_description,access_description,established_date,area_acres,elevation_range,wikipedia_url,website. - narrative — generates a curated narrative from Phase 1 enrichment data combined with the ecological address at the place's coordinates. Stored in the
curated_narrativefield. - save — targeted update of specific enrichment fields.
Allowed models: claude-haiku-4-5-20251001, claude-sonnet-4-5-20250929, claude-opus-4-5-20250918, ollama:gpt-oss:20b. Model specified as a query parameter with validation against an explicit allowlist; defaults to Sonnet if an unrecognized model is requested.
Queue view: Lists all places ordered by enrichment status — unenriched places appear first, enabling systematic batch enrichment workflows.
8.4 Narrative Caching
Narratives are cached by coordinate + MD5 hash of the ecological data (excluding weather and eBird). Multiple persona tiers accumulate in a single JSON object per coordinate+hash. If underlying data changes — new species observed, new conservation listing, cache refresh — the hash changes and fresh narratives are generated on next request. Cache TTL is 30 days.
9. Curated Places System
9.1 Overview
The Curated Places layer provides enriched ecological profiles for 1,000+ natural areas, field stations, and research sites. Source networks include OBFS (Organization of Biological Field Stations), UC Natural Reserve System, LTER (Long-Term Ecological Research), NEON (National Ecological Observatory Network), ILTER (International Long-Term Ecological Research), and The Nature Conservancy. These places carry accumulated ecological knowledge — site abstracts, conservation narratives, historical context, facilities, photopoints, 360-degree panoramas, and live monitoring sensor feeds — that deepens interpretation far beyond what coordinate-only API queries can provide.
9.2 Database Schema (yea_places v3.1)
yea_places — Core place records: name, slug, lat, lon, radius_km, status (draft/published/archived), category, type_id, organization_id, country, state_province, elevation_m, area_acres, established_date, site_abstract, wikipedia_url, website, place_description, stewardship_description, history_description, facilities_description, access_description, curated_narrative, badge_path, elevation_range, created_at, updated_at.
yea_photopoints — Marked camera positions: place_id FK, name, description, lat, lon, elevation_m, bearing, pano_type (360/flat/video), status, sort_order.
yea_media — Photos and panoramic images: place_id FK, photopoint_id FK, type (photo/pano/video/audio), filename, title, caption, taxon_id, category, tags (JSON), file_size, width, height, taken_at, author, license, sort_order, status.
yea_people — Associated researchers and stewards: name, slug, title, affiliation, orcid, email, bio, role_description, photo_filename.
yea_monitoring_sources — Linked sensor instruments: place_id FK, name, type (tempest/strata/birdweather/ecowitt/pano/pano_video), class (physical/virtual/human), platform_id, config (JSON), status (active/seasonal/inactive/planned/decommissioned), notes.
Supporting tables: yea_tags, yea_field_log, yea_person_organizations, yea_place_sources.
9.3 Proximity Detection
findNearbyPlaces($lat, $lon) uses the Haversine formula for point geometry. Returns all published places where the query coordinate falls within the place's own radius_km, ordered by distance. Results are included in the address_api.php response and drive the Curated Discovery panel and Natural Area Detail panel activation.
9.4 Frontend: Curated Discovery Panel
Rendered by fg-places.js and inserted after the Identity panel. Displays network badges (OBFS, UC NRS, LTER, NEON, ILTER, TNC) for nearby places, place cards with name, network, distance, and brief description, and click interaction that opens the Natural Area Detail panel.
The Natural Area Detail Panel is a full-width replacement view containing: identity header with coordinates and category, site abstract, monitoring widgets (live sensor feeds for configured instruments), media gallery, Pannellum panorama viewer for photopoints, field log (recent observations), associated researchers/staff, and source/citation links. Breadcrumb navigation returns to the standard field guide.
10. Monitoring Widgets
10.1 Architecture
The monitoring widget system displays live sensor data within the Natural Area Detail Panel for curated places that have configured monitoring sources. Each widget type is a self-contained module (mw-*.js + mw-*.php) following a consistent pattern: the PHP backend fetches and formats data from the sensor platform; the JS module renders the display widget; core.js orchestrates initialization.
10.2 Widget Types
Table 7. Monitoring widget modules.
| Widget | Sensor Platform | Data | Notes |
|---|---|---|---|
| mw-tempest | WeatherFlow Tempest | Temperature, humidity, pressure, wind, rain, lightning, UV | REST API via platform_id (station ID) |
| mw-strata | Canemah STRATA array | Stratified temperature/humidity at multiple canopy heights | Custom hardware; vertical profile visualization |
| mw-birdweather | BirdWeather PUC | Recent acoustic detections, species with confidence scores | GraphQL API, same source as address_api |
| mw-ecowitt | Ecowitt GW series | Temperature, humidity, soil moisture, leaf wetness, rain | REST API; supports multi-channel sensors |
| mw-pano | Pannellum viewer | Interactive equirectangular panorama display | Static image; uses photopoint lat/lon/bearing |
| mw-pano-video | Pannellum + Video.js | 360-degree video playback with equirectangular projection | videojs-pannellum-plugin.js bridge |
10.3 Panorama Import Pipeline
Three import tools handle panoramic content:
- pano-add.php / pano-import.php — upload single or batch still panoramas. Validates equirectangular format, generates thumbnails, creates media records linked to photopoints.
- pano-video-add.php / pano-video-import.php — upload and configure 360-degree video files. Associates with photopoints; served via Video.js + Pannellum plugin.
- import-obfs-panos.php — bulk import tool for the OBFS Virtual Field Project archive. Imports 360-degree panoramas from 33 biological field stations (457 panoramas from the 2020–2022 Virtual Field seasonal capture program).
11. Analytics System
11.1 Design Principles
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 that dies when the browser tab closes. Sessions cannot be linked to individuals or across visits.
11.2 Frontend Event Tracking
Table 8. Analytics events tracked by fg-analytics.js.
| 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 |
place_view |
place_id, place_name | Natural Area detail panel open |
Transport uses navigator.sendBeacon when available, falling back to fetch with keepalive: true.
11.3 Administrative Dashboard
Password-protected admin interface at /admin/ providing:
- Dashboard — API health summary, cache statistics, recent queries with per-source timing.
- Analytics — 14-day session overview, daily activity trends, entry method breakdown, card engagement heatmap, narrative persona usage, device/browser distribution, referrer analysis.
- Globe — MapBox globe with satellite-streets basemap showing all queried locations as GPU-rendered circle layers (~111m diameter, matching cache coordinate resolution). Time filter (7d/30d/90d/All). Click-to-fly.
- Places admin — full CRUD for
yea_placesschema, media management, people, organizations, monitoring sources, enrichment queue. - Monitoring — cross-place view of all monitoring instruments, filterable by class (physical/virtual/human) and status.
12. UI Design Specifications
12.1 Color Palette (Warm Parchment)
Table 9. UI color palette.
| 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 |
| Card hover border | #7a8c5a |
12.2 Typography
| Element | Value |
|---|---|
| Font family | Georgia, 'Times New Roman', serif |
| Base font size | 26px (bumped for senior accessibility) |
| Mobile base | 24px |
| Line height | 1.7 |
| Coordinate display | 'SF Mono', 'Fira Code', Consolas, monospace |
| Card titles | 1.1rem, bold, uppercase, letter-spacing 0.04em |
12.3 Responsive Breakpoints
| Breakpoint | Behavior |
|---|---|
| > 850px | Full desktop layout, side-by-side elements where applicable |
| 500–850px | Tablet — single column, reduced padding |
| < 500px | Mobile — stacked layout, 24px base font, touch-optimized tap targets |
13. Key Technical Decisions
Table 10. Key technical decisions and rationale.
| Decision | Rationale |
|---|---|
| Vision-enabled narratives (Sonnet 4.6) | Terrain images allow spatial reasoning that pure data cannot provide. Dense data scaffolds produce inventory prose without perceptual grounding ("the Attenborough problem"). Vision + data + persona yields genuine interpretive synthesis [22]. |
| Two-tier narrative model (Haiku text / Sonnet vision) | Cost optimization. Text-only narratives use Haiku. Vision calls requiring spatial reasoning use Sonnet. |
fg-places.js as standalone 88K module |
Curated places functionality is architecturally independent from the ecological address lookup. Isolating in fg-places.js allows maintenance without touching the 11 core field guide modules. |
| Land Protection as separate card | PAD-US/WDPA data is independent of biodiversity and conservation status. Silo independence: each card owns its API sources. |
| PAD-US for CONUS, WDPA for global | PAD-US has the most granular US coverage. WDPA covers international sites. Both cached permanently — designations rarely change. |
| Monitoring widgets in Natural Area Detail panel only | Live sensor feeds are place-specific and require configured monitoring_sources records. Not appropriate for ad-hoc coordinate queries. |
site_abstract replacing multi-field prompt context |
Five prose description columns generated excessive LLM prompt length. site_abstract is a concise (~150 word) AI-ready synthesis delivering more interpretive value per token. |
CONUS_ONLY_CARDS object in fg-config.js |
Centralizes the logic for disabling US-only source cards without scattering conditional checks through rendering modules. |
| Orbit mode stops on user interaction | mousedown and touchstart handlers cancel the animation frame — users who start interacting clearly want control. |
| Globe zoom computed from container dimensions | Log₂ scaling from calibrated 640px baseline ensures globe fits at all responsive breakpoints without hard-coded media query overrides. |
enrich.php model allowlist |
Prevents arbitrary model strings being passed to the Anthropic API. Explicit allowlist with safe default. |
| Unified climate archive (6 vars, single request) | Feeds both Climate History and Water Balance cards. 48% API cost reduction vs. three separate requests. |
| 3-decimal coordinate rounding (~111m) | Matches ecological resolution of data sources. Coarsest common resolution is 10m (Esri LULC); most are 30m+; biodiversity APIs search in km-scale radii. Points within ~111m return identical data. |
BirdWeather Species.stations nested field |
Root stations query returns HTTP 500. Nested field uses a different resolver and works reliably. |
| LANDFIRE 30m grid-snapping | GPS jitter across devices can place same location in different 30m pixels. Snap to pixel center ensures cache consistency. |
| mysqli over PDO | Project convention for all Macroscope PHP code. |
| Vanilla JS, no frameworks | No React/Vue build step. Editable directly in BBEdit. Simplicity over scaffolding. |
14. Verified Test Sites
Table 11. Sites used for system verification.
| 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. 574m. Tests RESOLVE ecoregion ecotone accuracy. |
| James/Idyllwild, CA | 33.746 | −116.715 | Southern CA Mountains. 5,400ft. Tests tight EPA bbox for mountain ecotones. |
15. Limitations
YEA depends on the availability and accuracy of 20+ external APIs, each with its own coverage gaps, rate limits, and potential for change.
Coverage gaps: US-specific sources (EPA, NLCD, LANDFIRE, PAD-US) are unavailable internationally; global alternatives (RESOLVE, Esri Sentinel-2, WDPA) are coarser. iNaturalist observation density varies dramatically by region — Pacific Northwest and California return rich lists; remote areas may return sparse data even at maximum radius. BirdWeather coverage depends entirely on PUC station deployment, concentrated in North America and Western Europe.
API stability: The Köppen Climate API is a third-party service with no SLA. BirdWeather's root stations query returns HTTP 500 (workaround via Species.stations nested field). Open-Meteo Historical responses for the 35-year unified query are large (~12,400 daily records); retry logic with 2-second pauses handles intermittent timeouts.
Vision narratives: Quality depends on Mapbox terrain rendering at the queried location. Ocean coordinates, flat terrain, and cloud-obscured satellite imagery produce less informative vision calls. Vision calls may describe satellite imagery processing artifacts as landscape features.
AI enrichment: enrich.php is admin-only and asynchronous. Research quality varies by how well-documented a place is on the web. Claude with web_search may synthesize inaccuracies from secondary sources; all enriched content requires human review before publishing.
Narrative anti-hallucination: Constraints are effective but not infallible. LLMs can occasionally introduce plausible-sounding details not present in source data. The teaser narrative (50-word target) occasionally exceeds the word count.
Coordinate resolution: The 3-decimal rounding (~111m) means users standing 120m apart receive different ecological profiles; users closer than ~111m share the same cached result.
16. Planned Enhancements
Organelle Convergence Architecture: Integration with the broader Macroscope platform. Shared spatiotemporal index, event bus, and STRATA synthesis layer connecting YEA, MEO, ecoSPLAT, and Macroscope Nexus. See CNL-FN-2026-026 for architectural details.
SCOPE Integration: YEA as ecological metadata engine for the ecoSPLAT 360-degree panorama database. The globe visualization infrastructure already supports multiple GeoJSON layers that could serve as spatial indices for 3D Gaussian splat reconstructions from the SCOPE network [23].
Agent-Prompted Field Protocols: YEA monitoring agent watches time series, detects phenological anomalies, formulates testable hypotheses, and generates field protocols for student or citizen scientist execution — the "tricorder-as-mentor" architecture described in Hamilton (2026) [22].
Additional Data Sources: GBIF for historical records and temporal coverage. Map of Life for predicted species ranges. IUCN Red List API for authoritative global conservation status. Climate projections to 2050 for forward-looking ecological context.
Content Enhancements: "Deep Dive" narratives using Sonnet for integrated media. Species lightbox modals with external resource links. PDF/image export of ecological address profile. Batch mode for classroom use.
17. Development Conventions
17.1 Code Standards
- Simplicity over cleverness — readable, maintainable, ≤200 lines/file.
- Minimal changes — never reimplement from scratch without permission.
- Style consistency — match existing code patterns.
- Scope discipline — never make unrelated changes.
- No filename prefixes — never
new_,improved_,updated_in filenames. - Complete files — ready for BBEdit; never snippets.
- File headers — all PHP and JS files begin with a comment block: path, filename, purpose, change description.
- Proceed protocol — after each file delivery, pause and wait for confirmation before proceeding.
17.2 Naming Conventions
Table 12. Naming convention summary.
| 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 |
17.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. The climate archive fetch implements retry logic with 2-second pauses.
References
[1] Mapbox (2026). "Mapbox GL JS, Terrain-RGB v1, Geocoding v5, Search Box v1." https://docs.mapbox.com/ (accessed March 5, 2026).
[2] iNaturalist (2026). "iNaturalist: A Community for Naturalists." https://www.inaturalist.org (accessed March 5, 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 March 5, 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
[11] USGS / UNEP-WCMC (2024). "Protected Area Database of the United States (PAD-US) 3.0 / World Database on Protected Areas." https://www.protectedplanet.net
[12] The Weather Company (2026). "Weather Underground API." https://www.wunderground.com/member/api-keys (accessed March 5, 2026).
[13] Open-Meteo (2026). "Open-Meteo Weather API (Pro)." https://open-meteo.com (accessed March 5, 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 March 5, 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
[19] 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
[20] LANDFIRE (2024). "LANDFIRE LF2024 Existing Vegetation Type (EVT)." U.S. Department of Agriculture and U.S. Department of the Interior. https://landfire.gov (accessed March 5, 2026).
[21] Wikipedia (2026). "MediaWiki API: Geosearch." https://www.mediawiki.org/wiki/API:Geosearch (accessed March 5, 2026).
[22] Hamilton, M. P. (2026). "The Morning I Gave the Field Guide Eyes." Coffee with Claude. https://coffeewithclaude.com/post.php?slug=the-morning-i-gave-the-field-guide-eyes
[23] Hamilton, M. P. (2026). "Science Community Observatory for Participatory Ecology." Coffee with Claude. https://coffeewithclaude.com/post.php?slug=science-community-observatory-for-participatory-ecology
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 |
| 2.0 | 2026-02-22 | Complete rewrite: modular JS frontend (10 modules), PHP sub-parser architecture, LANDFIRE EVT replacing USDA FIA, Macrostrat geology, conservation status card, place context enrichment, narrative AI (4 tiers via Haiku), admin dashboard, analytics, globe visualization, unified climate archive (6 vars), 3-decimal coordinate rounding |
| 3.0 | 2026-03-05 | Curated Places system (yea_places v3.1, fg-places.js, enrich.php, admin); vision-enabled narratives (Sonnet 4.6 + 3D terrain screenshot, tricorder architecture); Land Protection card (PAD-US + WDPA); monitoring widget system (core.js + 6 mw-* modules); Pannellum panorama integration and OBFS import pipeline; Natural Area Detail panel; gallery module (fg-gallery.js); 12 JS modules (was 10); rotating globe on load with orbit/nadir/labels controls; site_abstract replacing multi-description prompt context; all references updated |
End of Document — CNL-TN-2026-025 v3.0
Cite This Document
BibTeX
Permanent URL: https://canemah.org/archive/document.php?id=CNL-TN-2026-025