The Flutter app IT staff and vendors carried into the field across seven Pelindo III branches — inventory, daily checks, reports, and alerts. [Flutter, Dart].
Risa is the mobile half of the IT asset and maintenance system whose backend I also built. It went to IT staff and vendors across seven Pelindo III branches in Kalimantan: Banjarmasin, Sampit, Bagendang, Kotabaru, Batulicin, Kumai, and Bumiharjo.
It is a ground-up rewrite of ITventory, which I had built the year before in Kotlin against a Flask backend. Same problem, same users, same port — no code carried over, only what I had learned from running the first one.
It shipped through the Play Store but was never open to the public — access was restricted to Pelindo staff, and the listing has since been taken down.

The daily check is the screen that got the most use, and it is built around the shift the technician is actually working — the list they are handed is generated for that moment, and an item someone flagged as a problem keeps coming back on the next check until it is resolved.
Two details mattered more than they look. Photo evidence is captured and compressed on the device before upload, which is the difference between a report that sends and one that times out. And the search field is a single box: type a name or an IP and the device comes back whatever category it belongs to. That is the user-facing end of the gen_unit projection described in the backend article — the app is the reason that mechanism exists.
PDF reports are generated server-side and opened on the device. Alerts arrive through Firebase Messaging when the backend’s hourly job finds a camera failing its ping.
The three Android apps before this one — Kamus IT, ITventory, and ECDR — were Kotlin with Retrofit and MVVM. Risa is where I moved to Flutter, and it is still the stack I reach for when I need a mobile app. Rewriting an app I already knew inside out was the right place to change language: the requirements were settled, so the only unknown left was the tooling.
api → models → providers → screens, which is the same separation the backend uses, one layer thinner. Dio handles HTTP, json_serializable generates the models through build_runner, and Provider holds the state each screen listens to.