Skip to main content

Overview

Synto Mobile uses Expo and EAS (Expo Application Services) for building and deploying the app. The project supports development builds, preview builds, and production releases.

Prerequisites

Before building the app, ensure you have:
1

Node.js and package manager

  • Node.js 18 or later
  • pnpm 10.12.3 (specified in eas.json)
# Install pnpm globally
npm install -g [email protected]
2

Expo CLI

npm install -g expo-cli
3

EAS CLI (for cloud builds)

npm install -g eas-cli
4

Development tools

For local development:
  • Android: Android Studio with SDK
  • iOS: Xcode 14+ (macOS only)

Environment setup

Install dependencies

# Clone the repository
git clone <repository-url>
cd synto-mobile

# Install dependencies
pnpm install

Environment variables

Create a .env file in the project root:
.env
# Backend configuration
EXPO_PUBLIC_BACKEND_URL=https://your-backend-url.com
EXPO_PUBLIC_BACKEND_KEY=your-api-key

# Solana RPC (optional, defaults to public RPC)
NEXT_PUBLIC_SOLANA_RPC=https://api.devnet.solana.com
Never commit .env files to version control. Add .env to your .gitignore file.

Development

Running the development server

Start the Expo development server:
pnpm dev
# or
pnpm start
This starts the Metro bundler and opens the Expo DevTools.

Development workflow

1

Start development server

pnpm dev
2

Scan QR code

  • iOS: Use Camera app to scan QR code
  • Android: Use Expo Go app to scan QR code
3

Enable hot reload

Changes to code will automatically reload the app.
For full native functionality (like Mobile Wallet Adapter), you need to create a development build instead of using Expo Go.

Code quality

The project includes several npm scripts for maintaining code quality:

Linting

pnpm lint:check
The project uses eslint-config-expo for linting rules.

Formatting

pnpm fmt:check
Prettier formats these file types:
  • app/**/*.{js,jsx,ts,tsx}
  • constants/**/*.{js,jsx,ts,tsx}
  • hooks/**/*.{js,jsx,ts,tsx}
  • components/**/*.{js,jsx,ts,tsx}

Type checking

pnpm build
# This runs: tsc --noEmit && npm run android:build
TypeScript is configured with strict mode enabled:
tsconfig.json
{
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "strict": true,
    "paths": {
      "@/*": ["./*"]
    }
  }
}

CI pipeline

Run all checks before committing:
pnpm ci
This runs:
  1. Type checking (tsc --noEmit)
  2. Linting (lint:check)
  3. Format checking (fmt:check)
  4. Android prebuild

Building the app

Build profiles

The app uses three build profiles defined in eas.json:
eas.json
{
  "development": {
    "developmentClient": true,
    "distribution": "internal"
  }
}
Purpose: For testing with full native functionalityFeatures:
  • Includes development tools
  • Fast refresh enabled
  • Internal distribution (TestFlight/Internal Testing)

EAS Build (Cloud builds)

EAS Build is the recommended way to build Expo apps. It handles all the complexity of native builds in the cloud.
1

Login to Expo

eas login
2

Configure project

eas build:configure
This creates eas.json if it doesn’t exist.
3

Build for Android

# Development build
eas build --profile development --platform android

# Preview build
eas build --profile preview --platform android

# Production build
eas build --profile production --platform android
4

Build for iOS

# Development build
eas build --profile development --platform ios

# Preview build
eas build --profile preview --platform ios

# Production build
eas build --profile production --platform ios
iOS builds require an Apple Developer account ($99/year).

Local builds

You can also build locally if you have the required development tools installed.
# Prebuild (generates android directory)
pnpm android:build
# or
expo prebuild -p android

# Build APK
cd android
./gradlew assembleRelease

# Build AAB (for Play Store)
./gradlew bundleRelease
Output location:
  • APK: android/app/build/outputs/apk/release/app-release.apk
  • AAB: android/app/build/outputs/bundle/release/app-release.aab

Configuration files

app.json

Main Expo configuration:
app.json
{
  "expo": {
    "name": "synto-mobile",
    "slug": "synto-mobile",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/images/icon.png",
    "scheme": "templateexpobasic",
    "userInterfaceStyle": "automatic",
    "newArchEnabled": true,
    "android": {
      "package": "com.juiceee.syntomobile",
      "adaptiveIcon": {
        "foregroundImage": "./assets/images/adaptive-icon.png",
        "backgroundColor": "#ffffff"
      }
    },
    "plugins": [
      "expo-router",
      ["expo-splash-screen", { /* ... */ }],
      "expo-web-browser",
      "expo-font"
    ]
  }
}
  • newArchEnabled: true - Enables React Native’s new architecture (Fabric + TurboModules)
  • scheme - Deep linking scheme for the app
  • userInterfaceStyle: "automatic" - Supports both light and dark mode
  • experiments.typedRoutes: true - Type-safe routing with Expo Router
{
  "backgroundColor": "#FFFFFF",
  "dark": {
    "backgroundColor": "#000000",
    "image": "./assets/images/splash-icon.png"
  },
  "image": "./assets/images/splash-icon.png",
  "imageWidth": 200,
  "resizeMode": "contain"
}
Separate configurations for light and dark mode.

package.json scripts

Available npm scripts:
package.json
{
  "scripts": {
    "android": "expo run:android",
    "android:build": "expo prebuild -p android",
    "build": "tsc --noEmit && npm run android:build",
    "ci": "tsc --noEmit && npm run lint:check && npm run fmt:check && npm run android:build",
    "dev": "expo start",
    "fmt": "prettier --write 'app/**/*.{js,jsx,ts,tsx}' ...",
    "fmt:check": "prettier --check 'app/**/*.{js,jsx,ts,tsx}' ...",
    "ios": "expo run:ios",
    "lint": "expo lint --fix",
    "lint:check": "expo lint",
    "start": "expo start",
    "web": "expo start --web"
  }
}

Testing

Manual testing

1

Install development build

Build and install a development build on your device:
eas build --profile development --platform android
# or
eas build --profile development --platform ios
2

Connect to dev server

After installing, launch the app and shake your device to open the developer menu. Select “Connect to dev server” and enter your computer’s IP address.
3

Test features

  • Wallet connection
  • Transaction signing
  • Chat functionality
  • Token transfers
  • Network switching

Testing on different networks

The app supports multiple Solana networks:
constants/app-config.ts
export class AppConfig {
  static clusters: Cluster[] = [
    {
      id: "solana:devnet",
      name: "Devnet",
      endpoint: clusterApiUrl("devnet"),
      network: ClusterNetwork.Devnet,
    },
    {
      id: "solana:testnet",
      name: "Testnet",
      endpoint: clusterApiUrl("testnet"),
      network: ClusterNetwork.Testnet,
    },
  ];
}
Switch networks from the settings screen to test on different Solana clusters.

Deployment

Android deployment

1

Build production AAB

eas build --profile production --platform android
2

Download build artifact

After the build completes, download the .aab file from the Expo dashboard.
3

Upload to Google Play Console

  1. Go to Google Play Console
  2. Select your app or create a new app
  3. Navigate to “Release” > “Production”
  4. Upload the .aab file
  5. Fill in release details
  6. Submit for review

iOS deployment

1

Build production IPA

eas build --profile production --platform ios
2

Submit to App Store

eas submit --platform ios
Or manually upload via Xcode or App Store Connect.
3

Configure App Store listing

  1. Go to App Store Connect
  2. Fill in app metadata (description, screenshots, etc.)
  3. Submit for review

Auto-incrementing versions

The production profile has autoIncrement: true, which automatically bumps the build number on each build. To manually update the version:
app.json
{
  "expo": {
    "version": "1.0.1",  // User-facing version
    "ios": {
      "buildNumber": "2"  // Internal build number
    },
    "android": {
      "versionCode": 2    // Internal version code
    }
  }
}

Troubleshooting

Clear cache and restart:
# Clear Metro cache
expo start --clear

# Clear all caches
rm -rf node_modules
pnpm install
expo start --clear
Rebuild native directories:
# Remove native directories
rm -rf android ios

# Regenerate
expo prebuild --clean
Check the build logs in the Expo dashboard:
  1. Go to expo.dev
  2. Navigate to your project
  3. Click on the failed build
  4. Review the logs for errors
Common issues:
  • Missing credentials (iOS)
  • Invalid package name (Android)
  • Dependency conflicts
Mobile Wallet Adapter requires a development build or production build. It doesn’t work with Expo Go.
# Build a development build
eas build --profile development --platform android

Best practices

Use EAS Build

Cloud builds are more reliable and don’t require local setup

Test on real devices

Test wallet adapter and native features on physical devices

Version control

Commit eas.json and app.json to version control

Environment variables

Never commit .env files; use EAS Secrets for sensitive values

Performance optimization

1

Enable Hermes

Hermes is enabled by default in Expo. Verify in app.json:
{
  "expo": {
    "jsEngine": "hermes"
  }
}
2

Optimize images

Use optimized image formats and appropriate sizes:
import { Image } from 'expo-image';

<Image
  source={{ uri: 'https://...' }}
  contentFit="cover"
  transition={200}
/>
3

Bundle size analysis

Analyze your bundle size:
npx react-native-bundle-visualizer

Next steps

App architecture

Understand the app structure

Component structure

Learn about components

Custom hooks

Explore React hooks

Expo documentation

Official Expo docs

Build docs developers (and LLMs) love