High-performance, GPU-accelerated real-time precipitation ensemble, temperature, wind stream, and solar forecast engine for the Netherlands.
Nimbus is a modern meteorological intelligence platform and radar server built in Rust and WebGL. It streams high-resolution weather data from the Royal Netherlands Meteorological Institute (KNMI), performing sub-millisecond projection re-mapping and serving lossless, GPU-decodable textures directly to interactive web and mobile interfaces.
By leveraging 20-member precipitation ensemble forecasts, KNMI Harmonie-AROME numerical models, and GPU-driven particle advection, Nimbus transforms complex multi-dimensional NetCDF and GRIB1 datasets into fluid, intuitive visualisations.
-
๐ง๏ธ 20-Member Precipitation Ensemble Forecasts
- High-resolution seamless blend across the Netherlands.
- View individual ensemble members (
1โ20), median (med), maximum (max), or precipitation probability (prob). - 6-hour forecast timeline at 5-minute intervals with real-time radar actuals backfill.
-
๐ก๏ธ Harmonie-AROME Atmospheric Layers
- Temperature: 2m surface temperature fields with smooth bilinear sampling.
- Wind Vector Field: Multi-altitude wind speeds and directions with real-time GPU particle simulation.
- Solar Irradiance: Global radiation maps for solar energy forecasting.
-
โก Lossless RG-Packed WebP Transport
- Encodes 16-bit precision meteorological variables into the Red and Green channels of WebP images.
- Minimises network payload size while enabling sub-millisecond on-GPU decoding via custom GLSL shaders.
-
๐ Event-Driven MQTT Pipeline
- Direct WebSocket connection to KNMI Open Data MQTT notification services.
- Automatic, zero-latency ingestion of new radar runs, actuals, and weather model cycles without polling.
-
๐ Interactive Location Analytics
- Click or tap anywhere on the map to inspect instant point values and 48-hour forecast trend curves.
-
๐ฑ Cross-Platform Ecosystem
- Modern, responsive glassmorphic web dashboard (MapLibre GL JS + WebGL + Chart.js).
- Dedicated companion Flutter mobile application for Android & iOS.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ KNMI MQTT Broker โ
โโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโ
โ
Push Notification Event
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Rust Axum Backend โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโ Ingest / Cache โโโโโโโโโโโโโโโโโโโ โ
โ โ MQTT Listeners โโโโโโโโโโโโโโโโโโโโโโโบโ Local Storage โ โ
โ โ (rumqttc WebSockets) โ โ (.nc / .bin) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโ Precalculated โโโโโโโโโโโโโโโโโโโ Parallel Rayon โ
โ โ Axum API Router โโโโโโโโโโโโโโโโโโโโโโโโค In-Memory Cache โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ (REST JSON / WebP) โ โ (LUT & Slices) โ โโ
โ โโโโโโโโโโโโโฒโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโ
โ โ โโ
โ โ HTTP / Tile Requests โโ
โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโ
โ
โ (/api/metadata, /api/data/*, /api/timeseries, /api/value)
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Client Visualisation Layer โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโ WebP Stream โโโโโโโโโโโโโโโโโโโ GPU Shaders โ
โ โ MapLibre GL JS / โโโโโโโโโโโโโโโโโโโโโโโบโ WebGL Textures โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Flutter Map View โ โ (Decode RG->u16)โ โโ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโ
โ โ โผโ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโ โผ โโโโโโโโโโโโโโโโโโโ
โ โ Chart.js โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค Particle Stream โ
โ โ Timeseries Trends โ โ & Custom Layer โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
| Layer | Technologies |
|---|---|
| Backend Core | Rust (2021 Edition), Axum 0.8, Tokio, Rayon |
| Data Ingestion | netcdf (HDF5), grib-reader (GRIB1), rumqttc (MQTT/TLS) |
| Web Frontend | Vanilla ES Modules, MapLibre GL JS, WebGL 2.0 / GLSL, Chart.js |
| Mobile App | Flutter (Dart), Custom Native OpenGL Overlays (Android / iOS) |
| Containerisation | Docker (Multi-stage build), Docker Compose |
- Rust (1.70 or newer)
- NetCDF / HDF5 development libraries:
- Ubuntu / Debian:
sudo apt-get install libnetcdf-dev libhdf5-dev - Arch Linux:
sudo pacman -S netcdf hdf5 - macOS:
brew install netcdf hdf5
- Ubuntu / Debian:
- A free KNMI Open Data Platform API Key
-
Clone the repository:
git clone https://github.com/Yannicked/Nimbus.git cd Nimbus -
Configure environment variables:
cp .env.example .env
Open
.envin your editor and add your KNMI credentials:KNMI_OPEN_DATA_API_KEY=your_open_data_api_key_here KNMI_MQTT_PASSWORD=your_mqtt_api_key_here
-
Run the server:
cargo run --release
-
Open
http://localhost:8080in your browser.
Note
On the first startup, Nimbus automatically downloads the latest ensemble and numerical weather prediction datasets (~200 MB) from KNMI and initializes the projection Look-Up Tables. Subsequent updates arrive automatically via MQTT.
You can build and run Nimbus via Docker Compose:
# Ensure .env is populated with your KNMI credentials
docker compose up --build -dTo view logs:
docker compose logs -fNimbus includes a native Flutter client located in the mobile/ directory.
cd mobile
flutter pub get
flutter runAll endpoints return JSON or binary image data with appropriate CORS headers.
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/metadata |
Current dataset dimensions, timestamps, ensemble members, and bounds |
GET |
/api/data/:ens/:time |
Lossless RG-packed radar tile WebP (:ens: med, max, prob, 1โ20) |
GET |
/api/value?ens=med&time=300&lat=52.1&lon=5.2 |
Single-point precipitation rate query (mm/h) |
GET |
/api/timeseries?ens=med&lat=52.1&lon=5.2 |
Complete 6-hour precipitation forecast timeseries for a coordinate |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/metadata/temp |
Available temperature forecast cycles and timestamps |
GET |
/api/data/temp/:time |
Lossless RG-packed temperature slice WebP |
GET |
/api/timeseries/temp?lat=52.1&lon=5.2 |
48-hour temperature trend for a coordinate |
GET |
/api/metadata/wind |
Available wind forecast cycles and timestamps |
GET |
/api/data/wind/:height/:time |
U/V vector packed WebP for wind speed/direction |
GET |
/api/timeseries/wind?lat=52.1&lon=5.2 |
Wind speed (m/s & Bft) and direction timeseries |
GET |
/api/metadata/solar |
Solar radiation forecast metadata |
GET |
/api/data/solar/:time |
Packed solar irradiance WebP ( |
GET |
/api/timeseries/solar?lat=52.1&lon=5.2 |
Solar irradiance timeseries |
1. Lossless RG-Packed WebP Protocol
Traditional map overlays stream pre-colored raster images, preventing client-side thresholding, dynamic color ramps, or client-side math. Nimbus encodes high-precision 16-bit unsigned integers (u16) into standard 8-bit Red and Green image channels:
The WebGL fragment shader unpacks this value in zero overhead directly on the GPU, applying dynamic colormaps and threshold filters in real time.
2. Pre-calculated Projection Look-Up Tables (LUT)
KNMI raw data uses a Polar Stereographic projection, whereas modern web maps operate on Web Mercator (EPSG:3857). Converting coordinates per-pixel at runtime is computationally expensive. On startup, Nimbus computes a Bilinear Interpolation Look-Up Table mapping output Mercator grid cells to fractional input grid coordinates, allowing Rayon-powered multi-threaded slice slicing in milliseconds.
3. GPU Wind Particle Simulation
Wind vector simulation is executed on the GPU using Ping-Pong Framebuffer Objects (FBOs). Particle coordinates are packed into floating-point textures, advected along the U/V wind velocity vector field, and faded with an alpha decay buffer to render smooth streamline trails at 60 FPS.
Contributions, issues, and feature requests are welcome!
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please ensure code conforms to project formatting and linting:
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings- KNMI Open Data Platform for providing open meteorological radar and NWP datasets.
- MapLibre GL for the open-source map rendering engine.
Distributed under the MIT License. See LICENSE for more information.


