Update, August 24, 2026. The project started as a Utah dashboard. It now covers eleven western states, and it is called the Western Water Dashboard. The address changed with the name. The counts on this page are the ones the site published on August 24, 2026. The roster grows as reservoirs pass review, so the live figure is higher than a screenshot taken before that date.
The problem: no combined source
Western water numbers are public. They are also separated. The Bureau of Reclamation publishes reservoir storage. The Natural Resources Conservation Service publishes mountain snow. The U.S. Drought Monitor publishes a weekly drought map. Each agency has its own application, and each application is missing something I want. None of them let you filter across all three.
In winter, most of us see one image. A static PDF of Utah snowpack goes through the social media feed about once a week. It shows six levels of detail. That is the whole picture for many skiers and many voters. I wanted to ask better questions than that image can answer. The same problem repeats in every western state.
How it started
The first version was a job-interview exercise. I built a map on the ArcGIS Maps SDK for JavaScript 4.34 for a web developer position with the State of Utah. I kept working on it after the interview. I got it to a reasonable place with no AI help.
Then I looked at where that work had actually stopped. The map was good. The scope was small, the vocabulary was inconsistent, and every new feature took longer than the last. So I made two decisions at the same time. I would move the whole application to the ArcGIS Maps SDK for JavaScript 5.1. And I would run the rebuild with a full agentic AI harness instead of one prompt at a time.
Agents, with guardrails
An agentic AI harness is a set of instructions that tells an AI coding agent how to work, not only what to build. The skills for this project come from skills.addy.ie. They encode senior software engineering practice as structured skills with verification gates. Write the specification first. Plan before you build. Prove the change with a test. Do not mark work complete until the exit criteria pass.
The value is the limits, not the speed. The skills stop an agent from doing too much in one step. Every change still goes through human review before it reaches the published site.
A geographic rule, written down
The old version tracked 28 reservoirs. The new version needed a rule, not a list. A hydrologic unit code, or HUC, is the federal numbering system for drainage areas. The first rule took every drainage area that touches Utah in HUC regions 14, 15, and 16. Those are the Upper Colorado, the Lower Colorado, and the Great Basin. That rule gave 14 drainage areas.
The rule is now larger and simpler. The dashboard covers HUC regions 14 through 18: everything in the contiguous states that drains to the Pacific Ocean, plus the Great Basin, which drains nowhere. That is 75 drainage areas in eleven states. Region 17 is the Pacific Northwest and region 18 is California.
One area shows what a rule change costs and gives. Drainage area 170402, the Upper Snake, clips Utah's northern edge. It failed the first rule on hydrology, because its water drains north-west to the Snake River, then the Columbia, then the Pacific. Under the new rule the Pacific is the point, so the Upper Snake is in scope. The decision record that excluded it is not deleted. It records why the answer was correct for the map that asked the question.
A reader can choose how finely the ground is divided. Every map offers 75 drainage areas or 44 larger subregions. Each subregion holds whole drainage areas, so the choice splits nothing. Each figure is measured again at the size you choose. It is not averaged up from the smaller size.

What the dashboard shows
The storage map is the primary view. The site publishes 382 reservoirs, and five agencies measure them. The Natural Resources Conservation Service reads 168. The California Department of Water Resources reads 142. The Bureau of Reclamation reads 55, the Colorado Division of Water Resources 10, and the U.S. Geological Survey 7. Those reservoirs sit in 54 of the 75 drainage areas. The other 21 hold no reservoir on the roster yet. To admit a reservoir, I must trace a full level to a named source and review it. That work is separate from drawing the ground, so the map draws areas that hold nothing.
Two reservoirs get their own controls. Lake Powell and Lake Mead are each large enough to hide every other reservoir in a combined total. The map now opens with both of them switched on, and the summary says so in words before it gives you a number. You can remove either one at any time. A total with them and a total without them are both true. They are not the same measurement.
You can filter by state, by subregion, by drainage area, by county, by percent-full class, or by reporting status. The three geographic filters narrow each other, so you can start at a state and stop at one drainage area. Filtered reservoirs stay on the map in gray. A month slider compares the last twelve months. Every view has its own address, so you can send a colleague the exact thing you are looking at.
"In a state" means where the water is, not where the dam is. Bear Lake sits on the Utah and Idaho line and its published point is in Idaho, so it is in both lists. A county works the other way. The county comes from the waterbody, so Lake Powell is in San Juan County, Utah, and not in Coconino County, Arizona, where Glen Canyon Dam stands.

A map cannot answer every question. The storage charts page uses ArcGIS charts components for six charts that compare reservoirs against each other and against normal. The search box, the subregion and drainage-area filters, and the reporting filter change all six charts, the summary values, and the table at the same time.
Snow that falls on the mountains melts into the reservoirs, so this winter's snow is next summer's storage. The snowpack page shows snow water equivalent, which is the depth of water the snow would make if it melted. It reads 637 measurement sites in eleven states and opens on the day the season held the most snow, because that is the day the rest of the year is judged against.
The season on this page never reached normal. Between November 12 and June 17 there were 218 days when the normal for the date held more than an inch of water, which is the span where the comparison means anything. The region did not reach 100 percent of normal on any of them. The closest it came was January 8, 2026, at 78.4 percent. Outside that span the ratio is noise. In early October the normal is a few thousandths of an inch, so one storm divides into four figures and means nothing.
The day with the most water was March 13, and that day held only 60.7 percent of its own normal. A snowpack can hold its deepest water of the year and still fall well short of what the date usually holds. Those are two different questions, so the site answers them separately. The map opens on the deepest day. The summary reports the best day against normal beside it.
The sites are not spread evenly. An automated snow site sits in 51 of the 75 drainage areas. The other 24 are desert, coastal lowland, or valley floor, and no machine measures snow in them. The inventory names them and publishes the gap. It does not fill the gap with an estimate.

The drought page reads the weekly U.S. Drought Monitor by drainage area, and shows it next to the water banked in that area. The two can disagree. A full reservoir in a dry drainage area means the region is drawing on saved water. The measurement covers all 75 drainage areas, and the 44 subregions as well.
The Drought Monitor stops at the Canadian and Mexican borders. The engine used to count every cell beyond a border as land with no drought on it. That cost nothing while the map stopped at Utah. At western coverage it would have reported a large drought-free area in the Kootenai that is really British Columbia. Unmeasured ground is now marked as unmeasured.

The drought map draws a second surface. It measures each drainage area against the week before it, and colors how much of that area's land moved into or out of severe drought. This is the one view on the site that answers "what changed" instead of "what is". It uses its own diverging colors, because the Drought Monitor palette belongs to the Drought Monitor and a map that borrows it for something else teaches a reader the wrong thing.
The comparison appears only when a second week exists to compare against. A control that switches to a blank map tells a reader the comparison is there and then shows them nothing.

How to use it
Hover to scan. Click to investigate. Link to share. Those three verbs cover most of the application. The middle one is a deliberate break from the default behavior of the ArcGIS Maps SDK.
The first screen asks two questions. You pick a place, either one of the eleven states or one of the five regions. Then you pick a subject: the storage map, the storage charts, the snowpack page, or the drought page. A shared link never lands on that screen. Someone who opens your link is being shown a thing, and a dialog in front of it is a worse version of the page you sent.
On the storage map, a pointer over a reservoir gives you a small card with the top-level reading. A click opens the full detail panel. Popups are switched off everywhere, on purpose. A popup covers the map at the moment you want to compare one reservoir against its neighbors, and it holds less than a panel can.
The panel gives the last twelve months as a chart and as a table. It also gives the four things a reader needs before quoting a number:
- who measures the reservoir
- how often the reading updates
- the drainage area the reservoir sits in
- the normal for that week, from 1991 through 2020
The panel answers one more question. It tells you what drains into that reservoir. Lake Mead reports 76 published reservoirs and 150 snow-measuring sites upstream of it. Those sets come from the Network-Linked Data Index, a U.S. Geological Survey service. It follows the national stream network from a point back up every branch that feeds it. That is the difference between reading one reservoir and reading the system that fills it.
Then you can send it. Every view has its own address. A copy button next to the summary gives you the link to the exact view on your screen. Each reservoir also has a page of its own. A sorted table, a filtered map, and a selected reservoir all survive being pasted into an email.
The place travels with you between pages. Narrow the storage map to one drainage area, then open the snowpack page, and the snowpack page opens on the same ground. The three maps exist to be compared. A reader who narrows one of them has not asked to widen the others.
The pipeline behind it
The site is static. The data is not. Python scripts use pandas, NumPy, and the ArcGIS API for Python to read each agency service, validate the values, and write one JSON file for each subject. A GitHub Actions workflow runs the refresh each morning. That commit is the deployment.
The pipeline keeps the last good record when a source does not answer, and marks the reading as late instead of showing a gap. A broadly failed run does not replace the published file. Capacity comes from the National Inventory of Dams, read from the U.S. Army Corps of Engineers service that maintains it, so the full level for each reservoir is traceable to a named source.
Decisions instead of preferences
A system atlas draws all of this as one interactive diagram: the sources, the pipeline, the payloads, and the pages a reader sees. It is a snapshot, generated on one date and frozen. The live system is the dashboard, not the drawing.
The repository holds 95 architecture decision records. Each one states a problem, the options, the decision, and the consequences. They cover the geographic rule, the color ramp, the label order, the basemap, and the vocabulary.
Three rules do most of the work. Color breaks live in one table, and a test asserts that the map, the legend, the charts, and the filters all read from it. Visible text follows a Simplified Technical English word list, which is also why the site says "acre-feet" and "late data" instead of shorter internal terms. Accessibility is a build gate, checked with axe-core, so a change that breaks keyboard use or contrast fails before it publishes.

What the agents did badly
Agentic development worked well for typed code, tests, data validation, and documentation. It worked poorly for anything an agent cannot measure.
Almost every remaining problem was visual. Labels collided at one zoom level and not another. A symbol read as one class on screen and a different class in a screenshot. A legend order looked arbitrary. An agent can confirm that a color value matches a table. It cannot see that two labels overlap, or that a map feels wrong. Those problems came back to a person every time. The project wiki records them, because they are the honest limit of this method for GIS applications today.
Open data, and a warning
The same checked JSON files the dashboard reads are published as a public data API, with field definitions and examples. A methods page names every source, every identifier, and the rule used to work out each value. Nothing on the site is modeled, predicted, or smoothed.
This is a personal open-source project. It is not an official product, and no agency endorses it. Where the site and an agency disagree, the agency is right.
View the Western Water Dashboard, the methods and sources, the public data API, or the source on GitHub. Agent skills: addyosmani/agent-skills. Data sources. Reservoir storage: the Bureau of Reclamation, the Natural Resources Conservation Service, the California Department of Water Resources, the Colorado Division of Water Resources, and the U.S. Geological Survey. Mountain snow: the Natural Resources Conservation Service. Drought: the U.S. Drought Monitor. Full levels: the National Inventory of Dams, read from the U.S. Army Corps of Engineers. Upstream tracing: the Network-Linked Data Index, a U.S. Geological Survey service over the national stream network. Every source, with its identifiers and its update rules, is named on the methods page. An earlier note describes the first version and its MapLibre GL JS comparison. The project was called the Utah Water Dashboard until August 2026.
