I Built an Offline-Capable App by Myself: React Native Frontend, C# Backend
This isn’t a story about gluing together a few UI components. It’s about how I, as a solo developer, built a complete mobile application that works offline, syncs data automatically when online, and shares a unified backend with a web-based admin panel. The frontend is built with React Native, and the backend is written in C# using ASP.NET Core.
What may sound like a team-level system can absolutely be done by one person — as long as the structure is clear.
📱 Frontend Architecture: React Native + SQLite + Sync Engine
The mobile client is built with React Native and uses SQLite for local data persistence. The architecture is layered and clean:
- Screens: Each business flow (task detail, photo capture, data entry) is isolated in a screen module
- Components: Reusable UI components like buttons, inputs, modals
- Models: Typed data structures, all aligned with the backend’s field naming (snake_case)
- Services: Business logic, validation, task management, and offline state marking
- Database Manager (dbManager): Centralized SQLite table schema and query wrapper
- Sync Scheduler (syncScheduler): Responsible for marking dirty records, triggering sync, handling conflict resolution, and status tracking
For example: the user records a reading and takes a photo — that data is stored in SQLite and flagged as dirty=1
. The sync scheduler runs in the background every few minutes. If the network is available, it pushes dirty data to the server and marks it clean after confirmation.
🌐 Backend Architecture: ASP.NET Core Web API + EF Core + SQL Server
The backend uses ASP.NET Core Web API with EF Core for data access, and it serves both the mobile app and the web admin portal.
- EF Core (Code First): Manages models, migrations, and database operations
- All APIs use standardized fields:
device_id
,local_id
, andlast_modified
to support de-duplication and conflict detection - Table schema includes
updated_at
,is_deleted
, andsynced
to track versioning and sync status - The web admin frontend consumes the same APIs as the mobile app, enabling shared business logic
- Token-based authentication and user-based data isolation are enforced at the API level
The backend was originally built to serve mobile, but as needs expanded, the web portal re-used the entire service layer without code duplication.
🔁 Sync Mechanism Design
The sync logic is simple but solid:
- Local changes are marked with
dirty=1
- Background job checks connectivity every X minutes
- Dirty records are POSTed to the backend
- Backend accepts the data if
updated_at
is newer, or rejects with status - Cleaned-up entries get
dirty=0
andsynced_at
timestamps - The client can pull downstream changes and apply patches
Manual sync via a button is also available for power users or critical moments.
✅ Key Highlights
- Mobile app works fully offline, including photo capture and data entry
- Syncing is automatic and happens in the background
- Shared API layer supports both mobile and web, no redundant logic
- EF Core provides a structured, version-controlled schema
- Lightweight deployment and maintenance for solo or small-team projects
🧩 Tech Stack
- React Native (with TypeScript)
- SQLite (via expo-sqlite)
- ASP.NET Core Web API
- EF Core + SQL Server
- GitHub Actions (for CI/CD and APK builds)
- Web Admin Panel (uses same APIs)
What started as a local data collection app turned into a complete system — from offline-first mobile UX to centralized backend logic and admin tools.
Sometimes, building a robust system doesn’t require complex tooling or a big team. If you clearly define boundaries, stick to responsibilities, and don’t over-engineer, one person can ship a production-grade full-stack app.