This guide covers local setup, project structure, build/release, and troubleshooting for the Stellar-Save React Native mobile app (planned for v4.0 on the roadmap). It uses Expo to keep iOS/Android builds reproducible without requiring native Xcode/Android Studio setup for day-to-day contribution.
This is distinct from mobile-app-guide.md, which is the end-user guide for the existing mobile-responsive PWA (the web app, not this native app).
- Node.js (same version as
/.env.example/ rootpackage.jsonengines) - Expo CLI:
npm install -g expo-cli(or usenpx expo) - Xcode (macOS only, for the iOS simulator) or Android Studio (for the Android emulator)
- The Expo Go app on a physical device, as an alternative to a simulator
cd mobile
npm install
npx expo startThis opens the Expo developer tools in your browser. From there:
- Press
ito launch the iOS simulator (macOS only) - Press
ato launch the Android emulator - Scan the QR code with the Expo Go app to run on a physical device
The mobile app talks to the same backend and Soroban contract as the web app. Copy the root
.env.example conventions into mobile/.env, prefixed for Expo:
EXPO_PUBLIC_STELLAR_NETWORK=testnet
EXPO_PUBLIC_STELLAR_RPC_URL=https://soroban-testnet.stellar.org
EXPO_PUBLIC_API_BASE_URL=http://localhost:3001/api/v2
EXPO_PUBLIC_CONTRACT_ID=Expo only exposes variables prefixed EXPO_PUBLIC_ to client code — never put secrets here.
See ENVIRONMENT.md for how this maps to the backend/contract config the
mobile app depends on.
mobile/
app/ # Screens, using Expo Router's file-based routing
(tabs)/ # Bottom tab navigator: Home, Groups, History, Settings
group/[id].tsx # Dynamic route for a single group's detail screen
components/ # Shared, presentational components
hooks/ # Shared hooks (wallet connection, contract reads, etc.)
lib/ # Non-UI logic: API client, Soroban RPC client, formatting
state/ # App-level state (see below)
assets/
- Navigation: Expo Router — routes are
derived from the
app/directory structure, mirroring the web app's URL structure where practical so deep links stay consistent across platforms. - State management: local component state (
useState) for screen-local concerns; shared state (wallet connection, active group) lives in lightweight context providers understate/, mirroring the pattern already used in frontend/src — do not introduce a new state library without discussing it first. - Styling: React Native
StyleSheet, not CSS — visual conventions should track the web app's design tokens where one-to-one screens exist (e.g. group cards, contribution flow).
The app is built with EAS Build for both platforms.
npx eas build --platform ios --profile preview # internal TestFlight build
npx eas build --platform android --profile preview # internal APK/AAB
npx eas build --platform all --profile production # store-ready buildsBuild profiles are defined in mobile/eas.json:
preview— internal distribution for QA, signed with the internal distribution certificate/keystore.production— store submission build, signed with the App Store / Play Store release credentials.
- iOS: managed via
eas credentials, which stores the distribution certificate and provisioning profile on Expo's servers. Do not commit.p12/.mobileprovisionfiles to the repo. - Android: the release keystore is managed the same way via
eas credentials; never commit the keystore or its password.
npx eas submit --platform ios
npx eas submit --platform androidRelease builds should only be submitted from main after the corresponding web/backend
release has been verified, since the mobile app shares the same contract/backend contracts.
npx expo start --clearrm -rf node_modules
npm install
npx expo start --clearConfirm Xcode's command-line tools are selected: xcode-select -p should point at
/Applications/Xcode.app/Contents/Developer. Reinstall with xcode-select --install if not.
Ensure hardware acceleration (HAXM/KVM) is enabled in Android Studio's AVD Manager — running without it makes the emulator unusably slow.
Native deep links require the URL scheme registered in app.json (expo.scheme) to match
the scheme the wallet app redirects back to. If this drifts, wallet sign-in will silently
fail to return control to the app — verify the scheme matches the wallet integration's
configured redirect.
Run npx eas credentials and confirm the correct Apple/Google account is selected — this is
the most common cause of build failures after switching machines or team accounts.
Follow the same workflow as the rest of the repo — see CONTRIBUTING.md for branch naming, commit conventions, and PR process. Mobile-specific PRs should be tested on both a simulator/emulator and, where the change touches wallet signing or deep links, a physical device before review.