How My Local POS is built
One app written once and packaged for two platforms, using modern open-source tools. All data is saved on the device, with no server and no cloud.
The tech stack
Vue 3
The user interface: screens, forms, the cart and reports. One shared interface for Windows and Android.
User interfaceTypeScript
JavaScript with types. It catches many mistakes before the app is built, including in the business rules.
LanguageVite
Builds and bundles the interface into small, fast files that are packaged inside the app.
Build toolElectron
Turns the app into a Windows desktop program, packaged as an MSI installer with electron-builder.
Windows appCapacitor
Turns the same app into a native Android app, distributed as a signed APK.
Android appSQLite
A small, reliable database stored as a file on the device. Windows uses Node's built-in node:sqlite, and Android uses the Capacitor SQLite plugin.
fflate
Creates and reads the ZIP backup files. Each backup includes a manifest with a SHA-256 checksum for every file.
BackupsVitest
Automated tests run the business rules (checkout, stock, permissions, backup and restore) against a real SQLite database before every release.
TestingNode.js
Powers the development tools and, inside Electron, the Windows app's database and file handling.
RuntimeOne app, two platforms
The screens never touch the database directly. Every action goes through one set of business rules.
On Windows
The business rules and database run in Electron's protected main process. The window only asks for named actions, such as "complete this sale", and can't run its own database commands or read files.
On Android
The same business rules run inside the app and save to private app storage that other apps can't read.
Built to be careful with your numbers
Exact money
Amounts are stored as whole centavos (₱125.50 is saved as 12550), so totals and change never have rounding errors.
All-or-nothing sales
The sale, its items, the payment and the stock deduction are saved together in one database transaction. If anything fails, nothing is saved, so there are no half-finished sales.
No double sales
Each checkout has a unique token. Tapping twice, or a retry after a glitch, returns the same sale instead of creating a second one.
History that doesn't change
Each sale keeps the product name and price from that moment. Editing a product later never rewrites old sales.
Every stock change is logged
Stock only changes through recorded movements (sale, delivery, correction or reversal), and it can never go below zero.
Checked on every action
Every request is validated, and the role is checked in the business rules, not just by hiding buttons. Passwords are stored as salted hashes.
Safe upgrades
Database changes are applied as numbered migrations when you update. A database from a newer version is refused instead of being damaged.
Locked-down desktop window
The Windows app runs sandboxed with context isolation. It can't open pop-ups or navigate to outside websites.