Skip to content

Android/iOS tablet client + free e-billing (WhatsApp) #135

Description

@itsbkm

Summary

Add an Android/iOS tablet client for order-taking and billing — as a thin client to an existing FloCafe desktop install over the LAN, not a port of the Electron app (Electron is desktop-only; there's no supported path to Android/iOS). Bundled into this same issue: how bills get to customers from that client for free, which folds in the WhatsApp messaging discussion that started in #126 (closed as duplicate, consolidated here).

Part 1 — Tablet client

Why this is smaller than it sounds

FloCafe already has exactly this shape of client for a different surface: KDS. main/index.ts's startMdns() advertises the desktop install as flo.local on the LAN, and main/kds-server.ts (port 3002) serves the kitchen display over plain HTTP + WebSocket to any browser on any device — no Electron, no native app, nothing installed. A tablet can already open http://flo.local:3002 today and see KDS.

This is about extending that same pattern to a second view: order-taking + billing, not just KDS. The desktop install stays the single source of truth (SQLite, printer, cloud sync); the tablet is a browser tab talking to it over the LAN, the same way a KDS display already is.

Scope (v1)

  • Order-taking UI (menu, cart, table selection) served from the existing local Express server, reachable via the same flo.local mDNS advertisement already in place for KDS.
  • Billing/checkout from the tablet, writing to the same SQLite DB the desktop already owns.
  • No printer support on the tablet. "Print" from a tablet-originated bill is dispatched to the desktop install (which already has working USB/Network/Bluetooth ESC/POS printing via node-thermal-printer) — same direction-of-control as KDS tickets already flow from POS → KDS, just reversed.
  • E-billing instead of/alongside printing — see Part 2.
  • Pairing a tablet to a specific desktop install: could reuse the same pairing-token pattern KDS already has (main/routes/kds.ts, kds_pairing_tokens, flo://kds/pair?token= deep link) rather than inventing a new mechanism.

Explicitly out of scope for v1

  • Any printer access from the tablet itself.
  • Working when the tablet isn't on the same LAN as the desktop install (no cloud relay for this — that's what FloAdmin/RevFlo are for, this is specifically the same-network order-taking case).
  • iOS printer support of any kind (see below — it's a different, harder problem than Android's).

Open questions

  1. Delivery mechanism for the tablet UI itself: plain responsive web page (zero install, works today's KDS-style) vs. a Capacitor-wrapped app (installable icon, offline shell, easier path to native printer access later). RevFlo already uses Capacitor, so there's in-house precedent either way. Leaning toward starting as a plain browser page (matches KDS, ships fastest) and revisiting Capacitor only if/when native hardware access (printer, barcode scanner) actually becomes a requirement.
  2. Auth on the tablet: same local PIN/role system as the desktop, or something lighter for a shared counter tablet?
  3. Concurrent order editing: two staff (desktop + tablet) touching the same order/table at once — needs a conflict story, even if it's just "last write wins" for v1.

Future: printing directly from the tablet (not v1)

If direct printing from the tablet itself is ever wanted:

  • Android can do USB/Bluetooth ESC/POS printing, but only from a native app with a printer plugin — a browser tab can't reach USB/Bluetooth hardware directly. Capacitor + an ESC/POS plugin would be the path.
  • iOS is much more restrictive: no generic USB/Bluetooth printer access without MFi-certified hardware or a vendor SDK. Meaningfully harder than Android; likely means picking specific supported printer models rather than "any ESC/POS printer" like the desktop app supports today.

Part 2 — Free e-billing (consolidated from #126)

Baseline, already shipped, zero cost, zero risk

frontend/src/lib/whatsapp-share.ts already builds wa.me click-to-chat links (Meta's own free, official mechanism) with a prefilled bill summary. Real limits: text only (wa.me can't carry a PDF/image attachment), and it's tap-to-send, not automatic. Worth keeping as the permanent free-tier default regardless of what else this issue lands on — it already works from a tablet session too, nothing to build there.

Original motivation (from #126)

FloCafe already has customer phone capture and WhatsApp sharing helpers. Richer WhatsApp integration (sending receipts, order updates, and customer notifications from within the app, not just a tap-to-share link) could round this out — automating the send rather than requiring a tap, and eventually attaching an actual bill image/PDF instead of a text summary.

Option A — Official WhatsApp Business Cloud API, merchant's own credentials

Fully possible — FloAdmin already does exactly this BYO-credentials pattern for OTP delivery (Whatsapp.php, Meta Cloud API). Customer-initiated conversations get a 24-hour free reply window, so cost isn't actually the blocker for the receipt/order-update use case. The real wall is onboarding: Meta Business verification, WhatsApp Business Account setup, and — for any operator whose number is already a personal WhatsApp Business account — being forced to delete it before Meta will attach it to the Cloud API. Most of FloCafe's target small operators won't do that to try a POS feature. Likely out of scope as the default path for this reason, even though it's the only fully ToS-clean option.

Option B — Unofficial automation (whatsapp-web.js, Baileys, etc.)

Credit: @carvalab did the real analysis here on #126, reproduced/summarized below — go read the original comment for full detail.

whatsapp-web.js is healthy and actively maintained (22.2k stars, v1.34.7 Apr 2026) but drives a real headless Chromium via Puppeteer — ~1–2GB RAM per session at idle, climbing past 2–3GB over a shift, several-second cold start, harder to package (Chromium system libs complicate the Linux AppImage/deb build). For a desktop POS already bundling one Chromium (Electron itself), a second one per WhatsApp session doesn't scale on the low-spec counter PCs this app targets.

@whiskeysockets/baileys is the recommended alternative: pure WebSocket client speaking WhatsApp's multi-device protocol directly, no browser at all. ~50MB RAM per session, sub-second cold start. Also actively maintained (10.2k stars, v7.0.0-rc13 May 2026). Trade-off: it reimplements the wire protocol, so it bumps more often on WhatsApp-side changes — acceptable for a narrow "reply to a known customer with a receipt" use case.

(Also surveyed: wppconnect — same Puppeteer/Chromium cost as whatsapp-web.js; waha — a sidecar HTTP API wrapping multiple engines including Baileys, a clean fit if FloCafe ever prefers IPC over an embedded library instead.)

Ban-avoidance rules, non-negotiable if this ships (from @carvalab's original writeup, condensed):

  • Reply-only, never initiate. The bot never starts a conversation — a customer must message first. Cold-outreach (a receipt for an order they didn't request by WhatsApp, a "here's our menu" to a scraped number) is close to a guaranteed ban; warm replies to a customer who messaged first are much safer, because that's the exact behavior WhatsApp's anti-spam system expects from a real business.
  • Human-like pacing: mark the incoming message seen, show typing for a randomized delay based on reply length, then send.
  • No bulk sends, no marketing content, no banned words/links.
  • Rate caps (roughly 4 messages/engaged contact/hour, then back off), randomized delays even within a burst, geographic clustering of who gets messaged in a session, a real profile picture/name/status on the number.
  • Explicit opt-in/consent, easy opt-out, and the operator needs to understand the number they connect is their own and they bear the ban risk — same disclosure posture as the anonymous telemetry work elsewhere in this app.

Recommendation

Ship the free wa.me baseline as-is (already done). If/when this issue moves past exploration into an actual build, go with Baileys over whatsapp-web.js for the resource-efficiency reasons above, gated behind explicit opt-in and the ban-avoidance rules baked into the send pipeline itself, not left as documentation someone might skip.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions