Skip to content
CompletedMobileSaaS

Bookodi Mobile — Android & iOS Apps

Native Android and iOS apps for a live restaurant dashboard that was built for laptops — fitted to every phone and tablet without touching the web code.

bookodi.com
Android shelliOS shellShell bridgePage layerLayout layerBookodi dashboardBookodi APILayout auditCI
Role
Sole engineer — shells, page layer, layout audit, tests, CI, docs
Team
Solo, AI-assisted
Timeline
Oct 2026
Organisation
Bookodi (XEOO)
Code
Proprietary (employer)
Reading time
6 min

A Capacitor 8 shell that runs the live Bookodi dashboard inside native Android and iOS apps, with a page layer injected before the web app loads and a mobile layout layer. A layout audit across 123 page states found 915 problems on the website and none in the app.

Overview

Restaurant owners and staff wanted Bookodi on their phones and tablets — the same dashboard, the same account and the same data as the website. The dashboard had been designed for laptops: on a phone the POS panels overlapped, order cards ran off the screen and dialogs hid their buttons in landscape.

Bookodi Mobile is a native app for Android and iOS that loads the live dashboard, adds what a phone app needs, and fits every page to small screens — while the web repository stays untouched.

The problem

  • The apps had to be exactly the website: every web deploy should reach them immediately, with no separate rebuild of around twenty dashboard pages.
  • The dashboard broke on small screens in portrait and landscape.
  • Payments had to stay on the website, in line with app-store rules.
  • Native expectations — safe areas, the back button, downloads, links, staying awake on the kitchen screen — had to work on both platforms.

Context & constraints

The web app and its API belong to a separate repository and team, so nothing could change there. I had no Mac with Xcode: iOS had to be built and tested entirely in CI.

Approach

  • Native shells — Java on Android, Swift on iOS, both on Capacitor 8. They provide the launch screen, a connection screen that retries by itself, crash recovery, safe-area handling with system bars in the page's own colours, downloads, an in-app browser and the Android back button.
  • Page layer — a TypeScript bundle injected at document start, before the web app's own scripts, and only on the Bookodi origin. It guards payments, hands files to the native side, routes new-tab links, keeps the screen awake on the Kitchen, Waiter and POS pages and tells the shell when the page has really drawn.
  • Layout layer — six stylesheets scoped to the app and to each route, switched off automatically once the website ships the same fixes. Every fix is written up with the matching change for the web team: 65 write-ups.
  • Proof — an automated audit that renders every dashboard page in both browser engines and checks for sideways scrolling, clipping, overlap and overflowing text.

Key capabilities

  • The live web app in a native shell — web deploys reach the apps instantly
  • Every dashboard page fitted to phones and tablets, portrait and landscape
  • Branded launch screen that lifts only when the dashboard has drawn
  • Connection screen with automatic retry and renderer-crash recovery
  • Payments kept on the website, with platform-appropriate notices
  • Exports to Downloads on Android and the share sheet on iOS
  • Screen kept awake on the Kitchen, Waiter and POS pages
  • iPad Split View and Slide Over

Architecture

  1. Native shell

  2. Injected at document start

  3. Live product

  4. Verification

The native shell loads the live dashboard; a page layer injected before the app’s own scripts adds native features and the mobile layout, and talks to the shell over a small bridge. Select a component to trace its connections.

Key decisions

Challenges

A laptop dashboard on a phone

Problem. POS panels overlapped, order cards and charts ran off the edge, menu text wrapped one word per line, figures were cut short and dialog buttons disappeared in landscape.

Solution. The scoped layout layer, measured by an audit of every page state in both browser engines and reviewed screenshot by screenshot.

Building iOS without a Mac

Problem. No Xcode was available locally, and Capacitor’s iOS internals limit how safe areas and injected scripts can be customised.

Solution. Swift is type-checked locally against UIKit, while real builds and iPhone/iPad simulator smoke tests run on GitHub’s macOS runners. A container root view handles safe areas; the user script is added after Capacitor’s own bridge scripts.

An embedded preview sharing storage

Problem. A same-origin preview frame shared the dashboard’s storage, so closing it could sign the owner out.

Solution. The page layer gives preview frames their own in-memory storage.

A launch that never flashes

Problem. The splash screen should lift onto a finished page — not a spinner — and survive server errors during deploys.

Solution. A readiness signal from the page layer, a 20-second safety timeout, and a WebView client that sends failures to the connection screen and returns to the same page when the network comes back.

Quality & delivery

Testing

  • Layout audit: 20 dashboard pages plus sign-in and sign-up, 123 page states, 23 screens, in Chromium (Android WebView) and WebKit (iOS) — 2,655 page-state checks. On the 14 core screens the website showed 915 real layout problems; the app showed none.
  • Android end-to-end: 14 of 14 passed on an Android 16 emulator — sign-in, auto sign-in, background resume, payments, back button, Excel download, Custom Tab, file picker, bar recolouring, dialer, landscape rotation and offline recovery.
  • 19 unit tests (Vitest) for the page layer.
  • CI: type-check, lint and unit tests; Android lint and release builds with an emulator smoke test against the live site; iOS simulator and device builds with smoke tests on an iPhone and an iPad simulator in both orientations.
  • A private local copy of the platform in Docker, so no test ever touches a real restaurant’s data.

Deployment

A signed APK for testers and an AAB for Google Play are produced locally; the signing key never enters the repository, and CI signs only when its secrets are present. iOS builds come from CI. Release hardening: minified, WebView debugging off, HTTPS only, two network permissions and nothing else.

Outcome

Layout problems, website vs app
915 → 0
14 core screens, both browser engines
Page-state checks
2,655
23 screens × 123 page states
Android end-to-end checks passed
14 / 14
Android 16 emulator
Resume from background
0.13 s
Debug build, measured on an emulator

Version 1.0.0 was delivered in October 2026: a signed Android APK, an AAB ready for Google Play, and iOS builds verified in CI. Store publishing waits on the company’s Google Play Console and Apple Developer accounts; App Links and push notifications are the next phase.

Lessons

  • When “the same as the website” is the requirement, the website is the product — wrap it, measure it, and send the fixes upstream.
  • An audit that counts problems turns “looks fine on my phone” into a number nobody can argue with.
  • CI can stand in for hardware you don’t have — even an entire operating system.

Building something similar?

Tell me what you’re working on — I reply to every serious message.

Related work

Bookodi web appGo API & agent hubHardened shellPrint Bridge servi…DiscoveryThermal printersNetwork printersOS print queues
Case study
In development2026Bookodi (XEOO)

Bookodi Desktop & Print Bridge

Native desktop app for the Bookodi restaurant platform with a built-in Print Bridge: it pairs with the cloud in one click, discovers printers on the local network and delivers server-rendered tickets over raw TCP, IPP, LPD, CUPS or the Windows spooler.

  • TypeScript
  • Vite
  • Electron
  • Node.js
  • WebSockets
  • GitHub Actions
  • +3
Operator dashboardCLIChapter runnerBrowser stageRestaurant dashboa…Realtime feedCoverage recorderPrint BridgeRun report
Case study
Completed2026Bookodi (XEOO)

Bookodi TestBot — Live Demo & End-to-End QA Bot

Playwright drives up to four real Chrome windows — owner, guest phone, kitchen display and waiter phone — through 21 chapters, from sign-up to the end-of-day report. It prints real tickets through its own Print Bridge and measures how much of the 180-endpoint API each run exercises.

  • TypeScript
  • Node.js
  • WebSockets
  • LLM APIs
  • Printing protocols
  • Playwright