During COVID, entering Sarawak meant approval through one mandatory state gate — a single system serving three very different users: travellers, frontline officers, and a command centre.
My role
Front-end engineer, Ukuya — top contributor across the three apps (266 of 499 commits)
Result
Shipped three production Flutter apps that ran the mandatory entry-approval flow end to end — apply, verify at the border, and decide — through the pandemic.
01The problem
When Sarawak controlled its borders during COVID-19, every non-Sarawakian had to be approved before entering. enterSarawak was the state's official system for that — the single mandatory gate for entering the state, run by the State Disaster Management Committee — and it had three sides: the public applies and carries a QR entry pass, enforcement officers verify and process arrivals at entry points, and a command centre reviews and decides. I built the front end at Ukuya — the largest contributor across all three Flutter apps, with 266 of the 499 commits on an eight-person team.
02A look at the app
03What I built
Built three Flutter apps for the three sides of the system: the public app (apply, upload documents, carry a QR entry pass, track status on a timeline), an officer app to verify and process travellers at entry points, and an admin Command Centre to review and decide applications.
Generated each approved traveller's QR entry pass with qr_flutter for officers to scan at the border.
Cached data on-device with Hive and gated access with device biometrics (local_auth), for frontline use on patchy connections.
Built on a shared in-house Flutter package ecosystem (~24 ukuya_* packages — OAuth, DI, API clients, form fields, validation, i18n, file handling) so the three apps stayed consistent and shipped fast.
Typed models with Freezed, code-generated routing with auto_route, Provider for state, and Sentry crash reporting in production.
04Key decisions
One system, three focused apps
Travellers, officers, and the command centre have completely different jobs, so each got its own app instead of one overloaded build — the public app tuned for applying and carrying a pass, the officer app for fast verification, the admin app for review and decisions.
Shared packages, not copy-paste
The three apps run on a common in-house package set — auth/OAuth, DI, API clients, form fields, validators, i18n — versioned through a private pub server. Shared behaviour lives in one place, so a fix or design change lands across all three apps instead of being copy-pasted into drift.
Typed and generated where it counts
Freezed for typed models and auto_route for generated routing keep a large multi-app codebase — 365+ Dart files across the three apps — navigable, with the compiler catching breakage that would otherwise need a test.
05Trade-offs
Front-end role: I built the three client apps against APIs owned by the backend team; the server side and the approval rules weren't mine.
Like a lot of pandemic-era software, it shipped fast under real pressure and leaned on production monitoring (Sentry) rather than an automated test suite.
It was retired when border controls lifted and is no longer on the stores, so this case study points to the SDMC system and press coverage rather than a live download.
06Result
Three production Flutter apps that carried Sarawak's mandatory border-entry approval through the pandemic — for the public, frontline officers, and a command centre. It's the work that taught me to keep three apps coherent across one repo and a shared package set while shipping under real public-health deadlines.
07What I would improve next
Add automated tests — especially contract tests on the shared packages, so one change can't silently break any of the three apps.
Add end-to-end flow tests for the apply → verify → approve path across the apps.
Promote the per-app theming into a single shared design-system layer.