HSLG Media

Why Capacitor and current limitations

Native build architecture

Capacitor packages the real shared UI in a native Android/iOS application and exposes device capabilities through plugins. Native WebViews are part of Capacitor's architecture; the rejected interim standalone preview APK had no Capacitor bridge or plugin integration.

Why

An existing web-oriented shared interface can be reused while exposing camera scanning, haptics, keyboard control, app links, orientation and secure platform storage through native adapters. This reduces screen reimplementation for one developer.

Limitations

  • A real release still requires frozen pnpm dependencies, resolved transitive Maven libraries, Capacitor sync, Gradle compilation, Android device tests and signing evidence.
  • NFC foreground reading, SQLite, encrypted credentials, push and Stripe native PaymentSheet remain unfinished.
  • iOS builds require macOS and Xcode, even when a Linux server hosts WordPress and can compile Android.
  • APK signing identity must remain stable for in-place Android updates; keystores are private and kept outside code/documentation archives.

What Capacitor contributes and what it does not

Capacitor is a native application container and bridge to device capabilities, not an ordering backend or database replication system. The shared HSLG interface runs from compiled assets. Official plugins provide Android/iOS access to camera QR scanning, network state, application lifecycle/URLs, haptic feedback, keyboard changes, portrait orientation and splash-screen control. The application still needs server APIs for identity, inventory, reservations and payments, plus local persistence where required.

The source currently separates apps/mobile/src/CapacitorBoot.ts, apps/mobile/native-adapters/CapacitorDeviceServices.ts, apps/mobile/src/NativeServices.js and apps/mobile/src/StartNative.js. Boot constructs the plugin adapter and an account coordinator if an HTTPS API URL is configured. It initializes the existing shared device experience and applies native UI setup. NativeServices.js is the explicitly fail-closed service provider injected into the shared UI. It returns no fabricated orders, rewards, availability or payments.

The plugin-by-plugin contract

@capacitor/network reports current network status and network changes. Its connected flag does not prove that HSLG API requests will succeed. The adapter separately performs an HTTPS health request with a timeout and validates the expected service/status response. The offline UI should distinguish 'no device connection', 'device online but HSLG unavailable' and 'operation timed out'. Reconnect is not permission to resubmit a financial operation without reconciliation.

@capacitor/app registers an appUrlOpen callback and obtains the URL used to launch the process. A resolved incoming URL must pass DestinationRouter.js origin/path validation before changing venue/table state. An external URL or arbitrary QR text cannot grant access, authorize an order or bypass a server-side identity check. Android OS association and HTTPS domain verification remain separate deployment tasks; registering a JavaScript handler does not prove the operating system will deliver real links.

@capacitor/barcode-scanner opens the rear camera with a QR-specific hint and returns scanned content or a cancellation indication. The pinned 3.1.3 ESM distribution exports CapacitorBarcodeScanner, not BarcodeScanner; call CapacitorBarcodeScanner.scanBarcode and retain the CapacitorBarcodeScannerTypeHint.QR_CODE hint. The first real presenter-triggered HSLG build failed at 55% during Vite bundling because it imported the nonexistent BarcodeScanner symbol. pnpm, TypeScript staging and 38 approved shared assets completed; the Android Gradle step did not start. The corrected import was checked against the previously uploaded 3.1.3 package archive and guarded by a contract test. Native success is still unverified until the rebuilt WordPress payload compiles on Ubuntu. The shared ordering screen already exposes a table QR action, so no new checkout flow is required for the basic camera test. Camera denial, OS-level permission prompts, cancelled scans, invalid links and wrong-venue links require distinct UI messages and physical-device tests. The browser presenter may show sample URLs but must identify that path as simulated.

@capacitor/haptics maps submit to a light impact, accepted to a success notification and error to an error notification. This is tactile feedback only; it must follow the actual business result instead of implying acceptance before the server confirms it. Devices may suppress or implement feedback differently. Haptic callbacks should never be necessary for an operation to complete.

@capacitor/keyboard listens for show/hide events and updates a CSS variable and visibility class with the native keyboard height. Test narrow Android screens, focused form fields, password managers, soft-keyboard resizing and navigation. An event listener alone cannot guarantee that a focused input remains visible; layout and scroll tests are still required.

@capacitor/screen-orientation attempts a portrait lock and tolerates platforms where the OS or device policy overrides the request. CSS must remain responsive. @capacitor/splash-screen hides the native splash after UI setup. Real splash artwork, Android version differences and cold/warm launch behaviour require device review. Hiding splash early must not expose an empty white frame or a failing bootstrap silently.

Capabilities that do not yet have an implemented native bridge

Foreground NFC reading is intentionally rejected by the mobile service implementation. A phone can sometimes open an associated HTTPS NDEF link using the OS, but that requires correct tags and verified app links; it is not an in-app NFC reader. Biometrics, encrypted token storage, native SQLite, push notifications, Stripe PaymentSheet and third-party social sign-in are not completed by the currently listed Capacitor plugins. A field named 'token vault' or an adapter interface is not proof of a secure Android Keystore bridge. Add each capability as a separately permissioned, tested module when its flow has been approved.

The account coordinator can call the registration, email-code verification and recovery API. Login must not retain credentials until encrypted native storage is available. Avoid localStorage or an unencrypted application preference as a substitute. Server APIs must not assume that possession of a QR code or a phone installation proves customer authentication.

Required build sequence and dependency evidence

Begin with an auditable pnpm lockfile and official Capacitor plugin packages with their transitive dependencies. Compile the native web entry with Vite, sync Capacitor with Android, resolve Android Gradle Plugin and AndroidX/Maven dependencies, build the Android project and sign the APK with an approved key. Verify the final package includes the intended Capacitor bridge and registered plugins. The previously generated Android scaffold and the interim WebView preview do not satisfy these conditions. Do not call an APK 'Capacitor connected' without positive evidence from an actual native build.

Record Android applicationId, minimum/target SDK, required runtime permissions, manifest intent filters, Android SDK/build-tools versions and signing certificate fingerprint. Do not embed REST secrets or Stripe secret keys in the APK. Public API origins and app association domains should be configured per build environment. Never modify Virtualmin globally merely to get Gradle or Node working.

Physical-phone acceptance plan

Install on a clean Android device and record the exact APK filename, checksum, package ID, version, OS release and signing identity. Start cold and confirm the splash transitions to the login screen. Deny camera permission and confirm an understandable rejection. Allow it and scan a valid HSLG table QR; check that venue/table state changes only after URL validation. Scan malformed and hostile QR content; confirm it is refused. Open a verified HTTPS app link from another app, then kill the HSLG process and repeat as a cold launch.

Toggle airplane mode while the order basket is open and confirm that the UI shows offline state while retaining the basket. Restore connectivity while the API is inaccessible and confirm the UI does not declare success. Confirm keyboard behaviour during registration, haptic feedback for actual outcomes, portrait/layout behaviour and safe app restart. For authenticated flows, verify the encrypted vault, session expiry, log-out clearing and account API under real HTTPS. For payment or booking flows, no visible success should appear without provider/server acknowledgement.

How the presenter relates to native proof

The next WordPress presenter can illustrate QR, offline/Retry, haptic entry points and app-link outcomes using clearly marked demo adapters. It cannot call Android camera APIs from a desktop browser as proof that Capacitor works. The same customer screens are reused, but service implementations are intentionally different. A presenter ZIP and a genuine signed Capacitor APK should be released with matching source/version evidence, and their test reports should clearly separate simulated UI and real device callbacks.

Next design decisions

Foreground NFC needs an agreed affordance—explicit Scan NFC button versus OS-initiated tap—and tag security model. Biometric unlock needs enrollment, fallback and recovery design. Push notifications need consent, categories and delivery infrastructure. PaymentSheet needs a verified merchant topology and saved-method policy. These are not safe to infer from existing visual mockups. Work may prepare narrow interfaces, but must not invent live authorization or transaction semantics.