Technology

Why your books still
balance on Friday.

Field software fails in one specific way: the network dies mid-transaction, and by the end of the week the van, the warehouse and the ledger disagree — so someone spends Friday reconciling by hand, and nobody trusts the numbers. Every decision below exists to make that impossible.

This page is for the person who has to own this after we hand it over. If that's not you, the platform tour is the better read.

01 · The stack

Boring where it counts.

Nothing here is chosen to be interesting. It's chosen because it survives a decade, hires well in this region, and can be handed over. The clever parts are in the architecture, not the dependency list.

What runs where
LayerTechnologyWhy this one
Mobile React Native · TypeScript · new architecture · Hermes · local SQLite One codebase, native performance where it matters, and a local database that is the app's actual source of truth.
Web portal Angular · zoneless + signals · PrimeNG · Leaflet / OpenStreetMap Zoneless signals keep 200-plus screens responsive without change-detection tax. Maps cost nothing per view.
Services .NET · Dapper · JWT · Serilog Hand-written SQL over an ORM, deliberately. Sync-shaped queries and bulk posts are clearer written out than fought through a mapper.
Database SQL Server · ~250 objects · numbered migrations Every change is a numbered, reviewable migration. There is no "someone ran a script once".
Workers Seven independent Windows services Snapshot building, post-queue draining, reporting, loyalty and speech each fail on their own without taking sales down.
On-device AI TFLite over JSI · MobileNetV3 · EfficientDet · Vosk Apache-licensed, runs on the handset, costs nothing per call, and works with the phone in flight mode.
Documents PDFsharp / MigraDoc · ZXing barcodes MIT-licensed. The better-known library is AGPL, which would have reached the client's deployment.

02 · The sync engine

The crown jewel.

The device never asks the server for a screen. It asks for a database — once — and then works. Everything after that is reconciliation.

One filter, two paths A single resolver turns "who is this person?" into a WHERE clause — and both the snapshot builder and the live delta go through it. The offline copy and the online delta are incapable of disagreeing, because they're the same code. The keystone class
Atomic bulk upload An order is 7 related batches. They post as one transaction, in order, so parents commit before children — which deletes the orphan class of failure rather than retrying it. Measured: 7 batches queued inside 20 ms. Race window: zero
Identity, not sequence IDs are generated on the phone, so 500 devices can't collide. Shared singletons use deterministic IDs derived from what they are — so a re-send updates the same row. A lost network reply costs nothing. Re-send = upsert
Self-healing local schema The device migrates its own tables every time it opens the database. A column added on the server reaches a phone in the field with no reinstall, no fresh snapshot and no support call. Zero-touch upgrade

03 · Invariants

Rules that never bend.

Every one of these is written down and enforced in code review. They are the difference between a system that works in a demo and one that works in month fourteen.

01

The server writes the ledger, never the balance.

Stock balances are replayed from an append-only ledger, and every row records the fact that it was applied — in the same transaction that wrote it. Nothing can be applied twice, and a device that misses a week catches up by replaying, not by being told a number that might already be stale.

02

Reads never touch the network.

Not "usually". Not "with a fallback". A server-fetch fallback in a read path is treated as a defect, because the moment one exists, the offline story is a lie and nobody finds out until a salesman is standing in a basement.

03

The day will not close over unfinished money.

End-of-trip blocks on approved-but-uncollected loads, pending unloads, unsynced local rows and a server queue still holding failures. Being offline is not "all clear" — the app says reconnect, because it cannot know.

04

Imports upsert. They never delete and re-insert.

An Excel import matches on the natural key, updates what changed, and deactivates what was dropped. A blank cell never nulls existing data. Nothing is re-parented or re-typed from a spreadsheet — because someone will one day upload last quarter's file.

05

Configuration, not code.

Org hierarchies, approval matrices, status tabs, menus, mobile feature visibility, claim scenarios, survey rules, promo targeting, scorecards and dashboards are all data. The tenth claim scenario is one master row, not a release.

04 · On-device AI

Architectural,
not a bolt-on.

The device already holds 30 days of transactions, the ledgers, the GPS trail and the promo rules. Once the model is there too, intelligence is a local function call — free, instant, and available in flight mode. For a cloud-first competitor to match that isn't a feature; it's a rewrite.

Vision · ShelfLens Detect, embed, cosine-match against your catalogue. 129–150 ms a frame, device-verified. Adding a SKU is uploading photos, never a retrain — and the first phone to learn it teaches the fleet. TFLite / JSI · Apache-2.0
Speech · offline voice Hands-free navigation and order entry with no cloud STT. Constraining the recogniser to the ~600 words that matter took accuracy from roughly 85% to 97–99% — the grammar is the whole unlock. Vosk · Apache-2.0 · offline
Deterministic intelligence Co-pilot, Command Center, Load Coach, Target Coach and Beat Doctor contain no model at all. They're rules and arithmetic over data the device already has — which is why every figure drills to its records. Explainable · auditable · free
The honest limit Small speech models have a fixed dictionary — brand words simply aren't in it, and swapping the model fixes accent, not vocabulary. So voice does navigation, quantities and workflow; three typed letters find the product. Documented, not hidden

What this costs to run. Nothing. No inference bill, no vision API, no speech API, no paid maps, no paid routing. Not as an introductory tier — as an architectural property. Your unit economics don't move when the fleet doubles.

05 · Operations

Deploys that refuse
to break production.

Seven services, a portal and a signed mobile build. The deployment scripts are preflight-gated: if the build fails, production is left exactly as it was.

Fail before you touch it Every deploy builds first and only then swaps. A failed compile leaves the running system untouched. Configuration is backed up and restored across every deploy, because it has been wiped before. Preflight-gated · config-safe
Deploy anywhere On-prem, private cloud, or a single machine in the back office — it's Windows services behind a reverse proxy. Nothing here requires a hyperscaler account or phones home to us. On-prem capable
Permanent addressing A named tunnel on an owned domain: reboots, WiFi reconnects and ISP address changes never break a client. Coexists with existing sites by isolating ports, roots, pools and loopback binding. Survives reboots
Adversarial QA A page-by-page negative sweep — client validation, server validation, uniqueness, boundaries, injection, authorisation, concurrency, error handling, data integrity — enumerated as findings and fixed as shared primitives. Findings-driven

Diagnostics are a feature. When a beat doesn't generate, the Beat Doctor tells you which gate stopped it and offers the fix. When a load looks wrong, the Load Coach shows the per-store table that sums to its forecast. Software that can explain itself needs far less support than software that can't.

Next

Ask the awkward one.

What happens when the signal dies mid-invoice? When two salesmen are put on one route? When an admin uploads last quarter's spreadsheet? There's an answer to each, and it's in the architecture rather than the brochure.