Skip to content
Shipping

Mobile apps

Expo / React-Native apps get the full treatment — live simulator preview, and debug · preview · production builds with signing, all on a Mac host. No EAS, no separate build service.

Overview

Add an expo service to your loor.json and Loor treats it as a real mobile app. Two things light up in the Studio preview pane: a Simulator tab (a live iOS / Android device streamed into the browser) and a Build tab (native builds, signed, downloadable). Both run on a Mac host attached to your project — the same machine, no EAS and no third-party build pipeline. Everything an app store needs — keystores, certificates, App Store Connect / Play uploads — is handled on Loor's side.

The mobile service

A mobile service is domainless: no domain, no HTTP port. It uses metroPort for the live dev server and builds to native artifacts. The minimum is just a type and root; the mobile block lets you pin bundle identifiers and per-profile settings.

"mobile": {
  "type": "expo",                 // or "react-native"
  "root": "apps/mobile",
  "metroPort": 8081,              // Metro dev server — mobile is domainless
  "mobile": {
    "platforms": ["ios", "android"],
    "ios":     { "bundleIdentifier": "com.acme.app", "deploymentTarget": "16.0" },
    "android": { "package": "com.acme.app", "minSdkVersion": 24 }
  }
}

Build profiles

Profiles mirror EAS so the mental model carries over. Each profile maps to a platform-specific build + distribution:

ProfileiOSAndroidFor
developmentDebug · unsigned simulator .appDebug .apkRun on the simulator / a dev device
previewRelease · internal .ipaRelease .apkShare with testers
productionRelease · App Store .ipa.aabShip to the stores
"build": {
  "profiles": {
    "development": { "ios": { "buildConfiguration": "Debug",   "simulator": true },          "android": { "buildType": "apk" } },
    "preview":     { "ios": { "buildConfiguration": "Release", "distribution": "internal" }, "android": { "buildType": "apk" } },
    "production":  { "ios": { "buildConfiguration": "Release", "distribution": "store" },     "android": { "buildType": "aab" } }
  }
}

Leave profiles out and Loor applies exactly this default matrix. Override only what you need.

Simulator preview

In the IDE preview pane, switch to mobile and pick Simulator, then tap iOS or Android. The latest available device for that platform boots on the Mac host and streams to the browser over WebRTC — tap, type, swipe, rotate, hardware buttons. One latest simulator per platform (no device catalog to wade through); it's a real simulator, not a screenshot loop, so you see your app exactly as it runs. Vibe Chat can boot it for you too — just ask ("open the iOS simulator").

Building an app

Switch to the Build tab, pick a platform (iOS / Android) and a profile, and hit Build. The Mac host clones your repo at the current commit, installs dependencies, runs expo prebuild, compiles with Xcode / Gradle, signs, and exports the artifact. You watch every step and the live log; the build is tracked server-side, so it survives a refresh and you can come back to it. When it finishes, download the .ipa / .apk / .aab straight from the panel. Builds run one-at-a-time per host; the history list keeps your recent builds. Vibe Chat can kick off a build for you too — ask "build the Android app for production" and it starts the same job.

Signing & credentials

Open Signing from the Build panel to manage credentials. They're stored encrypted on Loor — never in loor.json, never in your repo — and decrypted only on the Mac host at build time, into a throwaway keychain that's wiped when the build ends.

  • iOS (recommended): an App Store Connect API key (the .p8 plus Key ID + Issuer ID) and your Apple Team ID. Loor manages provisioning profiles and signs with it — the same mechanism EAS uses, no interactive Apple ID / 2FA. A distribution .p12 + provisioning profile works as a fallback.
  • Android: upload your release keystore (.jks) with its alias and passwords. Loor signs release builds with it.
  • Stores (optional): the same ASC API key uploads to TestFlight; a Google Play service-account JSON uploads to Play.

Studio only ever shows you which credentials are set — never the values back. Development / simulator builds need no signing at all.

Artifacts & stores

Each finished build produces a downloadable artifact, retained on the host. Production iOS builds can upload to App Store Connect (TestFlight) with your API key; production Android builds produce a Play-ready .aab and, with a service account, upload to an internal track. Install a preview .apk straight onto a device, or drag a simulator .app into a running simulator.

Requirements

Mobile builds + simulator run on a Mac host assigned to your project by an admin (a provisioned Apple-Silicon Mac with Xcode, the Android SDK, and the Loor runtime). If you see "No simulator host assigned", ask an admin to attach one. A connected GitHub repo is required — builds clone from the current commit. Everything else — Metro, prebuild, signing, store upload — Loor handles for you.