TL;DR
- A mid-sized construction company had 18 field engineers dispatching and reporting jobs entirely through a WhatsApp group — with zero structured data and a 31% monthly documentation gap rate.
- We built an offline-first Flutter app for iOS and Android that assigns jobs, captures work records and site photos, and collects digital sign-offs — all without requiring live connectivity on site.
- The app authenticates via Azure AD (MSAL), reads and writes to SharePoint Lists through Microsoft Graph, and triggers Power Automate flows for manager notifications and escalations.
- Job confirmation time dropped from 4.2 hours to 23 minutes. Documentation gaps fell from 31% to 0.3%. The whole thing was live in 10 weeks.
The WhatsApp Problem Nobody Talked About
When the operations manager at this construction company first called us, she didn't use the word "chaos." She said their communication was "a bit informal." That was an understatement that became clearer with every conversation we had over the following two weeks.
The setup: 18 field engineers spread across active sites, reporting into 3 site managers. Every morning, jobs were dispatched via a WhatsApp group called "Team Jobs." An engineer would get tagged in a message: "Ravi — Unit 4B plumbing inspection, before noon." Ravi would respond with a thumbs-up. By the time he'd finished, he'd upload two or three photos to the group, type "done," and move on to the next job.
On paper, this sounds like it works. In practice, it produced a stream of problems that compounded daily:
- No structured timestamps. "Done" could mean 10:47 AM or 3:15 PM. Nobody knew. Invoicing disputes with subcontractors had no reliable reference point.
- Photos mixed with everything else. Site inspection photos sat in the same thread as birthday wishes, cricket match commentary, and forwarded memes. Finding a specific photo from three weeks ago took 20 minutes of scrolling.
- No audit trail on job completion. If a client disputed whether a job had been done before a certain date, the evidence was a chat message. No GPS stamp. No sign-off. No structured record.
- The admin bottleneck. One office admin spent roughly 90 minutes every day copying job completions out of WhatsApp and into an Excel sheet. That sheet was then emailed to managers as a PDF.
- 31% documentation gap rate. Their monthly internal audit showed that nearly a third of all completed jobs had at least one missing data point — photo, completion time, engineer name, or job description — when reviewed 30 days later.
The operations manager had tried three things before calling us: a stricter naming convention for photos, a second WhatsApp group for "completed jobs only," and a shared Google Sheet. None of them stuck past the second week. The engineers were on site, on their phones, doing physical work. Anything that required extra steps got skipped.
What the Client Actually Needed
When we ran our discovery sessions, the client said they wanted "something like WhatsApp but more organised." That framing was understandable — WhatsApp had genuinely low friction, and the team was comfortable with it. But what they were describing wasn't a messaging tool problem. It was a structured data collection problem.
WhatsApp is designed for conversation. It isn't designed to be a job management system, a document store, or an audit trail. Trying to use it as one is like using a group SMS thread to run a CRM. The engineers weren't failing to use WhatsApp correctly — they were using a tool that was never designed for what they needed it to do.
What the business actually needed was straightforward once we framed it properly:
- A single place where jobs appear, with all relevant details pre-filled by the manager
- A way for engineers to record work completion with photos, notes, and a timestamp — without any manual data entry overhead
- Automatic storage of all records in a system the business already owned and could query
- A management view that didn't require anyone to compile anything manually
Critically, the system had to work without reliable internet access. Construction sites are not offices. Signal drops, basement levels, temporary structures, rural plots — connectivity is unpredictable. Any solution that assumed a live connection would fail within the first week.
The Flutter App We Built in 10 Weeks
We built a single Flutter codebase that shipped to both iOS and Android. The app is the only tool engineers need on site — it replaces the WhatsApp group entirely for job-related communication.
How jobs flow through the app
A site manager creates a job directly in a SharePoint List via a Power Apps form on their desktop — or on their phone through the same Flutter app with a manager role. The job record includes the assigned engineer, site address, job type, priority, and any pre-loaded instructions or checklist items.
The Flutter app polls for new jobs via the Microsoft Graph API and stores the full job record locally using sqflite. When an engineer opens the app on site, their assigned jobs are already there — regardless of whether they have signal.
On the job detail screen, the engineer can:
- View all pre-filled job details and instructions
- Work through a checklist (custom per job type) with pass/fail toggles
- Capture photos directly from camera or gallery — compressed and stored locally
- Add a free-text completion note
- Capture a digital signature from the site contact
- Mark the job complete — which sets a UTC timestamp on the local record
None of these steps require a network connection. Everything is written to local SQLite first. When connectivity returns — whether that's walking back to the site office or driving off site — the sync queue fires automatically in the background, pushing all completed job records and photos up to SharePoint via Graph API batch requests.
The management side
Site managers and the operations director see a Power BI report embedded in their SharePoint intranet. It shows live job status by engineer, site, and job type. Because data comes from SharePoint Lists — the single source of truth — the dashboard is always current once syncs land. No one compiles anything manually. The 90-minutes-a-day admin job simply stopped existing.
Why Offline-First Was Non-Negotiable
The phrase "offline-first" gets used loosely. In this context it means something specific: the app never requires a network connection to function. Every user action — reading job details, submitting a checklist, saving a photo, marking complete — writes to the local SQLite database first. The UI never awaits a network response to show the user feedback. The network is treated as an optimistic delivery channel, not a dependency.
This matters on construction sites because connectivity is genuinely unreliable. Basement levels, reinforced concrete structures, rural plots without mobile coverage, and temporary site compounds without Wi-Fi are all real scenarios the engineers encountered daily. An app that requires a live connection will fail in exactly these situations — when the engineer is actually doing the work and needs to record it.
In an offline-first app, the local database is the primary store — not a cache. The sync layer is responsible for reconciling local state with the server, not the other way around. Design your data model for the local store first, then design the sync protocol.
The sync queue pattern in practice
We implemented a sync queue using a dedicated sync_queue table in SQLite. Every time the app writes a completed job record, a corresponding row is inserted into the sync queue with the record ID, record type, operation (create/update), and a status of pending. A background isolate monitors connectivity using the connectivity_plus package and, on reconnection, processes the queue in order.
The key packages in pubspec.yaml for this architecture:
dependencies:
sqflite: ^2.3.3 # Local SQLite storage
path_provider: ^2.1.3 # Resolves device file paths
connectivity_plus: ^6.0.3 # Monitors network state
msal_auth: ^1.0.3 # Microsoft MSAL for Azure AD auth
http: ^1.2.1 # HTTP client for Graph API calls
image_picker: ^1.1.2 # Camera and gallery access
signature: ^5.4.1 # Digital signature capture
The sync worker processes one record at a time, marks it synced on success, or leaves it in pending with a retry counter on failure. Photos are uploaded to a SharePoint Document Library via a multipart Graph API request, with the returned file URL written back to the job record in SharePoint Lists. The engineer never waits for any of this — it all happens in the background after they've moved to the next job.
SharePoint as the Single Source of Truth
A natural question at this stage is: why SharePoint? Why not a custom backend, or Firebase, or Supabase?
The answer is that this client was already a Microsoft 365 organisation. They had SharePoint. They had Azure AD with all 21 staff already provisioned. They had Power BI licences. They had Power Automate. Adding a new backend would have meant adding a new subscription, new user management, a new admin burden, and new security review cycles — for infrastructure that was functionally a duplicate of what they already owned.
If your client is already on Microsoft 365, using SharePoint as the data layer eliminates the need for a separate backend, database hosting, and identity provider — potentially saving thousands per year in infrastructure costs. MSAL gives you enterprise SSO for free.
Authentication via MSAL and Azure AD
The Flutter app authenticates using the msal_auth package against the company's Azure AD tenant. Engineers sign in once with their work Microsoft account — the same credentials they use for Outlook and Teams. There is no separate username or password to remember, no separate user database to maintain, and no password reset emails for us to handle. Azure AD handles all of it.
We registered the Flutter app as an Azure AD App Registration with delegated permissions for Sites.ReadWrite.All and Files.ReadWrite.All. The acquired token is stored securely in the device keychain and refreshed silently by MSAL. From the engineer's perspective, they tap "Sign in with Microsoft" once during onboarding and never see an authentication prompt again unless their session expires after 90 days.
Microsoft Graph API calls
All data operations go through the Microsoft Graph API rather than the legacy SharePoint REST API. Graph is faster, better documented, and supports batch requests — which we use heavily for the sync queue to push multiple job updates in a single HTTP round-trip rather than one call per job.
Jobs are stored as items in a SharePoint List with columns mapped to the job data model. Photos go to a Document Library organised by job ID. Power Automate watches the list with an "When an item is modified" trigger — when a job's status column changes to "Complete," it fires a notification to the relevant site manager's Teams channel and updates a separate KPI list used by the Power BI report.
What Happened After Go-Live
We ran a two-week parallel period where both WhatsApp and the Flutter app were used simultaneously. This was the client's idea and it was the right call — it let engineers get comfortable with the new tool without the pressure of it being the only option. By day nine, most engineers had stopped using the WhatsApp group voluntarily. By the end of week two, the group was silent.
The operations manager's response after the first full month:
"The biggest shock wasn't the dashboard — it was the silence. I used to check the WhatsApp group 40 times a day to piece together what was happening on site. Now I open Power BI once in the morning and once before end of day. I know exactly what's been done, what's pending, and which engineer is running behind. I haven't sent a 'please confirm' message in three weeks."
— Operations Manager, construction client (name withheld)
The concrete improvements after 60 days of live use:
- Job confirmation time dropped from an average of 4.2 hours (the time between job completion and management awareness) to 23 minutes — the typical sync + Power Automate notification lag.
- Documentation gaps in monthly audits fell from 31% to 0.3%. The remaining 0.3% was one job where an engineer's phone ran out of battery before sync completed.
- Admin time saved: the 90-minute daily manual extraction process was eliminated entirely. The admin team re-allocated that time to invoice processing.
- Photo retrieval: finding site photos for a specific job went from a 20-minute manual WhatsApp scroll to a 15-second SharePoint search.
One result we didn't anticipate: Power Automate started surfacing a pattern that had previously been invisible. Three specific job types — HVAC pre-inspection, external cladding sign-off, and electrical compliance checks — were consistently taking longer than their allocated time slots. The data had always been there, buried in WhatsApp chat timestamps. Now it was structured, queryable, and visible in Power BI. The operations team used it to revise their job time estimates for those categories, which reduced scheduling conflicts by 18% in the following month.
Key Takeaways
Offline-first is not a feature — it's a prerequisite. If your field app assumes connectivity, it will fail in exactly the moments it needs to work. Design your data model for local storage first; treat the network as a delivery channel.
SharePoint is a legitimate production backend for SMB field apps. If the client is already on Microsoft 365, building against SharePoint Lists and Graph API avoids introducing new infrastructure, new subscriptions, and new security review cycles.
MSAL and Azure AD give you enterprise SSO for free. Engineers sign in once with their existing work credentials. No separate user database, no password resets, no onboarding friction. This is one of the biggest adoption accelerators for M365-adjacent businesses.
Power Automate turns structured job data into proactive operations. Notification flows, escalation triggers, and KPI calculations that previously required manual checks can all be automated once the underlying data is structured and in SharePoint.
Field adoption is won or lost in the first two weeks. A parallel running period — where the old system and the new one coexist — removes psychological pressure from engineers and lets the new tool prove itself on its own merits. Don't force a hard cutover on day one.
Frequently Asked Questions
Ready to replace WhatsApp with a real app?
We build offline-first Flutter apps for field teams — synced to SharePoint, authenticated via Azure AD, deployed to iOS and Android in weeks.