# Indennizzo Diretto

> The paper car-accident statement, rebuilt as a guided flow on the phone.

Case study by Paolo Gianfelici (Full-stack developer & UI/UX designer). https://paologianfelici.com/work/indennizzo-diretto

- **Role:** Flutter developer: the whole client app
- **Client:** LC Solutions
- **Period:** 2021–2023
- **Platforms:** iOS, Android and web from one codebase
- **Stack:** Flutter, Dart, BLoC + RxDart, REST API, Firebase Messaging, Geolocation, PDF
- **App Store:** https://apps.apple.com/it/app/indennizzo-diretto/id1566892543
- **Google Play:** https://play.google.com/store/apps/details?id=com.indennizzodiretto.app

After a car accident in Italy both drivers fill in the CAI, the “constatazione amichevole di incidente”: a dense two-column paper form most people meet for the first time at the roadside, usually shaken and in a hurry.

Indennizzo Diretto turned that form into eight guided steps on the phone (GPS for the place, the camera for the evidence, a finger for the signatures), then took over the claim with the insurer on the driver’s behalf and kept them posted on its progress.

*Released on the App Store and Google Play in 2021 and still there, updated as recently as May 2026. Everything on this page comes from the app code of my time on the project, running against a stand-in backend I rebuilt for this portfolio: the live service and its customers’ claims are never touched.*

- 8: guided steps replace the paper form
- 3: platforms from a single Flutter codebase
- 18k: lines of Dart in the client
- 96%: of the app’s commits are mine (239 of 248)

## From the roadside to a signed statement

### A form that fills itself where it can

Date and time come from the clock, the address from GPS through reverse geocoding, personal details from the profile. Brand, model and insurer are looked up on the server as you type. The first answer (two vehicles, a pile-up, or a pedestrian) decides which of the following steps are needed at all.

### Evidence collected on the spot

Driving licence photos, guided shots of the damage from suggested angles, a tap on the car outline to mark the first point of impact, a voice memo describing what happened, and witnesses with their documents. Every attachment is uploaded as it is taken and downloaded again as thumbnails when the claim is reopened.

### The official layout, translated

The statement’s seventeen standard circumstances keep the two-column logic of the paper form, colour-coded like the original: blue for vehicle A, yellow for vehicle B. The counterpart’s sections switch the whole screen to yellow so both drivers always know whose data is on screen.

### Signed on the glass, delivered as a PDF

Both drivers sign on the phone, along the long side of the screen for a full-width signature. After accepting the mandate, the claim is submitted and the official statement comes back as a PDF, compiled and signed, rendered inside the app.

### Following the claim

Submitted claims become read-only and the stepper turns into free navigation. Status changes arrive as push notifications, and the support desk is one tap away on WhatsApp or SMS from every screen.

### Getting in

A three-page intro, a guest mode with a demo claim to explore before committing, registration with e-mail verification, and sign-in with e-mail, Facebook, Google or Apple.

## One codebase, three platforms

The same Flutter code shipped to iOS and Android and also ran on the web. Above 800 px the bottom bar becomes a side menu and the forms sit in a readable column; platform differences (secure storage, camera, audio recording, push) are isolated behind small wrappers.

## How it was built

### State and structure

Screens are driven by hand-rolled BLoCs on RxDart streams (22 of them, one per screen or form step), with an inherited widget carrying the session. A parent BLoC owns the claim being edited; each step validates, saves its slice to the API and hands the updated model back, so a claim can be abandoned and resumed at any step.

### Talking to the backend

A thin REST layer with bearer tokens and transparent re-authentication, multipart uploads for photos, signatures and audio, and explicit request/response mappers between the server’s JSON and the app’s models.

### Device features

Geolocation with OpenStreetMap geocoding and address autocomplete, camera capture, audio recording and playback, a signature pad, in-app PDF rendering, and Firebase Cloud Messaging with local notifications.

## The real app, running on its own: Not a mock-up: the original app, running again

Without its servers the app cannot get past the login screen, and those servers are a live service holding real people’s accident claims. Rather than mock up pictures of it, I made the real code run on its own: in a browser, with nothing behind it.

- **A backend that lives in the app.** The network layer now hands every request to an in-memory mock that speaks the same routes and JSON as the original API. Services, models and BLoCs run unchanged: what you see is the production UI doing its real work against fictional data.
- **Documents generated on the fly.** The statement and mandate PDFs used to be produced server-side. The demo lays them out in Dart from whatever was typed into the form, including both signatures, the impact sketch and the photos.
- **Stand-ins for the hardware.** Camera, microphone and GPS are replaced with sample photos, a recorded voice memo and a fixed position, so the full flow works in a browser tab without asking for a single permission.
- **Recorded by a script, not by hand.** Flutter draws on a canvas, so there is no DOM to click. A Playwright storyboard finds widgets through Flutter’s accessibility tree, drives them with real touch events and records Chrome’s screencast at device resolution. Every clip and screenshot here can be regenerated with one command.

All people, plates and claims shown are fictional. Contact details and API keys were removed from the demo build.

## Recordings

- **Filing a claim, start to finish** (224 s): The whole accident statement in eight guided steps: place and time from GPS, both vehicles and drivers, photos, point of impact, circumstances, a voice memo, witnesses, both signatures. Then the official document is generated. https://paologianfelici.com/media/indennizzo-diretto/clips/new-claim.mp4?v=db10583407
- **Filing a claim, fast forward** (75 s): The same recording at 3x: a complete claim in about a minute. https://paologianfelici.com/media/indennizzo-diretto/clips/new-claim-reel.mp4?v=5f69c0da47
- **Onboarding and sign-in** (26 s): Three-page intro, guest mode with a demo claim, then email sign-in (Facebook, Google and Apple sign-in were also supported). https://paologianfelici.com/media/indennizzo-diretto/clips/onboarding.mp4?v=4c1819ebab
- **Creating an account** (40 s): Guests are sent to sign-in when they start a claim. Registration with consent, e-mail verification code, then an empty claims list. https://paologianfelici.com/media/indennizzo-diretto/clips/signup.mp4?v=028a3b427f
- **Following a claim** (51 s): Opening a submitted claim: read-only steps with photos and impact point, summary, signatures, the generated PDF, then notifications, profile and settings. https://paologianfelici.com/media/indennizzo-diretto/clips/browse.mp4?v=6a721ebf32
- **The same code on a large screen** (28 s): The Flutter codebase also targeted the web: above 800px the bottom bar becomes a side menu and forms are centred. https://paologianfelici.com/media/indennizzo-diretto/clips/desktop.mp4?v=b015efaba3
