All work

Client work at Mobil80

EZTrak

Organisations tag equipment with QR codes, and field staff scan them to run checks and report faults. I built the mobile app from scratch.

Role
Built the mobile app from scratch
When
Jun 2025 – now
Status
Live on iOS and Android
Platforms
Android, iOS
Built with
Flutter, GetX, AWS Amplify, AppSync GraphQL, Hive, Google Maps

What it is

Organisations tag their equipment with QR codes and use EZTrak to verify and maintain it.

Field staff scan a tag to open the asset’s record, including its documents, certificates and past checks. Verifications run on a schedule, and each one records the phone’s location. When something breaks, a user reports the fault, an admin assigns a technician, and the technician submits an update. Admins set up assets, forms and roles in a separate web portal that shares the app’s AWS Amplify backend.

What I worked on

EZTrak’s web product existed before I joined Mobil80. When the client wanted a mobile app, I built it from scratch in Flutter, starting in June 2025, and I’m still its main mobile developer. 78 of the 95 commits are mine, and the App Store lists 15 releases, from 1.1.0 in September 2025 to 2.5.0 in September 2026.

My work on the app covers the local caching, filters, location capture, the map, deep links, the dashboard redesign with its maintenance calendar, and asset editing with image upload. I also made the Google Play builds and many of the App Store ones. Two colleagues each joined for a couple of weeks in 2025.

Technical notes

Cache-first loading

After login the app fires about a dozen API requests in parallel and stores the responses in Hive. Screens open from the cache straight away and refresh in the background. If the network fails at startup but a cached user exists, the session stays alive instead of signing the user out. The fiddly part was that the API returns its data as JSON inside strings, so the cache and network paths have to decode it the same way.

The bottom navigation is built from the user’s role, so a page shows up only if the role can view it. I cached that menu so it appears straight away on the next launch and is then rebuilt from fresh data. I also added a scan-only home screen for users left with one page or fewer, so they can still scan a tag and open an asset.

Registered vs current location

The asset map shows where the asset is registered (R) and where it was last checked (C). A colleague set up the first version. I added the distance between the two points and reworked the zoom, so one point gets a fixed zoom and two points are fitted to their bounds.

QR links on the product’s domain open the app directly through Android App Links and iOS associated domains. I fixed a bug where links that launched the app were handled twice, because the link stream already delivers the launch link and the code was also asking for it separately. When the user is signed out, links open in an in-app browser tab, since an external browser would hand the verified domain straight back to the app.