Afteroffice Studio ID
ENTRY 013 Fold-out plate

A till that keeps working when the internet doesn't

Sepiring POS

An Android point-of-sale for restaurants that runs fully offline, prints to a thermal printer, and syncs afterwards.

CapacitorKotlinReactTypeScriptPostgreSQLExpress

The problem

A restaurant can't stop serving because the connection dropped. But a purely offline till is no use either if the owner can never see the numbers from elsewhere. Both had to be true at once.

The user journey

  1. Staff sign in with a PIN, open a shift, and start taking orders — all from a database inside the tablet itself.
  2. Orders are paid in cash or split across methods, then the receipt and kitchen ticket print to a thermal printer over Bluetooth.
  3. The shift closes, and the system works out how much cash should be in the drawer.
  4. Customers scanning the QR code on their table order from their own phone, and that order lands in the same queue.

What was built

A React app inside Capacitor with two Kotlin plugins I wrote: one for ESC/POS printing over Bluetooth Classic, one for native SQLite. Behind it sits PostgreSQL and an Express API I run myself rather than a third-party service.

Architecture

Tablet Capacitor · SQLite lokal
Printer Bluetooth · ESC/POS
Self-order QR meja · ponsel tamu
Express API sync engine
PostgreSQL multi-tenant

The hard part

Bluetooth thermal printers aren't supported by Web Bluetooth, so there was no browser shortcut — the native plugin had to be written. And printing can't be called working until it's tested against real hardware.

The outcome

  • The full till flow runs completely offline: sign in, open shift, order, pay, print, close, daily report.
  • Printing verified on a physical thermal printer, not just an emulator.
  • QR self-ordering is live in production, and a second restaurant was created through the dashboard by the owner themselves.
  • App updates ship without going through an app store, and never apply mid-shift.

What isn't finished

There's no manager-approval flow yet for cash variance, discounts, or voids — anyone signed in can do all three. Refunds are whole-order only, not per item. Both are recorded as the next piece of work.

My role

Product, architecture, app, native plugins, backend, and operations.

Recorded by
Ihsan Nugraha
Checked
6 Aug 2026, 17:17 WIB
How to verify
Click any URL on this page
Recorded by