Skip to content

Mobile builds

Expo Go is enough to work on screens: bun run dev:mobile. You need a build of your own for push notifications, for testers and for the stores. Builds are made by EAS, Expo’s build service, from the profiles in apps/mobile/eas.json.

Without an account: a build on your machine

Section titled “Without an account: a build on your machine”

On a Mac with Xcode, this builds the app for the iOS simulator. It needs no Expo or Apple account, and it is the quickest way to see that your native changes build:

Terminal window
cd apps/mobile
bunx expo run:ios

It writes the native project to apps/mobile/ios, which is not committed. Afterwards bun run dev:mobile:build starts the dev server for that build instead of Expo Go.

You need an Expo account, and for the stores an Apple Developer and a Google Play account.

  1. In apps/mobile/app.json, set name, slug, scheme, ios.bundleIdentifier and android.package to your own. Set MOBILE_SCHEME to the same scheme, in .env and in .env.railway.

  2. In apps/mobile/eas.json, replace https://app.example.com with your web app’s address. The app calls the API there, under /api.

  3. Sign in and make the project:

    Terminal window
    cd apps/mobile
    bun run eas login
    bun run eas init

    init writes your project’s id to app.json. Push notifications need it. Commit it.

Profile For Command
development-simulator The iOS simulator, with reload bun run mobile:build --profile development-simulator
development Your own phone, with reload and push, against your machine bun run mobile:build --profile development
preview Testers, against production, without the stores bun run mobile:build --profile preview
production The App Store and Google Play bun run mobile:build --profile production

Add --platform ios or --platform android to build one. The first build of each platform asks for your Apple or Google credentials and offers to set up push: say yes, and EAS keeps them for every build after.

A development build replaces Expo Go. Install it, run bun run dev:mobile:build, and open it. On a phone, set EXPO_PUBLIC_API_URL in the development profile to your machine’s address on your network, such as http://192.168.1.20:3000.

EXPO_PUBLIC_API_URL is fixed when the app is built, as a variable of the web app is. Change it in eas.json, then build again.

A preview or production build sends its source maps to Sentry when SENTRY_AUTH_TOKEN, SENTRY_ORG and SENTRY_PROJECT are EAS environment variables, and builds without them too: see Error reporting.

Terminal window
bun run mobile:submit --profile production

The build number goes up by itself with each production build.

.github/workflows/mobile.yml starts a build without your machine. It runs only when you start it, because a build uses your EAS build minutes: Actions > Mobile release > Run workflow, then choose the profile, the platform, and whether a production build goes to the stores when it is done.

  1. Make the first build of each platform from your machine, so EAS has your credentials.
  2. Create an access token at https://expo.dev/settings/access-tokens and add it to the repository as the secret EXPO_TOKEN.

The workflow type-checks and tests the app, starts the build, and finishes. Follow the build at expo.dev.

The mobile app is also part of CI: bun run build bundles it for iOS and Android, so a pull request that breaks the app’s code fails before anyone builds it.

The API needs nothing. If you turn on enhanced security for push in your Expo account, set EXPO_ACCESS_TOKEN in .env.railway.

Check it on a phone with a development or preview build: sign in, open the Account tab, turn on notifications and send a test. A simulator cannot receive them.