Anvil
The radar bench I built for myself.
A pro-grade macOS weather-analysis workstation — GR2Analyst / AWIPS-class. Gate-accurate GPU Level II radar, a self-decoded severe-weather product suite, dual-pol validated against the NWS, forecaster tools, and a 3D volume viewer.
Not on the App Store. Not for sale. This is the studio's own instrument — the page exists because it's the most technically ambitious thing here, and worth showing.
A workstation for interrogating the atmosphere — not a forecast you're handed.
Most weather apps tell you the answer. Anvil is the opposite: a bench for pulling apart raw radar and forecast data and forming your own judgment, the way GR2Analyst, GRLevelX, and AWIPS do for operational meteorologists. It decodes the same NEXRAD Level II/III volumes the National Weather Service works from, renders them gate-accurately on the GPU, and layers on the severe-weather products a chaser actually reads.
The same volume the NWS works from — rendered per-pixel on the GPU.
Single-site reflectivity, velocity, ZDR, CC, and spectrum width render from the full NEXRAD Level II volume (decoded with Py-ART) through a Mapbox WebGL custom layer: a fragment shader computes range and azimuth per pixel and samples a polar data texture — 16-bit values packed into the texture, an in-shader 256-entry color lookup, mask-aware bilinear smoothing in both azimuth and range so data never bleeds across echo edges.
The payoff is the thing the public radar tiles can't give you: crisp at any zoom level, no pixelation, with real per-elevation tilt selection and value-under-cursor readout. An animation loop streams N Level II volumes into N GPU textures and swaps between them.
GR2-class products, self-decoded from the raw volume.
These are the products that exist as no free tile anywhere — so Anvil computes them itself from the Level II volume in a local Python sidecar (Py-ART + MetPy), then renders them through the same GPU polar layer.
Validated against the NWS, not just rendered.
A radar product that looks right isn't necessarily right. Anvil ships an accuracy harness (validate.py) that resamples each self-decoded Level II product onto a shared grid and scores it against the operational NWS Level III as ground truth — coverage, correlation, bias, RMSE. Findings at KLSX:
The harness paid for itself: it caught a broken KDP retrieval (correlation 0.08 — the fast φDP-gradient fallback was garbage), which is why KDP and HCA now serve the operational NWS Level III product directly, accurate by construction. The honest pass is the point — if a product can't be trusted, it gets fixed or replaced.
Everything you need to build a forecast judgment.
Beyond the radar scope: the analysis tools an operational forecaster reaches for, wired to free public data.
The storm as a solid you can fly around.
A Three.js viewer renders the full Cartesian reflectivity grid as translucent voxels and smooth nested isosurfaces (30 / 45 / 55 dBZ shells via surface-nets). Switch the field to Z / V / ZDR / CC, or to HCA hydrometeor classification voxels. GLM satellite lightning bolts jag down through the volume, faded by age. A cross-section curtain cuts a vertical RHI wall through any azimuth.
Click-readout gives dBZ, height, range and azimuth at any voxel; a column profile plots dBZ-vs-height; the whole thing exports as an orbiting MP4. Geography (county and state lines, town-name labels) grounds it to the map below.
A native shell, a web map engine, and a Python radar brain.
Three layers, each doing what it's best at. The front end is SwiftUI + AppKit. The map is Mapbox GL JS running in a WKWebView — seeded from the Weather.Co macOS engine — driven by a typed JS command channel. The radar decoding runs in a local Python FastAPI sidecar so MetPy / Py-ART do the heavy lifting off the main thread.
- Front end
- SwiftUI + AppKit · SwiftData (
AnvilSchemaV1, versioned) · macOS 26, Apple Silicon - Map engine
- Mapbox GL JS in a WKWebView · WebGL custom layer for the GPU radar · typed JS command channel with a two-stage queue
- Radar sidecar
- Python FastAPI (
l3server.py) · Py-ART + MetPy · decodes NEXRAD Level II/III from AWS, serves polar textures + products over localhost - Data sources
- All free, no key: NEXRAD L2/L3 (AWS) · IEM mosaic + GOES tiles · NWS RIDGE / alerts / SPC · NDFD · Open-Meteo · GOES-19 GLM lightning
- Accuracy
validate.py— scores each L2 product vs operational NWS L3 (coverage / correlation / bias / RMSE)- Design system
- "Forge" — charcoal RadarScope panels, forge-amber
#F2960Daccent, adaptive over-map chips - Build
- XcodeGen vendored ·
com.kuhlman.anvil· not sandboxed (localhost sidecar) · not App Store - Status
- v0.1 · in active development · personal use only
Built for one forecaster. Shown for everyone.
Anvil isn't for sale and isn't on the App Store — it's the studio's own radar bench. But the techniques, the architecture, and the lessons are all written up. Start with the lab guides, or read how the shipping apps are made.
Read the lab guides → See Weather.Co →