Skip to main content

Mobile App Deployment Guide

Deploy your FSS mobile application built with Expo and React Native to app stores.

Prerequisites

  • Node.js 18+
  • Expo CLI (npm install -g expo-cli)
  • Expo Developer account (free at expo.dev)
  • Apple Developer account (for iOS)
  • Google Play Developer account (for Android)

Build Configuration

Environment Variables

Create .env file for your mobile app:

# API Configuration
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
NEXT_PUBLIC_APP_URL=https://yourdomain.com

# Feature Flags
NEXT_PUBLIC_ENABLE_PUSH_NOTIFICATIONS=true
NEXT_PUBLIC_ENABLE_ANALYTICS=true

# Analytics (optional)
NEXT_PUBLIC_GA_TRACKING_ID=UA-XXXXXXXX-X
NEXT_PUBLIC_FIREBASE_API_KEY=your-api-key

app.json Configuration

Update app.json with your app details:

{
"expo": {
"name": "FSS App",
"slug": "fss-app",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "automatic",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.yourcompany.fssapp",
"buildNumber": "1",
"infoPlist": {
"NSCameraUsageDescription": "This app uses the camera for QR code scanning.",
"NSPhotoLibraryUsageDescription": "This app accesses your photos for profile images."
}
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#ffffff"
},
"package": "com.yourcompany.fssapp",
"versionCode": 1,
"permissions": ["CAMERA", "READ_EXTERNAL_STORAGE"]
},
"plugins": [
[
"expo-camera",
{
"cameraPermission": "Allow FSS to access your camera for QR code scanning."
}
]
]
}
}

Building for Production

Development Build

# Start development server
npx expo start

# Run on iOS simulator
npx expo run:ios

# Run on Android emulator
npx expo run:android

Production Build (Expo Application Services)

# Install EAS CLI
npm install -g eas-cli

# Login to Expo
eas login

# Configure build
eas build:configure

# Build for iOS
eas build --platform ios --profile production

# Build for Android
eas build --platform android --profile production

EAS Build Profile

Create eas.json:

{
"cli": {
"version": ">= 3.0.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"android": {
"buildType": "apk"
},
"ios": {
"simulator": true
}
},
"preview": {
"distribution": "internal",
"android": {
"buildType": "apk"
}
},
"production": {
"android": {
"buildType": "app-bundle"
},
"ios": {
"buildType": "release"
}
}
},
"submit": {
"production": {}
}
}

App Store Submission

iOS App Store

  1. Build the app (see above)
  2. Submit to App Store
eas submit --platform ios
  1. Required Information:

    • App name and description
    • Screenshots (various sizes)
    • Privacy policy URL
    • App Store category
    • Pricing (free or paid)
  2. After Submission:

    • Review typically takes 24-48 hours
    • Respond to any App Store Review guidelines issues

Google Play Store

  1. Build the app (see above)
  2. Submit to Play Store
eas submit --platform android
  1. Required Information:

    • App name and description
    • Screenshots and feature graphic
    • Privacy policy URL
    • Content rating questionnaire
    • Target audience
  2. After Submission:

    • Review typically takes 1-3 days
    • App goes to production after approval

Push Notifications

Setup FCM for Android

  1. Go to Firebase Console
  2. Create new project or select existing
  3. Add Android app with your package name
  4. Download google-services.json and place in project root
  5. Enable Cloud Messaging API in Google Cloud Console

Setup APNs for iOS

  1. Go to Apple Developer Console
  2. Create Push Notifications service for your app ID
  3. Create and download SSL certificate
  4. Convert certificate to PEM format:
# Export certificate from Keychain
openssl pkcs12 -in Certificates.p12 -out certificate.pem -nodes -clcerts
  1. Upload certificate to Expo:
eas credentials:manager

Push Notification Code

// notifications.ts
import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';

export async function registerForPushNotificationsAsync() {
if (!Device.isDevice) {
return null;
}

const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;

if (existingStatus !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}

if (finalStatus !== 'granted') {
console.log('Failed to get push token for push notification!');
return;
}

const token = await Notifications.getExpoPushTokenAsync({
projectId: 'your-project-id',
});

return token.data;
}

Over-the-Air Updates (OTA)

FSS supports Expo OTA updates for instant app updates:

# Publish update
expo publish

# Publish with specific channel
expo publish --channel production

Configure Channels

{
"expo": {
"updates": {
"url": "https://u.expo.dev/your-project-id",
"enabled": true
},
"runtimeVersion": {
"policy": "appVersion"
}
}
}

Security Considerations

Secure Storage

import * as SecureStore from 'expo-secure-store';

// Store sensitive data
await SecureStore.setItemAsync('authToken', token);

// Retrieve data
const token = await SecureStore.getItemAsync('authToken');

// Delete data
await SecureStore.deleteItemAsync('authToken');

Certificate Pinning

import { AuthSession } from 'expo-auth';

const config = {
issuer: 'https://your-domain.com',
clientId: 'your-client-id',
scopes: ['openid', 'profile', 'email'],
redirectUri: AuthSession.makeRedirectUri('your-app'),
usePKCE: true,
};

Monitoring and Analytics

Crash Reporting (Sentry)

npm install @sentry/react-native
import * as Sentry from '@sentry/react-native';

Sentry.init({
dsn: 'https://[email protected]/xxx',
tracesSampleRate: 1.0,
});

const App = () => {
return <Sentry.Hub wrapperComponent={MainApp} />;
};

Analytics

import { useAnalytics } from '@react-native-firebase/analytics';

const analytics = useAnalytics();

const logEvent = async () => {
await analytics.logEvent('purchase', {
item_id: 'product_123',
value: 99.99,
currency: 'USD',
});
};

Troubleshooting

Build Errors

# Clear cache and try again
expo start -c

# Reset iOS simulator
xcrun simctl erase all

# Reset Android emulator
adb emu kill && emulator -avd <avd_name>

App Crashes

  • Check Expo Dev Tools for logs
  • Enable Crashlytics for production crash reports
  • Test on physical devices, not just simulators