Files
Europa/Nuvolari
Alby96andClaude Opus 5 f434a68155 Replace the default Flutter icon with a stylised cloud
The app shipped the Flutter template's blue F, which said nothing about what it
does and did not match the interface. The launcher icon is now a white cloud on
the same seed blue the app themes itself with, so the two read as one product.

The icon is drawn rather than hand-edited: tool/generate_icon.py renders it from
signed distance fields — a union of three circles and a rounded box — using only
the standard library, so regenerating it needs no image toolchain. The shape's
framing is derived from its own bounding box, which is what keeps it centred;
maintaining the bounds separately from the shape had it drifting off-centre.

Adds the adaptive icon and the Android 13 monochrome layer, which were missing
entirely. The generator frames the cloud against the 72dp the launcher mask
always keeps and adaptive_icon_foreground_inset is 0, so the layer is not shrunk
twice and the icon reads at the same size as its neighbours on a home screen.

Verified on the emulator: the cloud appears in the app drawer and holds its shape
down to 48px. docs/architecture.md records how to regenerate it, including the
flutter_launcher_icons 0.14.4 bug that writes a string into a boolean Xcode
setting and needs reverting by hand afterwards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 22:44:33 +02:00
..

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.

The credits are on the Sources screen, reached from the settings button over the map. There is no permanent credit line on the map itself: the OSMF attribution guidelines allow the licence information to sit behind an "About option in a menu" so long as it stays findable, and a test asserts that route still exists.

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.