Saltar al contenido principal

Native Hardware Runtime

FlowPOS has two native hosts around the same unmodified frontend-pwa build:

HostAppRuntime
Mobileapps/mobileExpo / React Native WebView
Desktopapps/desktopTauri v2 / Rust

The product is the PWA. Each host is a container: device identity, durable local storage, tray and autostart (desktop), over-the-air web bundles vs signed native releases, and hardware the browser cannot reach.

The only contract between PWA and host is the shared bridge in packages/global/types/mobile-bridge.types.ts (the mobile- prefix is historical; both hosts speak it).

  React Native host                 Tauri host
↕ ↕
NativeBridge NativeBridge
↕ ↕
frontend-pwa

Printing is the first native capability, not the architecture. Later hardware — scanners, scales, drawers, payment terminals, customer display — should land as additional advertised capabilities on the same bridge. See Capabilities beyond printing.

Rules that must not drift​

These are load-bearing in 051-mobile-app-shell and 054-desktop-runtime-shell. A later hardware feature may add merchant UI; it does not quietly invent host or capability branches against them.

  • FR-003 — the PWA never branches on which host it is in (isWindows, __TAURI__, ReactNativeWebView, user-agent host tests). Enforced by a source guard. Host knowledge is permitted in exactly one module: the shared bridge client's transport layer (FR-003a).
  • FR-004 — both hosts speak the same handshake, capability declaration, and command shapes. One set of contract fixtures covers both.
  • FR-004a — an absent capability means ordinary browser behaviour. There is no capability-conditional layout, no "desktop mode", and no screen that exists only when a capability is present. A capability may change what the host does with a request; it may not change what the merchant sees.
  • FR-038 — an unsupported capability returns UNSUPPORTED_CAPABILITY, never silence.
// Forbidden — host branch
if (isWindows) { /* … */ }

// Forbidden under current specs — capability-conditional UI
if (capabilities.scale?.serial) showScale();

// Allowed — the host advertises what it can do; the PWA degrades when absent
await bridge.request("scale.read", /* … */);
// host returns UNSUPPORTED_CAPABILITY; PWA behaves as in a browser

A future scale, scanner, or customer-display feature that needs merchant-facing UI gets its own spec. That spec amends FR-004a deliberately; it does not drift in application code.

Where to look​

  • Mobile Shell — Expo container, origin pin, sessions, outbox
  • Desktop signing — code-signing and notarisation for the Tauri host
  • Printing topology — where printing happens by platform today
  • Specs: 051-mobile-app-shell, 054-desktop-runtime-shell