GenericJam

GenericJam

Mob - Native BEAM / Elixir on Native Mobile

Edit: 2026 May 15 - This post is archived.

Mob is alive!!

Main docs: mob v0.7.11 — Documentation

A bit of explanation for the slightly convoluted repo structure. There needs to be three repos:
mob lives in the app you create.
mob_dev is a dev dependency so it doesn’t make it into your production app. It creates a dev server which allows you to connect to the app while it’s running. Also it’s full of mix tasks and such to help you manage your devices, deploying code, etc.
mob_new is the installer which you install with mix archive.install hex mob_new

After that you just run these commands to create an app, install the dependencies and deploy to all the ios and android devices on your system:

mix mob.new my_app 
cd my_app
mix mob.install
mix mob.install --ios --android

The ethos of mob is combining the best of Elixir and the BEAM with the best of mobile. I think they both have good and interesting things to contribute. I want to make things useful and accessible while also being powerful. It is a developer first ecosystem with good ergonomics just like the rest of Elixir.

We already have the first app in the App Store: ‎AirCartMax App - App Store
We will soon (already have?) the first app in the Play Store: https://play.google.com/store/apps/details?id=com.beyondagronomy.aircartmax

So all of the questions regarding the viability of the project have been answered.
There were also some questions around battery usage. There are some battery tests in mob_dev you can run but this has been a non issue for all users as far as I can tell.


I’ve posted a couple times about this topic before:

I’m hoping the description below is close to the final iteration of what the Elixir community would like in a mobile app framework. Working title, mob.

BEAM-on-device mobile framework, looking for feedback

I am working on a mobile framework for Elixir that takes a different approach than what’s out there although it combines a bit of every approach so far. Looking for early feedback before going further.

The idea in one sentence:

Write mobile apps in Elixir using a LiveView-style lifecycle: mount, render, handle_event, where the BEAM runs directly on the device and drives native UI through NIFs. No server, no JavaScript, no WebView.

How it actually works:

The app shell (Android APK / iOS IPA) is a thin native wrapper that boots the BEAM on startup. From that point, Elixir owns the app. render/1 returns a component tree; the renderer walks it and makes NIF calls that create and mutate real native views — Android Views on Android, UIKit on iOS. State changes trigger a diff and only the changed views are updated. The native shell is just a display surface; all logic lives in Elixir.

  defmodule MyApp.CounterScreen do
    use Mob.Screen

    def mount(_params, _session, socket) do
      {:ok, assign(socket, :count, 0)}
    end

    def render(assigns) do
      %{type: :column, props: %{padding: 16}, children: [
        %{type: :text,   props: %{text: "Count: #{assigns.count}"}},
        %{type: :button, props: %{text: "+", on_tap: self()}}
      ]}
    end

    def handle_event("tap", _, socket) do
      {:noreply, assign(socket, :count, socket.assigns.count + 1)}
    end
  end

If you already know LiveView, that lifecycle is immediately familiar. The intent is that transitioning to mobile should feel like learning a new set of components, not a new paradigm. That being said, delivering to the web is a dream come true in terms of distribution. We can’t get away from having to submit via app stores, etc. There very well could be some platform related glue code using gradle or plist files that you may still have to alter yourself. I’m not deep enough into it to know at this stage.

How it relates to existing work:

  • LiveView Native — closest in spirit, but LVN requires a Phoenix server. Mob runs fully on-device; no server needed, works offline, no latency on interactions. When
    people first heard “LiveView Native” a lot of them expected something like this — BEAM on the phone, LiveView-style code, native UI. LVN is excellent but it’s a
    different tradeoff.
  • Elixir Desktop — proved BEAM-on-device is viable. Mob builds on that insight but targets mobile-native UI patterns (component trees, event model) rather than desktop
    wxWidgets.
  • React Native — the component/props/event model is familiar territory for people coming from that world. mount ≈ component lifecycle, handle_event ≈ event handlers,
    assigns ≈ state. The diff-and-patch render loop is the same idea.

Dev experience goals:

Dev mode connects the device to your machine over Erlang distribution (WiFi, mDNS), no USB required, works on Android and iOS identically). The device boots a minimal shell and dials home.

mix mob.dev

on the dev machine starts a file watcher; save a file and the new module is pushed to the device, same loop / experience as

mix phx.server

Full IEx shell into the running on-device BEAM: inspect GenServer state, trace function calls.

OTA updates are supported. Beam bytecode runs in the embedded BEAM VM; same interpreted-code exception that covers React Native/CodePush and LiveView Native.

Code-signed delivery.

Current status:

HelloScreen confirmed working on Android emulator, real Android phone (non-rooted), and iOS simulator.

What I’m looking for:

  • Does the LiveView-on-device model resonate? Is this what you were hoping LVN would be?
  • Component vocabulary: what would you reach for first beyond the basics?
  • Any prior art I’m missing?
  • Would you use this?

Non goals for the project

  • All things to all people
  • Not targeting anything outside of iOS, Android, although I think this approach is fairly easy to replicate if you want to build a desktop app for Windows, etc.

I have a larger planning document I coauthored with Claude but I wanted to avoid a wall of LLM text. I can post that as well if people are interested for a fuller vision of the project.

Working on Android / iOS and I’ve also run this on my own Android device.

One of the things I thought was a blocker but turned out to be fine was the BEAM boot time. It takes about half a second depending on hardware.


Most Liked

GenericJam

GenericJam

Published! Give it a whirl!

This screenshot is the generated app you can get with mix mob.new my_test_app.

Any and all feedback is appreciated. You can open an issue if you find something. There’s probably lots wrong but it’s working ok for me. There’s an awful lot of surface area that needs fleshed out.

File issues here:
https://github.com/GenericJam/mob

GenericJam

GenericJam

Mob is in the Apple App Store!

Android will probably be another two weeks down to the review process.

GenericJam

GenericJam

I wrote a blog post that kind of summarizes a lot of this thread but also framework decisions made, etc.

Where Next?

Popular in Announcing Top

seancribbs
Today I released a new dialyzer Mix task as the dialyzex package! At the time we started writing this task, the existing dialyzer integra...
New
ityonemo
Currently just starting out on a new mini-project - getting zig NIFs to run in elixir. https://github.com/ityonemo/zigler The idea here...
New
Crowdhailer
I have been updating a library that allows you to pipe between functions that use the erlang result tuple convention. Assuming you have ...
New
mtrudel
Bandit is an HTTP server for Plug and WebSock apps. Bandit is written entirely in Elixir and is built atop Thousand Island. It can serve...
New
Crowdhailer
Experimenting with this code. OK.try do user <- fetch_user(1) cart <- fetch_cart(1) order = checkout(cart, user) save_orde...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36352 110
New
josevalim
Hello everyone, We have just released NimbleCSV which is a small and fast CSV parsing library for Elixir. It allows developers to define...
New
marcuslankenau
I feel kind of stuck with the absence of a proper xml library for Elixir. Currently I use SweetXML which was ok for me more or less to pa...
New
mplatts
With HEEX released we decided to start a components library using Tailwind CSS - check it out here: Petal Components. We also have a boi...
New
tmbb
I’ve decided to create this topic to discuss optimization possibilities for something like Phoenix LiveView. I’ve created this topic unde...
144 10462 141
New

Other popular topics Top

stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43757 214
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New

We're in Beta

About us Mission Statement