create-mobile-surfaces
v2.0.0
Published
Guided installer for the Mobile Surfaces Expo iOS Live Activity starter.
Maintainers
Readme
create-mobile-surfaces
Guided installer for Mobile Surfaces, an Expo iOS starter for Live Activities, Dynamic Island, home-screen widgets, and iOS 18 control widgets.
Usage
Pick the package manager you already have on PATH:
npm create mobile-surfaces@latest
pnpm create mobile-surfaces
bun create mobile-surfacesThe installer detects whether the current directory is empty (greenfield) or an existing Expo app (add-to-existing) and runs the matching flow.
Scripted (non-interactive)
Pass --yes plus the required fields to skip every prompt. Useful for CI, AI agents, and expect-free automation:
npm create mobile-surfaces@latest --yes \
--name my-app --bundle-id com.acme.myapp \
--no-install| Flag | Description |
|------|-------------|
| --name <slug> | Project name. Required with --yes. |
| --scheme <scheme> | URL scheme. Defaults to slugified project name. |
| --bundle-id <id> | iOS bundle id. Required with --yes because the default com.example.<slug> is rejected by Apple on upload. |
| --team-id <id> | Apple Team ID. Optional. |
| --home-widget / --no-home-widget | Include the home-screen widget surface (default: yes). |
| --control-widget / --no-control-widget | Include the iOS 18 control widget (default: yes). |
| --install / --no-install | Run pnpm install + expo prebuild after scaffold (default: yes). |
| --yes, -y | Non-interactive: accept defaults, skip the recap. |
| --help, -h | Show help. |
Run npm create mobile-surfaces@latest --help for the canonical reference.
CI / GitHub Actions
A typical CI step that scaffolds and verifies a clean install. The CLI exits non-zero on any failure path, so the workflow stops early without needing custom branching:
- name: Scaffold Mobile Surfaces
run: |
npm create mobile-surfaces@latest --yes \
--name my-app --bundle-id com.acme.myapp \
--no-install
- name: Install + prepare iOS
run: cd my-app && pnpm install && pnpm mobile:prebuild:iosIf you want to branch on cause, use the canonical exit codes — 1 is user-error (bad inputs), 2 is environment-error (missing tools, install failed), 3 is a packaging issue with the CLI itself.
Exit codes
CI consumers can branch on these. The categories are coarse so adding a new failure path doesn't change the contract.
| Code | Meaning |
|------|---------|
| 0 | Success — also returned for --help, EPIPE, and prompts the user explicitly cancelled. |
| 1 | User-error — bad flag value, target dir not empty, --yes missing a required value, or the cwd is one we can't scaffold into (non-Expo with files, or apps/mobile/ already exists). |
| 2 | Environment-error — preflight failed, pnpm/CocoaPods missing on PATH, install failed, prebuild failed, or the apply phase threw. The fix is in your environment. |
| 3 | Template-error — the bundled template tarball or manifest is missing or unreadable. The published CLI is broken; please file an issue. |
| 130 | Interrupted — Ctrl+C / SIGINT during a task. POSIX convention (128 + SIGINT). |
Breaking change in v1.4: refuse paths (cannot-scaffold-here) used to exit 2. They now exit 1 so the contract reads 1=user, 2=env, 3=template. Any CI that checked for 2 to detect "wrong directory" should update.
What it does
Greenfield
- Preflight: macOS, Node 24, Xcode 26+, an iOS 17.2+ simulator runtime, pnpm, and CocoaPods.
- Prompts for project name, URL scheme, bundle identifier, Apple Team ID (optional), and whether to install + prebuild now.
- Materializes the starter, runs the rename script, installs, and runs
expo prebuild --platform ios.
Add-to-existing Expo
- Detects the existing
app.json/app.config.{js,ts}, plugins, deployment target, and Apple Team ID. - Plans which packages, plugins, Info.plist keys, and widget files to add. Surfaces a recap before any change is applied.
- Patches
app.jsonin place (or stages a paste-ready snippet for JS/TS configs), copies the SwiftUI widget target with names rewritten to your project's identity, and optionally runsexpo prebuild.
Requirements
- macOS with Xcode 26+
- Node 24
- pnpm 10+ for the greenfield flow (the template ships
pnpm-lock.yaml); npm / yarn / bun work in add-to-existing - An iOS 17.2+ simulator runtime
- CocoaPods (
gem install cocoapodsorbrew install cocoapods)
Links
License
MIT
