StockPilot
In productionAn offline-first point of sale and inventory system for shops with unreliable internet.
- Period
- 2024 — present
- Role
- Sole developer — architecture, interface, backend, infrastructure
- ~30k
- lines of TypeScript
- 289
- automated tests
- 3
- surfaces, one core
- Solo
- built and shipped
Get the app — StockPilot
The register runs in the browser and installs like an app, and the desktop and Android builds download straight from the project's own server - no store in between.
- Download .exe
Windows
Windows 10 and later - 106 MB
The desktop register, built by CI on every change. It keeps taking payments with the connection down and updates itself from the same server.
- Download .apk
Android
Android 9 and later - 99 MB
The signed APK, installed outside any store. You can also open the site in Chrome and choose "Install app" if you would rather not handle a file.
- Install
iPhone and iPad
Safari on iOS 16.4+
No installer: open the site in Safari, then Share and "Add to Home Screen". It runs full-screen and works offline, with no App Store account needed on either side.
- Not available
macOS
macOS 12 and later
Buildable locally, but unsigned, so it will not start on Apple Silicon without a developer certificate.
A shop with patchy coverage cannot run a cloud point of sale. The connection drops at the worst possible moment — a customer at the counter, a queue behind them — and the register stops. StockPilot takes the payment locally and reconciles with the server once the network returns.
One core, three surfaces
The web app, the mobile app and the desktop register share the same business logic, the same local catalogue and the same sync client, written once in TypeScript inside a pnpm monorepo. Each surface keeps its own data on the device and reconciles through commutative operations rather than absolute values — the difference between “this sale removed 2 units” and “stock is now 17”, and the reason concurrent offline registers converge instead of clobbering one another.
What it does
Register — offline checkout, barcode scanning, free-form entries, change calculation, printable receipts, PDF invoices.
Inventory — goods receipt, price corrections, low-stock alerts, a full movement trail.
Sales — history, partial returns, cancellations, refunds.
Multi-shop — strict tenant isolation, owner / manager / employee roles, super-admin.
Catalogue — barcode import from Open Food Facts, compressed product photos.
Accounting — VAT handling on tax-inclusive and tax-exclusive prices, numbered invoices, an audit log.
Installing it
There is no app store in the loop. The register is a progressive web app: open it in a browser, choose “install”, and it lands on the home screen as a full-screen application with its own icon. A service worker keeps the interface and the local catalogue on the device, so it opens and takes payments with the connection down.
That matters more than it sounds. Shipping through the stores would mean an Apple developer account, a review queue, and a release cycle measured in days for a shop that needs a fix this afternoon. Installing from the browser puts a correction in a cashier’s hands the moment CI is green.
Running it
Docker and Traefik on a VPS, deployed over SSH from GitHub Actions. The web and mobile surfaces are in production and in daily use in a real shop, and signing up for a new shop is open to anyone.
The Electron desktop register takes payments offline, keeps inventory and history, and updates itself. What it lacks comes down to one thing: a signature. Without a certificate, Windows shows a SmartScreen warning on first launch — the installer is published, but opening it takes a detour through “More info”.