Platform
Mobile App
A thin WebView wrapper around the staff portal, built with Expo and React Native.
Overview
SalonOS ships a single Android/iOS app (apps/mobile) that wraps the staff-only web portal
(https://app.modernsalonowner.com/my) in a native shell via react-native-webview. It is
not a native rewrite of the dashboard — the app itself contains no calendar, client-lookup,
or booking UI; all of that is the same /my React pages served to a desktop browser, rendered
inside the WebView. Native code is limited to a handful of device-level concerns the browser
can't provide on its own.
This replaces an earlier native-Expo plan (SALO-21, SALO-154–158) that this doc used to
describe — full native screens, offline write queueing, push-notification categories, and
per-brand white-label EAS builds. None of that shipped. The pivot to a WebView wrapper happened
in SALO-375, with follow-ups in SALO-402/403 (loading-state and biometric-lock fixes) and
SALO-493 (repointing every role to /my).
What the native shell actually does
Everything below lives in apps/mobile/src/app/_layout.tsx — there is currently no other
screen or route in the app.
- Loads
/myin a WebView withsharedCookiesEnabled/thirdPartyCookiesEnabled, so it behaves like a normal authenticated browser session against the same backend as web. - Android device permissions: requests fine/coarse location, camera, and microphone on launch (for features the wrapped web pages use, e.g. GPS attendance clock-in).
- Session persistence across app restarts: a small JS snippet is injected into the WebView
that polls
localStorage/cookies for Supabase'ssb-*-auth-tokenentries every 3 seconds and posts them back to the native side, which stores them inexpo-secure-store. On next launch, those values are re-injected into the WebView before content loads, so the user doesn't have to sign in again. - Biometric unlock: if a saved session exists and the device has enrolled biometrics
(
expo-local-authentication), the app shows a lock screen requiring Face ID/fingerprint (or a password fallback) before rendering the WebView. - Android hardware back button: routed to the WebView's own back/forward history.
- Connection-error screen: a native retry screen if the WebView fails to load, since there's no native content to fall back to.
What it does NOT do
- No native calendar, client list, booking, or checkout UI — all of that is the
/myweb app, unmodified, running in the WebView. - No offline support. There is no write queue, no cached-data fallback, no "last synced" indicator — if the device has no connectivity, the WebView simply fails to load and shows the native connection-error screen.
- No push notifications.
expo-notificationsis not a dependency of this app. - No white-labelling or per-brand builds. There is one app, one bundle ID, one App
Store/Play Store listing, covering every SalonOS tenant — brands are not distinguished at the
native app level at all (that distinction happens inside
/my, same as on desktop web).
Target users
The wrapped /my portal is staff-facing only (owners, managers, stylists, front desk) — there
is no client-facing surface in this app. What each role can actually do is defined by /my
itself, not by this native shell; see the web dashboard's own role-permission model rather than
this doc for that.
Technology
- Framework: Expo ~51, React Native 0.74
- WebView:
react-native-webview13.8.6 - Biometrics:
expo-local-authentication~14.0.1 - Secure storage:
expo-secure-store~13.0.2 - Navigation: none — a single root layout, no expo-router screens
- Backend: none directly — the WebView talks to the same Next.js app/Supabase backend as desktop web; the native shell itself makes no API calls of its own
Distribution
Release-build tooling (a WSL-based EAS build pipeline for producing a signed Android APK) is tracked separately and not yet complete — see SALO-416. There is no current App Store/Play Store listing.
Related tickets
- SALO-375 — WebView wrapper pivot (this architecture)
- SALO-402 / SALO-403 — loading-state and biometric-lock fixes
- SALO-493 — repoint all roles to
/my - SALO-416 — native build/release toolchain (open)
- SALO-480 — "Develop Web Screens" (open; if ever picked up, would be new work, not a continuation of the abandoned native-Expo plan this doc used to describe)