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, 🟡 = partial or not yet verified on a device, — = not supported, n/a = not applicable on that platform.
A ✅ capability may live in core or in a first-party plugin
(0.7.0 extracted camera, photos, location, notifications, biometrics,
scanning, and Bluetooth into mob_* capability packages). The Notes
column names the supplying plugin; rows without one are core. Plugins
activate with the dep + config :mob, :plugins, [...] in mob.exs —
see the Plugins guide.
UI components (render tree)
Elements you can use inside ~MOB. The set is intentionally small
and orthogonal — composition over a fat component library.
Component
Status
iOS
Android
Notes
<Box>
✅
✓
✓
Container with align, padding, background, corner radius, border
<Column>, <Row>
✅
✓
✓
Flex layouts
<Wrap>
✅
✓
✓
Measured wrapping layout for chips, tags, and pills
<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)
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 pickers
❌
—
—
Plugin candidate
<SearchBar>
❌
—
—
Native search bar (UISearchBar / SearchBar). Plugin candidate
<DatePicker>
❌
—
—
Plugin candidate
<Modal> (sheet presentation)
✅
✓
✓
Mob.UI.sheet/2 — native modal sheet composing ordinary Mob nodes (iOS .sheet, Android Material 3 ModalBottomSheet). Android needs an app generated by mob_new ≥ 0.4.24. Programmatic alerts + action sheets also available via Mob.Alert
Pull-to-refresh
❌
—
—
Missing; commonly requested. Plugin candidate
Bottom sheets
✅
✓
✓
Same primitive as <Modal> above — Mob.UI.sheet/2 with :detents ([:medium, :large] subset). iOS cannot set the system dimming opacity, so :scrim is applied exactly on Android and approximated on iOS
Drawer navigation
❌
—
—
Plugin candidate; mob's nav model is stack-based today
Touch, gesture, input
Capability
Status
iOS
Android
Notes
Tap / double-tap / long-press
✅
✓
✓
on_tap, on_double_tap, on_long_press props
Press in / out (hold)
✅
✓
✓
on_press_in, on_press_out props (MOB-380); Mob.Test.hold_xy/4 drives a real held touch on Android
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 / zoom
❌
—
—
Plugin candidate; common for image/map views
Rotation gesture
❌
—
—
Plugin candidate
Hardware keyboard events
❌
—
—
key_press/1 exists for the test harness but not as a user-facing API
Keyboard show/hide events
❌
—
—
Missing; commonly needed for keyboard-aware layouts
mob_speech plugin (MobSpeech.listen/2; platform recognizer by default, or offline whisper.cpp via mob_whisper). Android verified; iOS builds, not yet run on a device
Voice activity detection
❌
—
—
Plugin candidate
Audio effects (reverb, EQ)
❌
—
—
Plugin candidate
Camera zoom / focus / exposure
🟡
🟡
🟡
Basic capture works; fine-grained control missing
Torch / flashlight
✅
✓
✓
Mob.Torch.on/1, off/1, set/2 — core, no camera session or permission. On/off only (brightness level is a follow-up)
MobBluetooth.Le (mob_bluetooth 0.3.0) — GATT peripheral role only (advertise + notify + receive writes), iOS + Android; BLE central (scan/connect) is a future addition
NFC
✅
✓
✓
mob_nfc plugin — read/write NDEF tags, raw tag UIDs (CoreNFC / NfcAdapter); tag emulation (HCE) is Android-only
Mob.Motion.start(:magnetometer, ...) — µT-calibrated mag + fused heading (0.7.14); keys present only when :magnetometer requested
Barometer
🟡
🟡
✓
MobSensors.read/2 / start/2 with :pressure (mob_sensors plugin), in hPa. iOS uses CMAltimeter (kPa converted to hPa) and hasn't been verified on a device yet
Proximity
🟡
🟡
✓
:proximity (mob_sensors), in cm. On iOS it's iPhone-only UIDevice proximity monitoring: near is [0.0], far is [5.0], and the screen blanks while something is near. Not yet verified on a device
Ambient light
🟡
—
✓
:light (mob_sensors), in lux. iOS has no public ambient-light API
Pedometer / step counter
🟡
🟡
🟡
:step_counter and MobSensors.steps/2 (mob_sensors); both need :activity_recognition. Android counts steps since boot and keeps no history (steps/2 → {:error, :history_unavailable}). iOS uses CMPedometer: steps since midnight plus history queries. Not yet verified on hardware
Other sensors (humidity, ambient temperature, gravity, rotation vectors, hinge angle, heart rate, vendor sensors)
🟡
—
✓
mob_sensors: MobSensors.list/0 returns every Android sensor; vendor sensors are read by their string type
Compass / heading
✅
✓
✓
Fused heading (degrees from magnetic north) via Mob.Motion:magnetometer — same request as above
Location
Capability
Status
iOS
Android
Notes
One-shot location
✅
✓
✓
MobLocation.get_once/1 (mob_location plugin)
Continuous updates
✅
✓
✓
MobLocation.start/2, stop (mob_location plugin)
Background location
🟡
🟡
🟡
Mob's foreground-service keep-alive lets updates continue while backgrounded; not a true background-location API
MobNotify.register_push/1 (mob_notify plugin) → token to handle_info
Push delivery via APNs / FCM
✅
✓
✓
Via mob_push Hex package
Notification tap handling
🟡
✓
🟡
{:notification, %{presentation: :foreground | :tap}} (Mob.Notification), including the tap that cold-launches the app, delivered once. Android: local notifications, and taps on pushes that carry mob_push's mob_notification_json data key (per FCM's documented behaviour, not device-verified); a push sent without it carries no mob payload
MobScanner.scan/2 (mob_scanner plugin; activate mob_camera too — it owns :camera) — full-screen scanner with format filtering
TFLite model inference
✅
✓
✓
Via mix mob.enable tflite (mob_dev 0.5.7+) — NNAPI/MTK on Android, Core ML delegate on iOS. The nx_tflite_mob package runs .tflite models with vendor accelerators (Apple Neural Engine, MediaTek/Qualcomm GPU+NPU)
Nx-based inference
🟡
🟡
🟡
mob_nx_eigen plugin — Eigen CPU Nx backend; spike, API surface still narrow
Apple Vision framework wrappers
🟡
🟡
n/a
mob_vision wraps VNRecognizeTextRequest (text recognition); face detection and image classification are plugin candidates
Apple Foundation Models (LLM)
❌
—
n/a
Plugin in flight — see mob PR #8 (DRAFT)
MLKit wrappers (Android)
🟡
n/a
🟡
Barcode scanning uses it under the hood; mob_vision uses ML Kit text recognition; face and pose models are plugin territory
OCR (text recognition)
🟡
🟡
🟡
MobVision (mob_vision plugin) — still-image text recognition via iOS Vision / Android ML Kit, no permission needed; no device run recorded yet
Face detection
❌
—
—
Plugin candidate
Pose detection
❌
—
—
Plugin candidate
Speech-to-text
🟡
🟡
✓
mob_speech + mob_whisper (on-device whisper.cpp); see Speech recognition above
Translation
❌
—
—
Plugin candidate
Smart Reply
❌
—
—
Plugin candidate
Maps
Capability
Status
iOS
Android
Notes
Native map view
❌
—
—
Plugin candidate (Apple Maps / Google Maps)
Annotations / markers
❌
—
—
Plugin candidate
Polylines / polygons
❌
—
—
Plugin candidate
User location display
❌
—
—
Plugin candidate
Map tile providers (Mapbox, etc.)
❌
—
—
Plugin candidate
System integration
Capability
Status
iOS
Android
Notes
Clipboard
✅
✓
✓
Mob.Clipboard.put/1, get/0
Open URL (outgoing: browser, mail, tel, another app)
Opened by a URL (incoming deep link, custom scheme)
🟡
🟡
✓
{:link, %{url: url, source: :launch | :running}} (Mob.Link), including the link that cold-launches the app, delivered once; Mob.Link.register/1 routes elsewhere. Schemes from config :mob_dev, url_schemes: [...] in mob.exs (mob_dev 0.7.12+); Android VIEW intents and iOS scene URL contexts forwarded by mob_new 0.6.4+ templates. iOS not yet run on a simulator or device
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 preference
❌
—
—
Plugin candidate
Bold-text preference
❌
—
—
Plugin candidate
Dynamic type / font scaling
🟡
🟡
🟡
iOS automatic via system size; explicit override needed
RTL support
🟡
🟡
🟡
Layout-engine level; no explicit I18nManager equivalent
Accessibility test inspection
✅
✓
✓
Mob.Test reads the AX tree for assertion-based UI testing
iOS-only platform features
Capability
Status
Notes
Live Activities / Dynamic Island
⛔
Requires Widget Extension target — separate from main app; not a Mob template today
Widgets (home + lock screen)
⛔
Same — Widget Extension target
App Clips
⛔
App Clip target; not in Mob templates
Watch app companion
⛔
WatchKit target; not in Mob templates
Share extensions
⛔
Share Extension target; not in Mob templates
Today extensions (deprecated by Apple)
⛔
—
Background App Refresh
❌
Plugin candidate
Apple Pencil events
❌
Plugin 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
🟡
Custom schemes: Mob.Link (see System integration). Universal links need an associated-domains entitlement and arrive as NSUserActivity, which the template does not forward
Handoff / NSUserActivity
❌
Plugin candidate
Spotlight indexing
❌
Plugin candidate
App Shortcuts (Siri integration)
❌
Plugin candidate
Android-only platform features
Capability
Status
Notes
Home screen widgets
⛔
AppWidgetProvider — separate component, not in Mob templates
Quick Settings tiles
⛔
TileService — separate component
App Shortcuts (long-press launcher)
❌
Plugin candidate
Picture in Picture
❌
Plugin candidate
Multi-window
✅
Works via resizable activity flag
Split-screen
✅
Works via resizable activity flag
Foldable / large-screen support
🟡
Layout adapts; no first-class foldable APIs
Auto Backup
✅
Honored by default per AndroidManifest
Doze mode handling
❌
Plugin candidate (alarm/wake-up scheduling)
Direct Share
❌
Plugin candidate
Notification channels (configurable)
🟡
Default channel works; per-app multi-channel API is partial
Architecturally not present (and probably shouldn't be)
Item
Why
JavaScript / TypeScript runtime
Mob's host language is Elixir/Erlang/Gleam on BEAM; bridging JS would defeat the architecture
React reconciler
Mob has its own render tree; no React VDOM under it
CSS / Yoga flexbox engine
iOS uses SwiftUI layout; Android uses Compose layout; both are native flexbox-equivalents
XMLHttpRequest / fetch polyfill
Use Erlang/Elixir HTTP libraries directly (:req, :finch, :gun)
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.
Related docs
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)