ashike.s

MyDailyBill Desktop: Billing Software that keeps working offline

Shop counters don't always have internet, and a web-only billing app stops when the connection drops. I built an Electron desktop app that runs the same React and Laravel code online against the cloud and offline on a local database, then syncs every change back when the connection returns.

23 Oct 2026 5 min read Desktop Applications MyDailyBill (Shastika Softwares Pvt. Ltd.)
MyDailyBill Desktop: Billing Software that keeps working offline — screenshot

1

Codebase for web and desktop

2-way

Sync with conflict-safe numbering

16

Business categories supported offline

3

Installers: Windows, macOS, Linux

Table of contents
  1. 1.The business problem
  2. 2.Why existing solutions failed
  3. 3.The solution
  4. 4.Key features
  5. 5.Technical architecture
  6. 6.Challenges
  7. 7.The outcome
  8. 8.What this means for other businesses

The business problem

MyDailyBill is a GST billing, inventory and accounting platform for Indian small businesses: mobile shops, hardware stores, medical shops, workshops, furniture dealers and more. Each business gets its own cloud account and its own database, and the team uses it all day: invoices, purchases, stock, payments, returns and GST reports.

It started as a web app, and that was the weak spot. Shop counters don't always have reliable internet. When the connection dropped:

  • Billing stopped. Customers waited at the counter, or bills were written by hand and typed in later.
  • Re-entering data caused mistakes: duplicate invoices, stock that didn't match, and payments that were never recorded.
  • Owners lost trust in a system that was only as reliable as their broadband.

The product needed a desktop app that keeps billing through an outage and catches up with the cloud on its own when the connection returns, without a second codebase to maintain.

Why existing solutions failed

  • A plain website stops the moment the network drops. Browser caching can show old pages, but it can't create invoices, adjust stock or apply GST rules offline.
  • Classic offline desktop billing software works without internet but lives on one PC. There is no cloud backup, no multi-branch view and no access from anywhere else.
  • Rewriting the app natively would have meant duplicating hundreds of screens and all the GST, stock and accounting logic, then keeping two versions in step forever.
  • Generic sync libraries assume a simple data model. MyDailyBill has 100+ related tables per business: invoices with tax and expense lines, IMEI and batch-tracked stock, party balances by financial year and auto-generated document numbers. All of that has to survive a round trip.

The solution

I built the MyDailyBill desktop app in Electron, plus the offline and sync layer across the whole stack. The key idea: the desktop app runs the same React front end and the same Laravel back end as the web app. When offline, that back end runs inside the app on a local database.

One app, two modes

  • Online: the app talks directly to the business's cloud API, exactly like the web app.
  • Offline: the app starts a bundled PHP server on the user's own machine and points the same React screens at it. Data lives in a local SQLite database, one file per business, so the same PC can serve more than one business safely.
  • Switching is automatic. A network monitor checks connectivity every 5 seconds. When it drops, the UI shows "You are offline — changes will sync when you reconnect." and keeps working. Invoices, purchases, stock and payments all behave the same.

online offline

A sync engine that understands billing data

  • Every offline change is queued. A model observer records each create, update and delete into a local sync_queue, including fields that are normally hidden from API responses.
  • Push, then pull. On reconnect, queued changes are pushed to the cloud, then everything that changed in the cloud since the last sync is pulled and merged in. A Sync button and a progress bar show what's happening, and the header shows "Synced 10:42 AM".
  • Incremental pulls. The cloud exports only rows changed since the last pull. A schema version forces a one-time full pull when a sync fix needs it.
  • Conflict-safe document numbers. If the offline PC and the cloud both issued, say, party code PTY0003 or invoice SI/26-27/0001, the local record is renumbered to the next free code and pushed again. The cloud stays authoritative and nothing is lost.
  • Schema differences handled. The cloud runs MySQL and the desktop runs SQLite. The sync converts date formats, drops columns one side doesn't know about, and lets NOT NULL columns fall back to their defaults.

sync engine

First launch, per-business setup

The first time a user logs in online, the app records their business and its category: mobile, medical, hardware, workshop and so on, across 16 categories, each with its own database schema. It then builds the matching local database and pulls the business's data, so the desk is ready to go offline from day one.

Installers and auto-updates

  • One command builds the React app, bundles Laravel and a portable PHP 8.3, and packages installers for Windows (NSIS), macOS (DMG) and Linux (AppImage).
  • Releases are published to a private GitHub repository. Installed apps check for updates on launch, show what's new, and let the user download now, install on next launch, or skip that version, with live download progress.

auto update

Key features

  • Online and offline modes in one desktop app, with automatic switching
  • Same React front end and Laravel back end as the web app, with no duplicate business logic
  • Bundled PHP server on a free local port, so nothing needs installing besides the app
  • Local SQLite database per business, stored in the user's app data
  • Change queue that captures every offline create, update and delete
  • Two-way sync: push queued changes, pull cloud changes since the last sync, with live progress
  • Conflict-safe numbering for invoices, parties and other generated codes
  • Category-aware setup for 16 business categories
  • Auto-updates from private GitHub Releases: what's new, download progress, install later or skip
  • Installers for Windows, macOS and Linux

Technical architecture

  • Electron main process: creates the window, finds a free port and starts PHP, monitors the network, runs the updater, and exposes a small IPC bridge to the React app.
  • React app: one shared codebase. A request layer sends calls to the cloud or to the local server depending on connectivity, and adds headers so the back end knows which business it is serving.
  • Laravel back end: a tenancy middleware identifies the business by domain on the web and by header on the desktop. Artisan commands handle first-time setup and sync, and an observer fills the sync queue. On the cloud side, export and import endpoints exist for every business category.
  • Packaging: electron-builder with NSIS, DMG and AppImage targets. During development a junction (symlink) points the app at the live Laravel code, so back-end changes show up without a rebuild.

Challenges

  • Running PHP inside a desktop app. Packaged apps are read-only, so Laravel's storage, cache, logs and settings are redirected to the user's app-data folder. HTTPS from the bundled PHP needed its own certificate bundle, or cloud calls failed with SSL errors.
  • Big businesses, big first sync. Some businesses export tens of megabytes. Inserting row by row on SQLite took minutes and hit PHP's time limit. Wrapping the pull in a single transaction with foreign-key checks deferred cut it to seconds, and the memory and time limits for sync were raised.
  • Two databases, one truth. Offline and cloud can both create records with the same generated number. Instead of failing the sync, the local record is renumbered and re-queued, so the cloud stays authoritative and nothing is lost.
  • MySQL vs SQLite differences. Nullable-vs-default columns, date formats and local-only fields all broke inserts at first. Each one now has an explicit, tested rule in the sync.
  • Errors you can actually debug. A crashed PHP process can exit without a message. The app now captures the end of PHP's error log and shows it with the failed sync, instead of a bare "sync failed".
  • Keeping the bridge safe. The React side can only call a short whitelist of commands, arguments are sanitised, and only http(s) links can be opened externally.

The outcome

  • Billing no longer depends on the internet. Shops can keep creating invoices, recording payments and updating stock through an outage, and the app catches up automatically.
  • One codebase for web and desktop. New features built for the web app reach desktop users without being rewritten.
  • Data stays consistent. Every offline change is queued and synced, with clear rules for conflicts instead of manual clean-up.
  • Releases are routine. A single command ships a new version, and users update from inside the app.

What this means for other businesses

If your software stops when the internet does, your customers notice first. Shops, clinics, warehouses, field teams, branch offices and event counters all work where connections are unreliable.

  • You don't need to rebuild your web app as a native app. Your existing app can run offline on the desktop.
  • A well-designed sync queue makes offline changes safe, even for complex data like invoices, stock and accounts.
  • Auto-updates mean every installed copy stays current without IT visits.

If downtime is costing you sales, I can help you build software that keeps working offline.