Mobile surface matrix

Copy Markdown View Source

What Mob covers — what's solid, what's partial, what's missing. Use this to set realistic expectations before starting an app, and to spot gaps worth filling (either in mob core, in a plugin, or by declaring out-of-scope).

The reference surface is the union of React Native core, Expo SDK modules, and platform-native capabilities both ecosystems have converged on as "what mobile apps need." Many missing items are pluggable — see MOB_PLUGINS.md for the manifest spec.

This doc is hand-maintained from inspection of lib/mob/ and src/mob_nif.erl. If you add a capability, update the matching row.

Legend

Fully present — public Elixir API, both iOS + Android (unless noted)
🟡Partial — works but limited (single platform, narrow API, or known caveats)
Missing — could be a plugin or future core addition
Out of scope — requires separate deployment target (widgets, Watch app), or fundamentally incompatible with Mob's architecture

Per-platform columns: = supported, = not supported, n/a = not applicable on that platform.


UI components (render tree)

Elements you can use inside ~MOB. The set is intentionally small and orthogonal — composition over a fat component library.

ComponentStatusiOSAndroidNotes
<Box>Container with align, padding, background, corner radius, border
<Column>, <Row>Flex layouts
<Text>Font, color, size, weight, align, line height, letter spacing
<Button>Tap handler, text, background, fill width
<Image>Local + remote (Coil on Android, AsyncImage on iOS)
<TextField>Keyboard type, return key, placeholder, change events
<Toggle>Boolean switch
<Slider>Min/max/value, change events
<Progress>Linear + circular
<Divider>Horizontal line separator
<Spacer>Layout filler
<Scroll>Vertical or horizontal, scroll observation on iOS 18+
<List>Vertical / horizontal stack with selection
<LazyList>Virtualised long-list with on_end_reached pagination
<TabBar>Bottom tab bar (Material 3 NavigationBar on Android, SwiftUI Tab on iOS)
<WebView>Inline web view, JS bridge, navigation control
<CameraPreview>Live preview with frame stream
<Video>🟡🟡Android: ExoPlayer integration pending
<GpuView>Metal (iOS) / GLES 3.0 (Android) fragment shader surface
Custom views via <NativeView>Register a plugin-defined render-tree node type
Date / Time / Color pickersPlugin candidate
<SearchBar>Native search bar (UISearchBar / SearchBar). Plugin candidate
<DatePicker>Plugin candidate
<Modal> (sheet presentation)🟡🟡🟡Programmatic alerts + action sheets exist; full sheet-style modal is plugin territory
Pull-to-refreshMissing; commonly requested. Plugin candidate
Bottom sheetsPlugin candidate
Drawer navigationPlugin candidate; mob's nav model is stack-based today

Touch, gesture, input

CapabilityStatusiOSAndroidNotes
Tap / double-tap / long-presson_tap, on_double_tap, on_long_press props
Swipe (l/r/u/d)on_swipe_left, etc.
Pan / drag gesture🟡🟡🟡Tap-based; full pan-responder system (like react-native-gesture-handler) is missing
Pinch / zoomPlugin candidate; common for image/map views
Rotation gesturePlugin candidate
Hardware keyboard eventskey_press/1 exists for the test harness but not as a user-facing API
Keyboard show/hide eventsMissing; commonly needed for keyboard-aware layouts
<KeyboardAvoidingView> equivalentPlugin / core candidate
Apple Pencil / stylus eventsn/aPlugin territory
3D Touch / Force Touchn/aDeprecated by Apple; low priority
Drag and drop (cross-app)Plugin candidate
Haptic feedbackMob.Haptic.tap/1 etc.

Device + system info

CapabilityStatusiOSAndroidNotes
Platform detectionMob.Device.platform/0 returns :ios or :android
OS versionMob.Device.os_version/0
Device modelMob.Device.model/0
Foreground / background stateMob.Device.foreground?/0 + {:device, :foreground/:background, ...} events
Battery level + stateMob.Device.battery_level/0, battery_state/0
Thermal stateMob.Device.thermal_state/0
Low-power modeMob.Device.low_power_mode?/0
Color scheme (light/dark)Mob.Theme.color_scheme/0 + Mob.Theme.Adaptive (auto-watch)
Safe area insetsMob.Device.safe_area/0
Screen dimensions / pixel ratioMob.Device.screen_info/0
Locale / language🟡🟡🟡Derivable from system; no first-class API
Time zone🟡🟡🟡Use Erlang's :calendar directly
Network info (cell vs wifi, type)Plugin candidate (NetInfo equivalent)
Network reachabilityPlugin candidate
Screen brightnessPlugin candidate
Screen orientation lockPlugin candidate
Idle timer / screen wakePlugin candidate
Exit appn/aAndroid only; iOS forbids programmatic exit

Storage

CapabilityStatusiOSAndroidNotes
Key-value storeMob.Storage with typed schemas, namespacing
Files APIMob.Files, plus Mob.Storage.dir/1 for app-private paths
External files dir (Android)n/astorage_external_files_dir/1
Save to photo libraryMob.Storage.save_to_photo_library/1 + Android MediaStore equivalent
SQLiteVia :ecto_sqlite3 + bundled libsqlite3_nif.so
Keychain / KeystorePlugin candidate (standalone API beyond biometric)
Secure-storage / encrypted-storagePlugin candidate

Camera + microphone

CapabilityStatusiOSAndroidNotes
Capture photoMob.Camera.capture_photo/1
Capture videoMob.Camera.capture_video/1
Live preview<CameraPreview> component
Per-frame streamMob.Camera.start_frame_stream/2 — pushes RGBA frames to handle_info
Photo library pickerMob.Photos.pick/2
Audio recordingMob.Audio.start_recording/2
Audio playbackMob.Audio.play/3, stop, volume
Speech recognitionPlugin candidate (SFSpeechRecognizer / SpeechRecognizer)
Voice activity detectionPlugin candidate
Audio effects (reverb, EQ)Plugin candidate
Camera zoom / focus / exposure🟡🟡🟡Basic capture works; fine-grained control missing

Connectivity

CapabilityStatusiOSAndroidNotes
Bluetooth Classicn/aMob.Bt + Hfp / Spp / Hid sub-modules
Bluetooth Low Energy (BLE)Plugin candidate — common request
NFCPlugin candidate (Core NFC / Android NFC)
WiFi info / scanningPlugin candidate; OS restrictions apply
USB hostn/aMob.VendorUsb — bulk read/write, custom devices
WebSocket client🟡n/an/aUse Elixir libs directly (e.g. :gun)
HTTP client🟡n/an/aUse Elixir libs (:req, :finch)
File upload progressPlugin candidate
Background download/uploadPlugin candidate
mDNS / BonjourPlugin candidate
Sockets (raw TCP/UDP)🟡n/an/aUse Erlang's :gen_tcp/:gen_udp
Mob.Dist (BEAM clustering)Hot-push, device → desktop connection

Sensors

CapabilityStatusiOSAndroidNotes
AccelerometerMob.Motion.start(:accelerometer, ...)
GyroscopeMob.Motion.start(:gyro, ...)
MagnetometerPlugin candidate; CMMotionManager / Sensor.TYPE_MAGNETIC_FIELD
BarometerPlugin candidate
ProximityPlugin candidate
Ambient lightPlugin candidate
Pedometer / step counterPlugin candidate
Compass / headingPlugin candidate

Location

CapabilityStatusiOSAndroidNotes
One-shot locationMob.Location.get_once/0
Continuous updatesMob.Location.start/1, stop
Background location🟡🟡🟡Mob's foreground-service keep-alive lets updates continue while backgrounded; not a true background-location API
GeofencingPlugin candidate (CLCircularRegion / Geofencing API)
Significant-change updatesPlugin candidate (iOS)
Mock-location detectionPlugin candidate
Reverse geocodingUse third-party API for now (e.g. Mapbox)

Notifications

CapabilityStatusiOSAndroidNotes
Local notification schedulingMob.Notify.schedule/2, cancel
Push notification registrationMob.Notify.register_push/0 → token to handle_info
Push delivery via APNs / FCMVia mob_push Hex package
Notification tap handlingForeground + background + cold-start (take_launch_notification/0)
Notification actions (buttons)Plugin / core candidate
Critical / time-sensitive flags (iOS)n/aPlugin candidate
Notification grouping / threadingPlugin candidate
Badge management🟡🟡🟡Basic only

Background tasks

CapabilityStatusiOSAndroidNotes
Foreground service / keep-aliveMob.Background.keep_alive/0
Background fetch (silent periodic)Plugin candidate (iOS Background Tasks framework / Android WorkManager)
Silent push handling🟡🟡🟡Push arrives but no dedicated "wake-and-handle-then-suspend" lifecycle
Background URL sessionPlugin candidate
Scheduled jobs (periodic / one-shot)Plugin candidate (WorkManager equivalent)

Auth + payment

CapabilityStatusiOSAndroidNotes
Biometric auth (Face ID / fingerprint)Mob.Biometric.authenticate/2
Apple Sign-Inn/aPlugin candidate (common requirement for App Store)
Google Sign-InPlugin candidate
Sign in with X / Facebook / etc.Plugin candidate
OAuth flow helpersPlugin candidate; can mostly be done from Elixir
In-app purchase (StoreKit / Play Billing)Plugin candidate; sensitive — needs receipt validation
Apple Payn/aPlugin candidate
Google PayPlugin candidate
Passkeys / WebAuthnPlugin candidate

ML / Vision

CapabilityStatusiOSAndroidNotes
QR / barcode scanningMob.Scanner.scan/1 — full-screen scanner with format filtering
TFLite model inferenceVia mix mob.enable tflite (mob_dev 0.5.7+) — NNAPI/MTK on Android, Core ML delegate on iOS
Nx-based inference🟡🟡🟡Via nx_eigen exploration; not formalised
Apple Vision framework wrappersn/aPlugin candidate (text recognition, face detection, image classification)
Apple Foundation Models (LLM)n/aPlugin in flight — see mob PR #8 (DRAFT)
MLKit wrappers (Android)🟡n/a🟡Barcode scanning uses it under the hood; other models (text, face, pose) are plugin territory
OCR (text recognition)Plugin candidate
Face detectionPlugin candidate
Pose detectionPlugin candidate
Speech-to-textPlugin candidate
TranslationPlugin candidate
Smart ReplyPlugin candidate

Maps

CapabilityStatusiOSAndroidNotes
Native map viewPlugin candidate (Apple Maps / Google Maps)
Annotations / markersPlugin candidate
Polylines / polygonsPlugin candidate
User location displayPlugin candidate
Map tile providers (Mapbox, etc.)Plugin candidate

System integration

CapabilityStatusiOSAndroidNotes
ClipboardMob.Clipboard.put/1, get/0
Open URL (deep linking, browser)Mob.Device.open_url/1 — picks browser, mail, tel, etc.
Share sheet (text)Mob.Share.text/1
Share sheet (image / file)Plugin candidate
Document pickerMob.Files.pick/1
Action sheet (iOS-style menu)action_sheet_show/2 via Mob.Alert
Toast (Android-style)toast_show/2 — implemented on both platforms
Alert dialogMob.Alert.alert/2
Vibration patternsVia Mob.Haptic
App settings page (open)Plugin candidate
Calendar eventsPlugin candidate
ContactsPlugin candidate
Reminders (iOS)n/aPlugin candidate
Permissions facadeMob.Permissions.request/2 for camera, microphone, photos, location, notifications

Accessibility

CapabilityStatusiOSAndroidNotes
Accessibility labels / hints🟡🟡🟡Some component props expose this; not uniform across all components
Screen reader announcements (imperative)Plugin / core candidate
Focus management (programmatic)Plugin / core candidate
Reduce-motion preferencePlugin candidate
Bold-text preferencePlugin candidate
Dynamic type / font scaling🟡🟡🟡iOS automatic via system size; explicit override needed
RTL support🟡🟡🟡Layout-engine level; no explicit I18nManager equivalent
Accessibility test inspectionMob.Test reads the AX tree for assertion-based UI testing

iOS-only platform features

CapabilityStatusNotes
Live Activities / Dynamic IslandRequires Widget Extension target — separate from main app; not a Mob template today
Widgets (home + lock screen)Same — Widget Extension target
App ClipsApp Clip target; not in Mob templates
Watch app companionWatchKit target; not in Mob templates
Share extensionsShare Extension target; not in Mob templates
Today extensions (deprecated by Apple)
Background App RefreshPlugin candidate
Apple Pencil eventsPlugin candidate
Multi-window (iPad)🟡App runs but no first-class multi-scene API
Split View / Slide Over🟡Same as multi-window
Picture in Picture (video)Plugin candidate
Universal Links / Custom URL Scheme🟡Open URL works; route registration is per-app, no unified API
Handoff / NSUserActivityPlugin candidate
Spotlight indexingPlugin candidate
App Shortcuts (Siri integration)Plugin candidate

Android-only platform features

CapabilityStatusNotes
Home screen widgetsAppWidgetProvider — separate component, not in Mob templates
Quick Settings tilesTileService — separate component
App Shortcuts (long-press launcher)Plugin candidate
Picture in PicturePlugin candidate
Multi-windowWorks via resizable activity flag
Split-screenWorks via resizable activity flag
Foldable / large-screen support🟡Layout adapts; no first-class foldable APIs
Auto BackupHonored by default per AndroidManifest
Doze mode handlingPlugin candidate (alarm/wake-up scheduling)
Direct SharePlugin candidate
Notification channels (configurable)🟡Default channel works; per-app multi-channel API is partial

Architecturally not present (and probably shouldn't be)

ItemWhy
JavaScript / TypeScript runtimeMob's host language is Elixir/Erlang/Gleam on BEAM; bridging JS would defeat the architecture
React reconcilerMob has its own render tree; no React VDOM under it
CSS / Yoga flexbox engineiOS uses SwiftUI layout; Android uses Compose layout; both are native flexbox-equivalents
XMLHttpRequest / fetch polyfillUse Erlang/Elixir HTTP libraries directly (:req, :finch, :gun)
Babel / Metro / bundlerBEAM bytecode replaces JS bundling; mix mob.push ships .beam directly

How to use this matrix

  • Starting a new app: scan the ❌ rows first to see what would need to be a plugin or worked around.
  • Reporting a gap: if something here is wrong (mob has a capability I missed, or partial that's actually full), the doc is hand-maintained — please open a PR or flag it.
  • Filling a gap as a plugin: see MOB_PLUGINS.md for the manifest spec. Most ❌ rows are plugin candidates (tier 1 or tier 2 depending on whether they ship UI).
  • Filling a gap in core: when a capability is universal enough (every app needs it, both platforms support it cleanly) it's worth landing in core rather than as a plugin. The boundary is fuzzy; raising a discussion before doing the work is the right call.

This matrix isn't a roadmap commitment — it's a snapshot of reality. Some ❌ rows may stay ❌ for a long time because no one's asked. Others will land via community plugins. The intent is honest disclosure, not a promise of feature parity with React Native.


  • MOB_PLUGINS.md — plugin manifest spec for filling missing capabilities without merging into core
  • RELEASE.md — release process if you're shipping a new capability that lands in core
  • guides/styling.md — visual styling for the components above (tokens, themes, dark mode)
  • guides/support_matrix.md — minimum OS / ABI / SDK supported (a different "support matrix" — platform versions rather than capabilities)