About RVA James
A passion project bringing James River conditions, trail info, and family-friendly guides together in one place.
What this is
RVA James is an independent dashboard that pulls together river conditions, flood and water-quality advisories, weather, and combined-sewer-overflow status for the James River around Richmond — and translates them into plain-language guidance for families with kids.
All of the underlying data already exists across USGS, NWS, the James River Association, and Richmond DPU. The goal here is to consolidate it, age-tune the recommendations, and be honest about uncertainty. The site uses AI to interpret sensor data into readable guidance — never to make safety decisions for you. Always use your own judgment near the river.
About the creator
RVA James is a passion project by Mike Garrett.
About Mike
I moved to Richmond in 2016 and quickly discovered that the James River is one of the city’s greatest assets. It’s where my family hikes, swims, and spends time together throughout the year.
As a parent, I found myself constantly searching for practical information: Which trails work for young kids? What does the river level actually mean? Which spots are crowded? Where can you safely explore, swim, paddle, or fish? The answers were often scattered across websites, maps, social media posts, and local knowledge.
RVA James is my attempt to bring that information together in one place.
I’m not a riverkeeper, biologist, historian, or professional guide. I’m a Richmond parent who enjoys researching the river and sharing what I learn. My goal is simple: help busy families spend less time searching for information and more time enjoying the James.
This site is a collection of practical guides, local knowledge, river conditions, history, and family-friendly adventures gathered along the way. I’m still learning, and RVA James is a record of that journey.
How it’s built
RVA James is a Next.js app running on Cloudflare Workers, with data stored in Supabase (Postgres). Scheduled jobs pull from USGS, NWS, the James River Association, and Richmond DPU every 15 minutes to a few times a day. Claude (Anthropic’s AI) interprets that stored data into family-readable guidance — it never fetches data itself.
The source code is open: github.com/MikeNGarrett/rvajames (opens in new tab).
For the technically curious
Stack. Next.js 15 (App Router, React 19), TypeScript end-to-end, Tailwind v4 (CSS-first @theme config), Cloudflare Workers via OpenNext for Cloudflare. Supabase (Postgres + RLS) for storage and @supabase/supabase-js on both server and edge. Anthropic SDK directly — no LangChain.
Ingestion. Cloudflare Cron Triggers run per-source jobs: */15 for USGS (gage height, discharge, water temp), 0 * for NWS hourly forecast and active alerts, 0 12 for daily James River Watch (E. coli + advisory), 0 6,18 for Richmond DPU’s combined-sewer-overflow advisories, plus a real-time poll of EmNet’s outfall sensors. Every run writes to an ingestion_runs table — visible at /status.
AI interpretation. A deterministic rules engine handles every safety threshold (gage bands, water temp cutoffs, age-appropriate activity gates) so the AI never decides who can swim. Claude turns the resolved conditions into prose that fits the brand voice. The system prompt is large but cached (Anthropic prompt caching, ephemeral cache control) — the location encyclopedia, age guidance, and JSON schema all sit in the cached block; only the date, location, age bucket, and snapshot summary are uncached per call. A SHA-256 hash of those uncached inputs prevents regenerating an interpretation when nothing has changed.
Freshness model. Each source has a per-tile staleness threshold (USGS 30 min, NWS 90 min, JRA 26 h, CSO 14 h). Past those, the affected tile renders a Stale state rather than a stale value — better to show “we’re missing data” than a number that isn’t true anymore.
Safety posture. The site never recommends an activity it can’t justify from sensor data, never personalizes financial or medical advice, and surfaces the underlying numbers so you can second-guess the prose. See the safety resources page for the AAP / NPS / USCG documents the thresholds are grounded in.