Scanned the two public ARPA Piemonte APIs and recorded what they actually contain, so this question does not get re-litigated from the marketing pages later. Neither needs a key, a token or a registration. This corrects something I got wrong. The docs said ARPA states no licence for its data, based on the open-data page saying only "gratuiti". The site's legal notice does state one — CC BY 4.0, commercial use explicitly permitted, credit "Fonte: Arpa Piemonte - www.arpa.piemonte.it" — and both APIs link that notice from their OpenAPI description, so anything they serve is covered. Only the radar volumes remain ambiguous, because their own page does not repeat the licence and the access link is still issued by email; both questions belong in the same message to ARPA. The survey's operative findings: - api_realtime carries 374 stations with coordinates, of which 286 have a rain gauge, spanning 74 m to 2820 m of elevation. - Its observations lag by about 4.5 hours on an hourly cadence, measured uniformly across every station sampled. That is the property that decides how it can be used: it is an observation archive with a publishing delay, not a real-time feed, and it must never sit next to 5-minute radar looking current. - Only 4 of 143 hydrometer stations publish guard and danger thresholds, and 5 publish a river name. A river-level warning built on this would be empty for 97% of stations, so that idea is recorded as rejected rather than pending. - Meteoweb is a 3.27-million-record historical archive plus a seismic catalogue: a research dataset, not app content. One thing is worth adopting: rain-gauge accumulations as ground truth for the radar. Radar infers rainfall from reflectivity aloft, gauges measure what reached the ground, and the network is densest exactly where Alpine terrain blocks the beam. It belongs behind the worker, clearly timestamped, once the worker exists. Also notes that the credit ARPA asks for is the full "Fonte: Arpa Piemonte - www.arpa.piemonte.it", not the bare name currently in the region config, to be adopted the moment any ARPA-sourced data is displayed. No code changes: nothing is integrated yet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nuvolari
Precipitation radar for Piedmont, Italy. Android first, iOS later, one Flutter codebase.
Radar imagery comes from the public Radar-DPC platform and weather alerts from the ARPA Piemonte XML-CAP bulletin, drawn over an OpenStreetMap base map. The app is free, with no advertising and no accounts.
Scope: radar, official alerts, rain notifications. No forecasts, no lightning, no home-screen widget. See CLAUDE.md.
Nuvolari is an independent app. It is not affiliated with, endorsed by, or operated by ARPA Piemonte or the Dipartimento della Protezione Civile. For civil-protection purposes the official channels always prevail.
Layout
app/ Flutter application (Dart package "nuvolari")
backend/ Python worker: fetches DPC rasters, crops, reprojects, renders PNG frames
docs/ architecture, data sources, licenses, stack decisions, roadmap, privacy
tool/ verification scripts
Start with docs/architecture.md, then docs/roadmap.md for what is built and what is next.
Toolchain
| Tool | Version |
|---|---|
| Flutter | 3.47.3 stable (Dart 3.13.3) |
| Android SDK | platform 36, build-tools 36.0.0, platform-tools |
| JDK | 21 |
| Python | 3.12+ (3.14 works; rasterio ships wheels for it) |
| Android NDK | 28.2.13676358 — pinned by maplibre_gl, not by this project |
A full toolchain plus a warm Gradle cache needs roughly 14 GB of disk: Flutter
3 GB, Android SDK 2.5 GB (2 GB of which is the NDK the map plugin pins), the Gradle
cache 5 GB, and build output around 2 GB. flutter clean reclaims the last of those.
Configuration
Secrets never enter the repository. Copy the template and fill it in:
cp env.example.json env.json # env.json is git-ignored
| Key | Purpose |
|---|---|
MAP_STYLE_URL |
MapLibre style URL. Empty uses the free OpenFreeMap style; offline forces the bundled no-network style. |
RADAR_MANIFEST_URL |
Base URL of the published manifest.json. |
RADAR_SOURCE |
mock (offline demo), dpc (live), arpa (disabled stub). |
REGION_ID |
Which region config to load. Defaults to piemonte. |
Running
cd app
flutter run --dart-define-from-file=../env.json
With no env.json the app starts in demo mode: mock radar frames from assets on the
free OpenFreeMap base map. No credentials are needed for anything — OpenFreeMap has
no API key and no signup.
The radar frames work with no network at all. The base map needs one; run with
--dart-define=MAP_STYLE_URL=offline to drop it too and work entirely offline.
Debugging in VS Code
Open the Nuvolari folder as the workspace root — the configurations in
.vscode/ are relative to it. Then pick one in Run and Debug and press F5:
| Configuration | Use it for |
|---|---|
| Nuvolari — debug (emulatore) | Everyday work. Demo mode, no env.json needed, hot reload on save. |
| Nuvolari — profile | Judging animation smoothness. Debug builds run the Dart VM unoptimised, so the radar timeline always looks worse than it is — never assess it in debug. |
| Nuvolari — debug con env.json | Pointing the app at a live radar manifest or a different base map style. |
| Nuvolari — debug su Windows | Fast UI iteration with no emulator. The native map does not render here. |
| Test — tutti / Test — file corrente | Debugging tests with breakpoints. |
Every emulator configuration runs tool/start_emulator.ps1 first, so F5 works from a
cold machine. The script exits immediately when a device is already attached, so
pressing F5 twice does not start two emulators.
Ctrl+Shift+B runs the full verification. Other tasks live under
Terminal → Run Task: quick verification, regenerating the demo radar frames, and
shutting the emulator down.
Verifying
.\tool\verify.ps1 # format, analyze, test, build, lint, pytest
.\tool\verify.ps1 -SkipBuild # fast inner loop
Stages whose target does not exist yet are skipped, so this runs from day one.
Attribution
Radar-DPC (CC BY-SA) · Arpa Piemonte · © OpenStreetMap contributors (ODbL) · © OpenMapTiles · OpenFreeMap.
See docs/licenses.md for the obligations these carry — in
particular, the rendered radar frames are a derived product of CC BY-SA data and inherit
share-alike, and the OpenFreeMap style ships no attribution field, so the app has to
render the map credits itself.