ADR-011: Expo Mobile Framework ADR-011: Expo SDK 54 for Mobile App Status: Accepted Date: 2026-02-21 Deciders: John (AI Director), Alem (CEO) Category: Mobile Context Drop requires a mobile app for iOS and Android. The mobile app is the primary interface for remittance and QR payments -- users scan QR codes with their phone camera and approve payments via BankID on the same device. Mobile framework options considered: Framework Cross-Platform Code Sharing (Web) OTA Updates Camera/QR BankID Integration Dev Experience Expo SDK 54 iOS + Android High (React shared) Yes (EAS Update) expo-camera expo-web-browser Excellent React Native (bare) iOS + Android High (React shared) Manual react-native-camera Custom deep links Good Flutter iOS + Android None (Dart vs TS) No native OTA camera plugin Custom deep links Good Native (Swift/Kotlin) Separate codebases None App Store only Native APIs Native SDKs Platform-specific Key factors in the decision: Code sharing: Drop's web app uses React 19. Expo enables sharing React components, hooks, types, and business logic between web and mobile. BankID flow: Mobile BankID authentication requires opening a secure browser ( expo-web-browser ) and handling deep link callbacks ( drop://auth/callback ). Expo provides both natively. QR scanning: Core feature requires camera access. expo-camera provides this with barcode scanning built in. OTA updates: Financial apps need rapid hotfix deployment. Expo Application Services (EAS) provides over-the-air JavaScript bundle updates without App Store review. Team capacity: AI-driven development team benefits from a single language (TypeScript) across all platforms. Decision Use Expo SDK 54 with managed workflow for the Drop mobile app. graph TB subgraph mobile["Mobile App (Expo SDK 54)"] screens["Screens
(10 screens matching web)"] hooks["Shared Hooks
(useAuth, useTransactions)"] types["Shared TypeScript Types"] screens --> camera["expo-camera
(QR scanning)"] screens --> browser["expo-web-browser
(BankID auth)"] screens --> notif["expo-notifications
(push alerts)"] screens --> storage["AsyncStorage
(Bearer token)"] screens --> linking["expo-linking
(deep links: drop://)"] end subgraph web["Web App (Next.js 15)"] web_screens["Screens
(10 screens)"] web_hooks["Shared Hooks"] web_types["Shared TypeScript Types"] end subgraph backend["Backend"] hono["Hono v4 API
(/v1/* - Bearer auth)"] nextjs["Next.js BFF
(/api/* - Cookie auth)"] end hooks -.->|"Shared React code"| web_hooks types -.->|"Shared types"| web_types mobile --> hono web --> nextjs classDef expo fill:#E3F2FD,stroke:#1565C0 classDef web_style fill:#C8E6C9,stroke:#2E7D32 classDef backend_style fill:#FFF3E0,stroke:#E65100 class screens,hooks,types,camera,browser,notif,storage,linking expo class web_screens,web_hooks,web_types web_style class hono,nextjs backend_style Key Expo Modules Used Module Purpose Drop Feature expo-camera Camera access + barcode scanning QR payment scanning expo-web-browser Secure in-app browser BankID OIDC authentication expo-notifications Push notification handling Transaction alerts, payment receipts expo-linking Deep link handling ( drop:// ) BankID callback, notification deep links @react-native-async-storage Persistent key-value store Bearer token storage expo-secure-store Encrypted storage Sensitive data (future biometric) expo-local-authentication Biometric auth App unlock (Phase 2) Mobile-Specific Auth Flow The mobile BankID flow differs from web: GET /v1/auth/bankid/initiate?platform=mobile returns { redirectUrl, state } Open BankID in expo-web-browser (secure, isolated browser) BankID redirects to drop://auth/callback?code=&state= expo-linking catches the deep link POST /v1/auth/bankid/callback exchanges code for Bearer token Token stored in AsyncStorage (7-day lifetime) Consequences Positive Single language (TypeScript) across web, mobile, and backend High code reuse: shared types, hooks, and validation logic with web app OTA updates via EAS enable rapid hotfixes without App Store review cycle Managed workflow eliminates native build complexity expo-camera provides built-in barcode scanning for QR payments expo-web-browser provides secure BankID integration Large React Native ecosystem for additional modules Negative Expo managed workflow limits access to some native APIs (can eject if needed) App size larger than pure native (~25MB vs ~5MB) JavaScript bridge performance for heavy computation (not a concern for Drop's use case) Must use Expo-compatible packages (some React Native packages require ejection) EAS build service adds to CI costs Risks Expo SDK upgrade breakage: Major Expo SDK upgrades can break packages. Mitigation: managed workflow handles most upgrades; test thoroughly before upgrading. App Store rejection: Financial apps face stricter App Store review. Mitigation: ensure compliance with App Store Review Guidelines section 3.1 (payments) and 5.1 (privacy). Performance on low-end devices: React Native may lag on older Android devices. Mitigation: minimal animations, lazy loading, optimized list rendering. References ADR-008: Hono API Framework -- Mobile API backend Authentication System -- Mobile BankID flow Component Overview (C4 Level 3) -- Mobile app components ADR-007: BankID OIDC Auth -- Authentication provider Expo documentation: docs.expo.dev