Full-Stack Case Study: How We Built a Scalable Web + Mobile Platform End-to-End

This case study is a composite drawn from patterns across several engagements of a similar shape; specific details, numbers, and the client's identity have been changed or generalized rather than describing one real account.
A mid-market operations platform — call it the kind of internal-facing-but-customer-visible tool that logistics, field-service, and healthcare-adjacent companies all end up needing eventually — came to us with a familiar starting point: a legacy admin dashboard nobody wanted to touch, no mobile presence at all despite half their field users being on phones all day, and a six-month runway before an investor-driven deadline to show a modernized platform. Here's the actual shape of what we built, and the decisions that mattered.
Starting constraints, honestly stated
Three constraints shaped every decision that followed: a five-person engineering team on the client side (meaning our team needed to build something they could own and extend after we left, not a system requiring specialized expertise to touch), a hard deadline that made a full rewrite-and-cutover too risky, and an existing Postgres database with years of real operational data that had to migrate cleanly, not get left behind.
Architecture decisions
We landed on a single backend serving both a web admin console and a mobile field app, rather than separate backends per platform — the business logic (job assignment, status transitions, compliance rules) is identical regardless of which client is calling it, and maintaining two backends for the same domain logic would have meant every rule change shipped twice, with the two inevitably drifting. A single Next.js application handled the web admin console (server-rendered for the data-dense internal views, where SEO doesn't matter but fast, boring page loads for people using this tool eight hours a day do), backed by a shared PostgreSQL database via Supabase — chosen specifically because the client's five-person team needed to own auth, database, and storage without hiring a dedicated backend infrastructure engineer, and Supabase's managed Postgres plus built-in row-level security policies gave them a real, production-grade data layer without that hire.
The mobile app — used by field technicians, often on spotty connectivity in the field — was the one place the architecture diverged meaningfully from the web app's assumptions: it needed genuine offline support, not just a loading spinner on a bad connection. We built it in React Native with a local SQLite store (via WatermelonDB) as the source of truth for the mobile client, syncing bidirectionally with the backend when connectivity allowed, with a conflict-resolution strategy (last-write-wins on most fields, with a small set of fields — job completion status specifically — using a stricter server-authoritative rule to prevent a stale offline device from ever overwriting a job another technician had already closed out). This is the single piece of the system that took the most design iteration, and for good reason: offline sync is one of the few areas in this kind of project where getting it subtly wrong doesn't fail loudly, it corrupts data quietly.
The web admin console is the system of record when connectivity is reliable. The mobile app's whole job is behaving correctly when it isn't — that asymmetry drove almost every mobile-specific architecture decision.
Stack choices and why
Next.js + Supabase for the reasons covered in more depth elsewhere on this blog: it minimized custom infrastructure for a small team to own long-term, and got the team to a working admin console fast enough to leave real runway for the harder mobile-offline problem.
React Native + WatermelonDB for mobile specifically because of the offline requirement above — WatermelonDB's local-first architecture (SQLite-backed, built for exactly this sync-when-possible pattern) fit better than a simpler REST-cache approach would have for a client base that regularly loses signal for hours in the field.
A shared TypeScript package for domain types and validation logic (Zod schemas) between the Next.js admin app and the React Native mobile app, following the same shared-core pattern we've written about separately — job status transitions, permission checks, and form validation rules lived in one place and were imported by both platforms, which mattered enormously for a small team: a business rule change (a new required field for job completion, added mid-project when a compliance requirement changed) was one pull request that updated both platforms' validation simultaneously, not two PRs that could drift.
Supabase Storage for the photo documentation field technicians attach to completed jobs, with images uploaded directly from the mobile app (including queuing uploads for when connectivity returned, part of the same offline-sync design) rather than round-tripping through the backend — simpler infrastructure and lower latency for a genuinely bandwidth-constrained user base.
Delivery pipeline
Given the fixed deadline, we ran the engagement in weekly milestones with a demoable build at the end of each one — a discipline covered in more detail in our piece on scoping fixed-price projects — specifically so scope risk on the harder offline-sync work surfaced in week 4, not week 20. CI ran the full test suite (including a set of integration tests specifically simulating offline-then-reconnect scenarios for the mobile sync logic, since that's exactly the class of bug that's invisible in a demo on office wifi and very visible in the field) on every pull request, gating merges. Web deploys went through Vercel with preview deployments per PR; mobile builds ran through Fastlane into TestFlight and an internal Android track for the client's field team to validate each iteration against real job data before anything reached the App Store or Play Store proper.
Outcome
The platform launched within the deadline with both the web admin console and the mobile field app live, on a shared backend, maintained since handoff entirely by the client's own five-person team — which was the actual measure of success we were building toward, not just "does it ship." Field technicians moved from a paper-and-phone-call workflow to structured mobile job updates that sync automatically once back in signal range, and the client's own team has since extended the platform (adding new job types, new compliance fields) without needing to bring in outside help for those changes — the shared-core architecture and the documentation habits from our production-readiness checklist meant the handoff actually held.
None of the individual pieces here are novel in isolation — Next.js, Supabase, React Native, and offline-first mobile sync are all well-understood tools independently. What made this project work was less any single technology choice and more the discipline of a single shared backend and shared domain logic across both platforms, and building the mobile app's architecture around its actual constraint (unreliable connectivity) instead of pretending that constraint away until it caused a data-integrity incident in production.