Skip to content

Latest commit

 

History

169 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bird-location-scouting

Frame — a free, installable, offline-first PWA that answers one question for a bird photographer: where do I go, in which month, to photograph which birds? Hotspots are ranked by photographic opportunity (present and shootable), not by lister rarity.

Scope — what's in, what's not

Geographic coverage

The 58 California counties plus 5 western-Nevada counties (Douglas, Lyon, Storey, Washoe, Carson City — the Tahoe/Reno area). Every county carries its top eBird hotspots from the quarterly data build (El Dorado, Placer, Sacramento and Humboldt keep every hotspot); regions (sets of counties) are user-defined on the county map, up to 3 saved on-device.

The ranking

opportunity(h, month) = Σ_species frequency × shootability over the working species set, trust-shrunk and ranked within each month. Frequency comes from real eBird histogram data where it exists and from a transparent habitat/season model where it doesn't (always flagged inferred). shootability (v24, frame/src/model/photo.js) is the transparent photo-first weight — two small global tables over each bird's published facets (behaviour: open ×1 / mixed ×0.6 / skulker ×0.25; size: ×0.5–×1) — on by default, announced by a standing camera chip with a one-tap "every bird equal" exit. The old hidden per-species photoability judgment stays gone (v23): each hotspot shows objective facets (type / size / nest / behaviour) as bright/subdued/faint icons keyed to real frequency, the icons double as tri-state filters, and displayed numbers (the "N birds likely" headline, every frequency) are never weighted — only the order and colour intensity are (frame/src/data/species.js, frame/src/data/facets.js).

The map

A fully offline SVG basemap — no tiles, no connection needed in the field:

Layer Source Notes
County shapes & names US Census via plotly GeoJSON generated by frame/scripts/gen-county-shapes.mjs
Rivers, lakes, coastline Natural Earth 10m (public domain), incl. the finer North-America rivers layer named on the map
Major roads Natural Earth 10m roads clay-red lines; numbered pill shields on major routes only
Parks / protected lands Natural Earth 10m (NPS-scale units) green fills, named
Reservoirs & lakes Natural Earth misses (Folsom, Natoma, Camanche…) curated list in frame/scripts/curated-landmarks.mjs; shorelines © OpenStreetMap contributors (ODbL), fetched by gen-basemap.yml on a runner real water polygons + labels; every position is point-in-polygon verified against its county at build time — a wrong position fails the build
Wildlife refuges & preserves (Cosumnes, Yolo Bypass, Gray Lodge, the NWRs…) curated, same verification the landmarks that matter most in a bird app

Deliberately not included: minor roads and street detail (the per-hotspot "Maps" button hands off to a real navigation app), turn-by-turn anything, and land-use layers without clean public-domain data (restricted areas, school campuses — on the roadmap if a trustworthy source is found). All map data is generated into committed files by frame/scripts/gen-*.mjs; nothing is fetched at runtime.

Data refresh

eBird histogram data rebuilds quarterly via the Refresh eBird data GitHub Action (needs EBIRD_API_TOKEN + a fresh EBIRD_COOKIE secret — see frame/HANDOFF.md for the iPad-only procedure).

Repository layout

Path What
frame/ the entire app (no build step — static ES modules)
frame/src/ UI, model, and generated data modules
frame/data/ per-county eBird data + taxonomy (committed, refreshed quarterly)
frame/scripts/ data generators & the eBird build
.github/workflows/ deploy (Cloudflare Pages), quarterly data refresh, releases, keepalive
CLAUDE.md standing working rules for AI sessions on this repo

Release process

Work lands on a claude/* branch → pushed to staging for a Cloudflare preview → on-device acceptance on the developer's actual iPad is a hard gate → PR merges to main, which deploys production and auto-publishes a GitHub Release from the top of CHANGELOG.md. App version = service-worker cache name (frame-v<n> in frame/sw.js); the two bump together.

Product values

Free · on-device · offline-first · no account · no install required · honest labels (an inferred number is always marked inferred, and every failure state explains itself and offers a way forward).

Accessibility

A top priority, not a feature. Colour-blind-inconsiderate design is a fail state for this project: every visual encoding must carry a non-hue channel (luminance step, shape, size, or text), text contrast is measured against WCAG AA (frame/scripts/contrast-check.mjs), and changed screens are verified in grayscale before they ship. The working contract — design rules, verification recipe, and the live audit register — is ACCESSIBILITY.md.

About

Frame — a free, offline-first PWA that answers: where do I go, in which month, to photograph which birds. California + western Nevada.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages