Commit Graph
3 Commits
Author SHA1 Message Date
Alby96andClaude Opus 5 f3a0e3794a Narrow scope to radar, and put the app on a real OpenStreetMap base map
Drops forecasts, lightning, the home-screen widget and advertising. What
remains is radar on a map, the official ARPA alert bulletin, and rain
notifications.

The base map is now OpenFreeMap's Positron style: real OpenStreetMap vector
tiles with no API key, no registration, no request limits and commercial use
permitted. Every other free tier — MapTiler, Stadia, Jawg, Thunderforest —
needs a key, which is a secret to manage, a quota to outgrow and a signup to
complete before anyone can build the project, and the map is the one thing the
app cannot work without. Positron rather than Liberty or Bright because the
radar overlay has to be the loudest thing on screen, and a desaturated grey
base is built to sit under data.

Its style JSON carries no `attribution` field, so MapLibre displays no credits
by itself. The app renders them from the region config instead: the two
mandatory credits, OpenStreetMap and OpenMapTiles, go in the always-visible
bar, and OpenFreeMap's own credit — optional by their terms — is listed on the
Sources screen with the rest. The bundled offline style is still reachable with
MAP_STYLE_URL=offline, and still claims no base map attribution, because
crediting OpenStreetMap while showing it would be a false claim.

Radar-DPC stays the source. ARPA Piemonte's own radar remains a disabled stub
for two reasons that belong to the project owner, not to the code: the
real-time access link is only issued by email, and the open-data page states
the data is "gratuiti" and nothing else. Free of charge is not a licence, and
rendering those volumes into frames served from a CDN is redistribution. Both
questions go in the same email. An earlier draft of the docs recorded ARPA
radar as CC BY 4.0; the source page does not support that, so the claim is
removed rather than carried forward.

The documentation is updated throughout rather than annotated: CLAUDE.md gains
an explicit scope boundary, data-sources drops MET Norway and ISTAT and gains
the base map, licenses records that free of charge is not a licence, privacy
loses the whole advertising section, and the roadmap is renumbered so the
backend worker is next — until it exists, DpcRadarSource has nothing to read.

licenses.md keeps Open-Meteo and Blitzortung listed as excluded even though the
features that would have used them are gone: both are non-commercial-only, ads
are a plausible future, and neither should be adopted on the grounds that there
are none today.

Verified: analyze clean, 130 tests passing, and on the emulator the radar
overlay sits correctly over Piedmont on real OSM tiles with Turin, Milan and
Genoa labelled, the age reads "Aggiornato 4 minuti fa", and the Sources screen
lists all five credits with their licences.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 16:10:29 +02:00
Alby96andClaude Opus 5 d84095b5a8 Add the region map, permanent attribution and the Sources screen
Puts a MapLibre map on screen framed on the region, with the credit
obligations that come with showing third-party data satisfied structurally
rather than by remembering to add a label.

The base map style comes from MAP_STYLE_URL, and with no key configured the
app generates a fallback style from the region's own bounding box: a flat
background and the extent outline, no network sources at all. That keeps a
fresh clone runnable offline without pulling in a boundary dataset that would
carry its own licence, and it deliberately looks like a placeholder so it is
not mistaken for a finished map.

Attribution is driven by what is actually rendered. The bar lists the credits
for the active sources only, because crediting OpenStreetMap while showing the
fallback style would be a false attribution, and it says plainly when no base
map is configured. It sits below the map rather than floating over it so no
map control or gesture overlay can occlude a credit that the ODbL and CC BY-SA
terms require to be visible.

The Sources screen leads with the independence disclaimer, before the sources
it qualifies, so a reader who stops after the first screenful has still seen
it. Sources with no stated licence — ARPA publishes none for the alert
bulletin — say so explicitly rather than being shown bare or given an invented
one. A separate note explains that the rendered radar frames inherit CC BY-SA
from the DPC source data.

Also declares the INTERNET permission in the main manifest: Flutter injects it
into the debug and profile manifests only, so a release build would otherwise
fail every request on device.

Verified: analyze clean, 66 tests passing, appbundle builds with the native
MapLibre plugin. Not verified visually — this machine has no Android device or
emulator image, so nobody has watched the map render.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 11:35:14 +02:00
Alby96andClaude Opus 5 85b2c99949 Scaffold the Flutter app with Italian l10n and region configuration
Creates the app skeleton and the seam everything else in the project hangs
off: region-specific data lives in an asset file, not in code, so adding a
region later is a new JSON file rather than a refactor.

Notable choices:

- applicationId and namespace are it.nuvolari.app rather than the doubled
  it.nuvolari.nuvolari that `flutter create` produces, with the Kotlin package
  and the iOS bundle identifiers moved to match.
- SDK levels are pinned instead of inherited from `flutter.*`. Google Play
  requires API 36, and that is a release blocker rather than something to let a
  Flutter upgrade change silently. minSdk 24 is the highest floor the planned
  dependencies impose.
- Riverpod and Dio-free for now, no code generation: see docs/stack-decisions.md.
- Italian is the l10n source language, so app_it.arb is the template rather
  than a translation of an English original.

The region parser rejects rather than repairs. An inverted bounding box, a map
centre outside its own bounds, an unknown adapter name, a duplicate zone code
or an empty attribution list all throw with the offending field named. Each of
those would otherwise fail silently and visibly wrong: a swapped latitude and
longitude renders the radar in the wrong place, an unknown adapter falling back
to mock would show demo frames where live data was expected, and a missing
attribution is a licence violation rather than a cosmetic gap.

Tests run against the asset that actually ships and against a captured copy of
the live ARPA CAP feed, so the eleven zone codes in the config are checked
against the eleven the feed really emits rather than against a list retyped
from documentation.

Verified: dart format clean, flutter analyze 0 issues, 50 tests passing,
flutter build appbundle --debug produces an AAB with applicationId
it.nuvolari.app, minSdk 24, targetSdk 36.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 11:24:26 +02:00