Architecture
What this is
H2OFlows is a streamflow data platform — a gauge dashboard backed by an open reach registry that the entire whitewater community can build on. At its core it aggregates real-time CFS readings from USGS and Colorado DWR, overlays community-defined flow ranges, and ties gauge data to geographic reach records (put-ins, take-outs, rapids, access notes).
The platform is free, open source, and will remain so. The data belongs to the community.
Tech stack
Backend
| Layer | Choice |
|---|---|
| Language | Go |
| Router | Chi |
| Database | PostgreSQL 16 + PostGIS |
| Migrations | golang-migrate |
| AI | Anthropic Claude (anthropic-sdk-go) |
| Object storage | Cloudflare R2 (planned) |
| Auth | Supabase (Google OAuth) |
Frontend
| Layer | Choice |
|---|---|
| Framework | Nuxt 4 |
| UI | Nuxt UI (Tailwind CSS v4) |
| State | Pinia |
| Maps | MapLibre GL |
Infrastructure
| Component | Hosting |
|---|---|
| API | EC2 at api.h2oflows.app (Docker Compose + Caddy) |
| Web app | Netlify at h2oflows.app |
| Docs | Netlify at docs.h2oflows.app |
| DNS | Cloudflare |
Repositories
| Repo | Contents |
|---|---|
| h2oflows-app/api | Go backend, migrations, gauge adapters |
| h2oflows-app/web | Nuxt 4 frontend |
| h2oflows-app/docs | This documentation site |
Gauge adapters
The gauge-core package in the API implements a plugin interface for data sources. Each adapter is a single file that satisfies the interface. Current adapters:
- USGS — National Water Information System (waterservices.usgs.gov)
- DWR — Colorado Division of Water Resources (dwr.state.co.us)
Adding a new data source means writing one adapter file. See the contributing guide for details.
Data model (key tables)
gauges — gauge metadata (source, external_id, name, lat/lng)
gauge_readings — time-series CFS readings per gauge
reaches — river sections (slug, name, class, geometry)
reach_gauges — many-to-many: reaches linked to gauges
flow_ranges — CFS band definitions per reach (too_low / min / optimal / pushy / flood)
rapids — rapid inventory per reach (name, class, coords, description)
reach_access — put-in/take-out/parking/shuttle per reach
dashboards — named watchlists per user
watchlist_items — gauge memberships in dashboards
Reach data seeding
Reach content is seeded using AI (Claude) from guidebook knowledge, American Whitewater records, and community trip reports. The cmd/seed-reaches tool defines reaches with local knowledge notes embedded in the seed prompt; the AI generates rapid inventory, access notes, descriptions, and flow ranges.
Every seeded item carries a data_source and confidence score:
confidence >= 85→ auto-verifiedconfidence 50–84→ stored as draft, shown with badgeconfidence < 50→ dropped at generation time
Community corrections and verified field data override AI-seeded content.
Build phases
| Phase | Status |
|---|---|
| Phase 1 — Gauge dashboard | Complete |
| Phase 2 — Reach pages + user features | Complete |
| Phase 3 — Accounts, alerts | Deferred (post-pilot) |
| Phase 4 — Trip planning | Planned |
| Phase 5 — Permit trip module | Planned |
| Phase 6 — Public API docs + token issuance | Parallel to Phase 3+ |
Contributing
Non-developer contributions:
- Add or verify reach data for rivers you know
- Define flow ranges for local gauges
Developer contributions:
- Issues tagged
good-first-issueare the entry point - Gauge source adapters are the easiest first contribution
See CONTRIBUTING.md for development setup.