
mPharma's pharmacy network spans multiple African markets where connectivity is unpredictable by design, not by accident. The existing workflows assumed a live server connection for every transaction — sales, patient records, inventory lookups — which meant a dropped connection didn't just slow things down, it stopped the pharmacy entirely.
The replacement needed to work fully offline, support hardware setups ranging from single-workstation clinics to multi-branch chains, and run as either a native desktop app or a browser tab depending on what the site had available — without maintaining two separate codebases.
We built a platform adapter layer so the same React codebase could target Electron or the browser without knowing the difference. In Electron, every database operation crosses a typed IPC bridge to a Prisma-backed main process — the UI never touches the database directly. In the browser, Dexie over IndexedDB implements the same adapter contract.
The database layer supports both SQLite for standalone installs and PostgreSQL for pharmacy chains, each with its own Prisma schema and generated client. The type differences between the two are real enough that a single shared schema causes subtle bugs — two honest schemas is the cleaner call. All configuration is stored encrypted on disk using the OS keychain via Electron's safeStorage API.
The sync engine runs in the background whenever connectivity is available. Unsynced sales and patient records queue locally, sync in dependency order — patients before sales — and handle the awkward edge cases. A request that timed out but actually reached the server gets detected by its UUID, deduplicated, and retired rather than creating a duplicate record or surfacing a false error.
A pharmacy POS that loses a sale because of a timeout isn't an offline-first app — it's an online app with a worse failure mode.
Pharmacists can process sales, register patients, check inventory, and print receipts whether the router is up or not. When connectivity returns, the sync engine catches up without any manual intervention and surfaces a clear sync status so staff always know where their data stands.
The same codebase ships to macOS, Windows, and Linux, and serves as a browser app for sites that can't install native software. The SQLite-to-PostgreSQL path is built into the database adapter, so a single-location pharmacy can grow into a chain without a migration project or a rebuild.