Pick a rectangle anywhere on Earth and watch water run down the real ground under it, in the rain that is actually falling there right now.
Nothing is precomputed and there is no server doing the work. The browser pulls four open datasets for the rectangle you drew, decodes them itself, and hands a plain grid of heights to a small piece of Rust compiled to WebAssembly. No API keys, no accounts, no rate limits.
Elevation arrives as PNG images, but they are not images of anything. The terrarium encoding packs one height in metres into each pixel's three colour channels:
Which means one step in the red channel is 256 metres. That single fact decides how the whole geodata stack is built. Draw one of these tiles to a canvas and read it back — the obvious way to get pixels in a browser — and colour management is free to nudge a channel by one on the way through. Nobody would notice on a photograph. Here it moves a hillside a quarter of a kilometre into the sky.
So every tile is decoded with ImageDecoder straight to raw
bytes, and never through a canvas. The soil layer needs deflate, which
DecompressionStream handles. Both are browser built-ins, which
is why the whole geodata stack has no dependencies at all.
This is the only part written in Rust, and it is deliberately the only part. It receives a grid of integer heights and knows nothing about maps, projections, tiles or file formats — every attempt to teach it about geodata has been deleted again.
Each droplet moves one cell per tick and leaves a trail that fades. A route every droplet crosses settles bright; ground crossed once in twenty ticks stays dim. That separation is the picture.
Radar gives reflectivity in dBZ, which becomes a rainfall rate through the standard Marshall-Palmer relation, capped at 65 dBZ because above that it is hail rather than rain. That is the easy half.
The interesting half is that rain falling on ground that can absorb it does not run anywhere. So the soil fractions are put through the USDA texture triangle, into the NRCS hydrologic soil groups, into a saturated infiltration capacity:
| Group | Texture | Soaks up |
|---|---|---|
| A | sand, loamy sand, sandy loam | 10.0 mm/h |
| B | loam, silt loam, silt | 5.5 mm/h |
| C | sandy clay loam | 2.5 mm/h |
| D | the clays | 1.0 mm/h |
A cell then spawns droplets on rate − capacity, not on
rate. Light rain on sand produces nothing at all; the same rain
on clay produces streams. And once a droplet exists, the ground underneath
keeps taking its rate out of it every tick, so a droplet crossing
free-draining soil dies sooner than one on clay. The same number does both
jobs.
The terrain is not one survey but a mosaic of many, merged into Terrain Tiles and hosted on the AWS Registry of Open Data. Its licence asks that every one of them is credited, so:
Rain from RainViewer. Soil from ISRIC SoilGrids, CC BY 4.0. Place search from Photon, over OpenStreetMap. Basemap © OpenStreetMap contributors, © CARTO.
← Open the map