Packages
mob
0.7.16
0.7.20
0.7.19
0.7.18
0.7.17
0.7.16
0.7.15
0.7.14
0.7.13
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.26
0.6.25
0.6.24
0.6.23
0.6.22
0.6.21
0.6.20
0.6.19
0.6.18
0.6.17
0.6.16
0.6.15
0.6.14
0.6.13
0.6.12
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.2
0.6.1
0.6.0
0.5.18
0.5.17
0.5.16
0.5.15
0.5.14
0.5.11
0.5.10
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.0
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.0
BEAM-on-device mobile framework for Elixir
Current section
Files
Jump to
Current section
Files
lib/mob.ex
defmodule Mob do
@moduledoc """
Mob — BEAM-on-device mobile framework for Elixir.
OTP runs on the device. Screens are GenServers. The UI is rendered by
Compose (Android) and SwiftUI (iOS) via a thin NIF. No server required.
## Quick start
defmodule MyApp.HomeScreen do
use Mob.Screen
def mount(_params, _session, socket) do
{:ok, Mob.Socket.assign(socket, :title, "Hello, Mob!")}
end
def render(assigns) do
%{
type: :column,
props: %{padding: :space_md},
children: [
%{type: :text, props: %{text: assigns.title, text_size: :xl}, children: []}
]
}
end
end
## Modules
- `Mob.App` — app entry point and navigation declaration
- `Mob.Screen` — screen behaviour and GenServer wrapper
- `Mob.Socket` — assigns and navigation API
- `Mob.Theme` — design token system
- `Mob.Renderer` — component tree serialisation
- `Mob.Test` — live device inspection and testing helpers
See the [Getting Started](guides/getting_started.html) guide to create your
first app. See [Architecture & Prior Art](guides/architecture.html) for how
Mob compares to LiveView Native, Elixir Desktop, React Native, Flutter, and
native development.
"""
defdelegate assign(socket, key, value), to: Mob.Socket
defdelegate assign(socket, kw), to: Mob.Socket
@doc """
A writable, app-private directory for runtime data — DB files, caches,
downloaded assets, anything you write at runtime.
On device this is `MOB_DATA_DIR`, set by the BEAM launcher to the platform's
persistent app-private location (iOS `NSDocumentDirectory`, Android
`getFilesDir()`). Off device (host/dev/tests) it falls back to `$HOME`, then
the current working directory. The directory is created if missing.
Use this — **not** `MOB_BEAMS_DIR`. `MOB_BEAMS_DIR` points inside the signed,
read-only `.app` bundle on iOS, so writing there fails with `:eperm`; it
happens to be writable on Android, which is how that trap stays hidden until
an app ships to iOS.
path = Path.join(Mob.data_dir(), "my.db")
See `data_dir/1` for a created subdirectory.
"""
@spec data_dir() :: String.t()
def data_dir do
dir =
System.get_env("MOB_DATA_DIR") ||
System.get_env("HOME") ||
File.cwd!()
File.mkdir_p!(dir)
dir
end
@doc """
Like `data_dir/0` but returns (and creates) the `sub` directory beneath it,
e.g. `Mob.data_dir("audio_cache")`.
"""
@spec data_dir(String.t()) :: String.t()
def data_dir(sub) when is_binary(sub) do
dir = Path.join(data_dir(), sub)
File.mkdir_p!(dir)
dir
end
end