# `mix mob.adopt`
[🔗](https://github.com/genericjam/mob_dev/blob/master/lib/mix/tasks/mob/adopt.ex#L1)

Adds Mob (mobile framework) to an existing Phoenix-based Elixir project.

## ⚠ Experimental (pre-1.0)

`mix mob.adopt` is experimental. On anything outside the supported
shapes the task refuses with a clear message rather than risk
breaking your app. The supported surface will widen as we stabilise.

### Supported (default — LV bridge)

- Single (non-umbrella) Phoenix project.
- Stock `assets/js/app.js` (contains `new LiveSocket(...)`).
- Stock root layout (`lib/<app>_web/components/layouts/root.html.heex`
  or the legacy `templates/layout/root.html.heex`) with a `<body>`
  tag.
- **Ecto Repo uses the SQLite adapter** (`:ecto_sqlite3` in deps).
  The generated `mob_app.ex` migrates `<App>.Repo` on-device; the
  SQLite assumption is hard-coded. A `mix phx.new --database sqlite3`
  project matches.

### Supported (`--no-live-view` — thin-client)

Same Phoenix-shape requirements but **no Ecto/Repo constraint** —
the phone opens a deployed Phoenix server via WebView and runs no DB
on-device. Works against Postgres / MySQL / `--no-ecto` hosts.

### Refused (loud, with guidance)

- Umbrella applications.
- Non-Phoenix projects (no `:phoenix` dep).
- Heavily customised `app.js` (no recognisable `new LiveSocket(`).
- Heavily customised root layout (no recognisable `<body>` tag, or
  no layout file at all).
- **LV mode** + host Repo uses Postgres / MySQL / MSSQL (or no Repo
  at all). Use `--no-live-view` instead, or wait for the future
  `--with-local-repo` mode that handles non-SQLite hosts via a
  separate on-device LocalRepo.

Composable, [Igniter](https://hex.pm/packages/igniter)-based — mirrors
the architecture of [team-alembic/phx_install](https://github.com/team-alembic/phx_install).
This is the install-into-existing counterpart to `mix mob.new`, which
generates a project from scratch. `mix mob.new` is unaffected by this task.

## Usage

    mix mob.adopt [OPTIONS]

Run from inside an existing Mix project. The target project must
declare `{:igniter, "~> 0.7", only: [:dev, :test]}` in its mix.exs
(most modern Phoenix-ecosystem projects already do).

The native trees (`--android` / `--ios`, on by default) render from
mob_new's templates, so they also require the **mob_new archive
installed**:

    mix archive.install hex mob_new

mob_new stays the single source of native templates (no duplication
across repos). The Elixir-side adoption (deps, LiveView bridge,
`mob.exs`, `MobScreen`) needs no archive — only `--android`/`--ios` do.

## Options

- `--no-ios` — skip the iOS native tree
- `--no-android` — skip the Android native tree
- `--local` — `path:` deps for `:mob`/`:mob_dev`; pre-fill `mob.exs`
  paths from `MOB_DIR` / `MOB_DEV_DIR`. For Mob framework contributors.
- `--python` — iOS-only: pre-configure embedded CPython via Pythonx
- `--host-url URL` — write `config :mob, host_url: URL` so the
  generated `MobScreen` opens `URL` instead of the default
  `http://127.0.0.1:4000/`. Use for thin-client deployments where
  the WebView points at a deployed Phoenix server (fly.io etc.).
- `--no-live-view` — skip the LiveView bridge patches
  (`assets/js/app.js` MobHook, `root.html.heex` bridge div) AND
  generate a thin-client `mob_app.ex` that does NOT boot Phoenix
  on-device. For Hologram-only or non-Phoenix hosts where the
  BEAM-on-device is just the native interop layer.

Both platforms emit by default. Passing both `--no-ios` and
`--no-android` raises.

## What gets installed

- `:mob` + `:mob_dev` deps in `mix.exs`
- `lib/<app>/mob_screen.ex` — `Mob.Screen` opening a WebView at
  `Application.get_env(:mob, :host_url)` (default localhost)
- `mob.exs` — build-environment config
- `.gitignore` updated to ignore `mob.exs`
- `android/` and/or `ios/` native trees (gated by platform flags)
- `lib/<app>/mob_app.ex` + `src/<app>.erl` for on-device BEAM entry
- `erlc_paths`/`erlc_options` added to `mix.exs`

Default (no `--no-live-view`):
- `MobHook` injected into `assets/js/app.js`
- bridge `<div>` injected into `root.html.heex`
- `mob_app.ex` boots the host Phoenix endpoint on-device

With `--no-live-view`:
- LiveView bridge patches skipped
- `mob_app.ex` is the thin-client variant (`use Mob.App` shell,
  no `Application.ensure_all_started`)

## Composability

Every sub-installer is invokable independently:

    mix mob.adopt.deps          # just bump mix.exs
    mix mob.adopt.bridge        # just patch app.js + root.html.heex
    mix mob.adopt.screen        # just generate mob_screen.ex
    mix mob.adopt.mob_app       # just generate mob_app.ex + .erl bootstrap
    mix mob.adopt.mob_exs       # just write mob.exs + .gitignore
    mix mob.adopt.native        # both native trees
    mix mob.adopt.native.android
    mix mob.adopt.native.ios
    mix mob.adopt.finalize      # post-install notice (no file changes)

Each accepts the same flags as `mob.adopt` and respects them
individually. Run `mix help mob.adopt.<sub>` for sub-task docs.

On-device runtime services (`Mob.ComponentRegistry`,
`Mob.NativeLogger`, etc.) start imperatively inside
`<App>.MobApp.start/0` — `Mob.App` is the *behaviour* the device
entry uses (via `use Mob.App`), never a supervision-tree child.

The native trees come from mob_new's `priv/templates/mob.new/`; the
Elixir-source content (`mob_screen.ex`, `mob_app.ex`, the LV bridge
patches) from `MobDev.Adopt.Patcher` / `MobDev.Adopt.Generator`, both
duplicated from mob_new pending the Phase-5 Igniter reunification.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
