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
- 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.
- Auth on the tablet: same local PIN/role system as the desktop, or something lighter for a shared counter tablet?
- 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
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'sstartMdns()advertises the desktop install asflo.localon the LAN, andmain/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 openhttp://flo.local:3002today 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)
flo.localmDNS advertisement already in place for KDS.node-thermal-printer) — same direction-of-control as KDS tickets already flow from POS → KDS, just reversed.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
Open questions
Future: printing directly from the tablet (not v1)
If direct printing from the tablet itself is ever wanted:
Part 2 — Free e-billing (consolidated from #126)
Baseline, already shipped, zero cost, zero risk
frontend/src/lib/whatsapp-share.tsalready buildswa.meclick-to-chat links (Meta's own free, official mechanism) with a prefilled bill summary. Real limits: text only (wa.mecan'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.jsis 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/baileysis 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 aswhatsapp-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):
Recommendation
Ship the free
wa.mebaseline as-is (already done). If/when this issue moves past exploration into an actual build, go with Baileys overwhatsapp-web.jsfor 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