# An offline-first point-of-sale PWA in Cameroon

> A dev.to build report describes Caisse Boutique, a Cameroonian point-of-sale PWA that queues sales on the device and syncs them when the network returns.

On 2026-10-02 the Caisse Boutique account published a build report on dev.to,
written in French, about a point-of-sale Progressive Web App made for small
retailers in Cameroon. The post states that designing point-of-sale
software for small shops in sub-Saharan Africa does not consist of copying Square
or Shopify, and that three field realities have to be solved instead: the
interruptions of the telecom networks it names as MTN and Orange, the high cost of
mobile data megabytes, and cash handling. It introduces Caisse Boutique as an
offline-first Progressive Web App designed for Cameroonian businesses, and says
what follows is the architecture and the technical choices behind it
([the report](https://dev.to/caisse_boutique/comment-jai-construit-une-pwa-de-caisse-enregistreuse-100-hors-ligne-pour-les-commercants-du-57i6)).

## What the report describes

The conditions the report names, the architecture comparison it prints, the
offline mechanisms it describes, the features it lists for the local market, and
the merchant feedback it quotes are taken in turn below, in the wording the post
itself uses.

### The conditions the author names

The post describes the daily situation of a shopkeeper in Douala, naming a snack
bar in Akwa, a grocery in Deido, and a hardware shop at the Marche Central, and
describes the conditions below. The first is chronic connection instability: it states that
4G and 3G mobile networks are interrupted regularly during peak hours, and that if
a point-of-sale program depends on a synchronous cloud API, the queue grows and the
shopkeeper goes straight back to pen and notebook. The second is what it calls the
friction of the Play Store: it states that asking a shopkeeper to download an 80 MB
application from the Google Play Store consumes that person's own internet bundle,
and that many refuse or give up. The third is what it calls the invisible loss of
money, which it attributes to unjustified cancellations of receipts by employees,
approximate mental arithmetic, and undocumented stock theft
([the report](https://dev.to/caisse_boutique/comment-jai-construit-une-pwa-de-caisse-enregistreuse-100-hors-ligne-pour-les-commercants-du-57i6)).

A figure is attached to the loss of money. The post states that on average a
small business without a computerised till loses between 50,000 and 150,000 FCFA
every month without noticing
([the report](https://dev.to/caisse_boutique/comment-jai-construit-une-pwa-de-caisse-enregistreuse-100-hors-ligne-pour-les-commercants-du-57i6)).

### The architecture table the post prints

The post gives its reason for choosing a Progressive Web App with what it calls a
radical offline-first approach as a table comparing a native application
distributed through the Play Store or as an APK against its own PWA. The rows, with
the post's own values, are download weight, 50 to 120 MB of mobile data for the
native app against under 2 MB for the PWA; installation, a mandatory Google Play
account against one click on "add to home screen"; network dependency, often
blocked without a connection against what it calls fully autonomous offline
operation using a service worker plus LocalStorage or IndexedDB; updates, heavy
manual downloads against silent and instant updates on each reconnection; and
compatibility, limited to recent Android versions against any smartphone, tablet,
or old PC
([the report](https://dev.to/caisse_boutique/comment-jai-construit-une-pwa-de-caisse-enregistreuse-100-hors-ligne-pour-les-commercants-du-57i6)).

### How the offline mode is described

The offline mode is described through named mechanisms. The first is cache-first
handling of assets: the post
states that the whole set of HTML components, Tailwind CSS styles, and application
scripts is cached locally by the browser from the first opening. The second is local
storage of transactions: every sale, stock change, or receipt print is recorded
locally in what it calls a secure queue on the device. The third is background
reconciliation: as soon as the device picks up the network again, over Wi-Fi or
mobile data, a synchronisation engine pushes the transactions in batches to the
central database without ever blocking the cashier's checkout interface
([the report](https://dev.to/caisse_boutique/comment-jai-construit-une-pwa-de-caisse-enregistreuse-100-hors-ligne-pour-les-commercants-du-57i6)).

MDN documents IndexedDB, one of the two storage mechanisms the architecture table
names. MDN
describes IndexedDB as a low-level API for client-side storage of significant
amounts of structured data, including files and blobs, states that it uses indexes to enable
high-performance searches of that data, and says that while Web Storage is useful
for storing smaller amounts of data it is less useful for larger amounts of
structured data. MDN also states that operations performed using IndexedDB are
done asynchronously so as not to block applications, and that IndexedDB is
available in web workers
([MDN, IndexedDB API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)).

### The features written for the local market

Bluetooth printing of 58 mm thermal receipts comes first, with the
post stating that the paper receipt remains the absolute symbol of trust for the
Cameroonian customer, that the application connects directly to the 58 mm mini
thermal printers sold on local markets or on Jumia, and that the receipts
automatically carry the legal mentions required by the DGI, which it lists as the
NIU, the RCCM, and a sequential invoice number. Second is a WhatsApp receipt sent
in one tap when no printer is at hand or the roll is empty. Third is a master PIN
belonging to the owner, which the post says locks every sensitive operation,
naming cancellation of a sale, an exceptional discount, and a change to the
inventory. Fourth is the payment model: the post states that no international bank
card is required and that the monthly subscription of 5,000 FCFA per month is
payable directly through MTN Mobile Money or Orange Money
([the report](https://dev.to/caisse_boutique/comment-jai-construit-une-pwa-de-caisse-enregistreuse-100-hors-ligne-pour-les-commercants-du-57i6)).

The post quotes feedback from a merchant it names as Papa Jean, who it says
runs a neighbourhood grocery in Deido, Douala. The quotation given there, in
French, is: "Avant, c'etait le cahier. Quand je devais m'absenter pour aller voir
les grossistes, les produits disparaissaient et le compte du soir ne tombait jamais
juste. Depuis que la tablette est posee au comptoir, je sais exactement ce qui a
ete vendu, franc par franc, meme sans connexion. Les 5 000 FCFA d'abonnement me
paient la paix du coeur." It describes keeping a paper notebook before, stock
disappearing and the evening count never balancing when the owner had to leave to
see wholesalers, and knowing what has been sold since a tablet was placed on the
counter, including without a connection
([the report](https://dev.to/caisse_boutique/comment-jai-construit-une-pwa-de-caisse-enregistreuse-100-hors-ligne-pour-les-commercants-du-57i6)).

## Why it matters for PWA developers

The post names a service worker as part of its fully autonomous offline
operation, and MDN documents that mechanism. MDN describes service workers as
proxy servers that sit between web applications, the browser, and the network
when it is available, and states
that they are intended, among other things, to enable the creation of effective
offline experiences, to intercept network requests, and to take appropriate action
based on whether the network is available. The same page states that service
workers are only available in secure contexts, meaning the document is served over
HTTPS, with browsers also treating `http://localhost` as a secure context to
facilitate local development
([MDN, Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)).

MDN also documents constraints on that worker. MDN states that service workers
run in a worker context, have no DOM access, and run on a different thread from
the main JavaScript that powers the app, and that as a consequence APIs such as synchronous XHR and Web
Storage cannot be used inside a service worker. MDN also states that service
workers cannot import JavaScript modules dynamically, that `import()` throws an
error when called in a service worker global scope, and that static imports using
the `import` statement are allowed
([MDN, Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)).

The post's receipt printing connects to thermal printers over Bluetooth, and MDN
documents the Web Bluetooth API. MDN marks it as limited availability, stating
that the feature is not Baseline because it does not work in some of the most
widely-used browsers,
and labels it experimental, advising that the browser compatibility table be
checked carefully before production use. MDN describes the API as providing the
ability to connect and interact with Bluetooth Low Energy peripherals, states that
it can only be used in a secure context, and notes that it is not available in web
workers because it is not exposed via `WorkerNavigator`
([MDN, Web Bluetooth API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API)).

## Related entries on this site

- [Capabilities](/reference/capabilities/): the report's receipt printer is a Web
  Bluetooth integration, and this page is where OpenPWA tracks the device and
  platform capabilities, Bluetooth among them, that a PWA can reach for.
- [Storage](/reference/storage/): the post's offline queue is described as
  LocalStorage or IndexedDB on the device, and this page covers quotas,
  persistence, and eviction, which is what decides whether such a queue survives.
- [Performance](/reference/performance/): the post's central comparison is a
  download-weight figure against a native app, and this page is where the
  performance budget side of that trade is documented.

## Open and unverified

- Whether the figure of 50,000 to 150,000 FCFA lost per month by a small business
  without a computerised till rests on a study, a sample, or an estimate is not
  confirmed.
- Whether the local transaction queue is written and read from the service worker
  or only from the page is not confirmed.
- Whether the under-2 MB download figure covers the first load, the cached
  application, or both is not confirmed.
- Whether the 58 mm thermal printers the post names work through Web Bluetooth on
  the specific browser and OS versions its merchants use is not confirmed.
- Whether the merchant feedback quoted was gathered under any defined process, and
  whether more than one merchant was asked, is not confirmed.
- Whether the post's compatibility row, which it gives as any smartphone, tablet,
  or old PC, is meant to cover the Bluetooth receipt printing as well as the rest
  of the application is not confirmed.
- Whether the application was tested on any of the widely-used browsers in which
  MDN states Web Bluetooth does not work is not confirmed.

## Sources

- [Comment j'ai construit une PWA de caisse enregistreuse 100% hors-ligne pour les commercants du Cameroun](https://dev.to/caisse_boutique/comment-jai-construit-une-pwa-de-caisse-enregistreuse-100-hors-ligne-pour-les-commercants-du-57i6) (dev.to)
- [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) (developer.mozilla.org)
- [IndexedDB API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) (developer.mozilla.org)
- [Web Bluetooth API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API) (developer.mozilla.org)