Update, August 20, 2026. This note describes the first version of the dashboard. That version used 28 Utah reservoirs, the Reclamation RISE API alone, and a MapLibre GL JS comparison build. The project has since moved to the ArcGIS Maps SDK for JavaScript 5.1, and it now covers snow and drought as well. It also covers eleven western states instead of Utah, and it is called the Western Water Dashboard. The MapLibre build is retired, and its address now sends you to the current map. For the current application, read One place to see the water in the West.
Utah has spent years in drought. The numbers that describe it, acre-feet of storage and percent of capacity, are hard to read from a table. An acre-foot is enough water to cover one acre one foot deep. This dashboard put current storage for 28 Bureau of Reclamation-monitored Utah reservoirs on one map. Each reservoir is drawn so that its depletion reads as a shape as well as a color. It was a personal project with no framework and no build step. It also served as a side-by-side test of a commercial mapping SDK against an open-source one.
Two ways to measure "low"
Every reservoir carries two drought metrics. Both are computed from the full record instead of read from one reported number. Percent of period-of-record max compares today's storage with the highest storage that reservoir has reached since 2015. That is a stand-in for physical capacity, and it is consistent across reservoirs of very different sizes. Seasonal percentile ranks today's level against every other year's value within a seven-day window of the same calendar date. A reservoir can be low against its record high and still be normal for early August. The two numbers together show the difference.
Reading depletion as a shape
Each reservoir renders as two circles. A gray outline ring is sized by the reservoir's period-of-record max. A colored filled circle on top is sized by current storage. The gap between the ring and the fill shows depletion. Both radii use the same square-root size scale, which fits Lake Powell at millions of acre-feet and the smallest reservoirs at a few thousand into one readable range. The fill is sized as a share of its own ring, so the ring-to-fill ratio always means percent depletion, whatever the reservoir's size. Fill color uses the same three-step ramp the popup states in words: red under 50%, orange 50 to 75%, green above 75%.
A pipeline that refreshed itself
The map was static. The data behind it was not. A Python script
(pandas, NumPy, and the RISE API) pulled each reservoir's full
daily storage series from 2015 to yesterday, computed both drought
metrics, and wrote one reservoirs.json file. A GitHub
Actions workflow ran the script every morning at 6 a.m.
Mountain, so the dashboard stayed current with no server to
maintain. Reclamation marks RISE data as provisional. The app
stated that in the title panel and in every popup.
Built twice: Esri vs. MapLibre
The first build used the ArcGIS Maps SDK for JavaScript, loaded
from Esri's CDN with plain script tags. There was no npm and no
webpack. Two FeatureLayers carried the symbology,
driven by Arcade valueExpressions. The popup was a
PopupTemplate that turned the raw percentage into a
plain-language status line and the acre-foot gap to the
historical peak.
The second build rebuilt the same dashboard in MapLibre GL JS on CARTO's free Positron vector basemap. It used the same data, the same dual-circle symbology, and the same popup wording. Both are WebGL vector renderers, so the comparison is fair. It replaced an earlier Leaflet attempt, which was not a like-for-like test because Leaflet paints raster tiles in the DOM. With both engines drawing vector data on the GPU, the results matched. Flaming Gorge, for example, agreed exactly on 2,669,060 acre-feet current against a 3,557,090 record max.
The difference is in the tooling, not the rendering. Esri's
PopupTemplate and Arcade expressions are declarative
and fast to work with once you know them. MapLibre's popups are
plain HTML you assemble yourself, and its data-driven styling
uses interpolate, step, and
sqrt expressions in place of Arcade. For this
dashboard, MapLibre's model of one shared source and two layers
was simpler to reason about, because both circle layers read from
one feature set. The open-source stack reached parity here. What
you give up is the higher-level conveniences.
View the current Western Water Dashboard or the source on GitHub. The MapLibre GL comparison build is retired and is no longer published. Data: Bureau of Reclamation RISE.
