Expo/React Native patterns for MathMind and Arena mobile — navigation, NativeWind, performance, offline-first, push notifications, App Store deployment, security.
// ❌ AsyncStorage is UNENCRYPTED — visible to anyone with device access
import AsyncStorage from '@react-native-async-storage/async-storage'
await AsyncStorage.setItem('auth_token', token) // INSECURE
// ✅ expo-secure-store uses iOS Keychain / Android Keystore
import * as SecureStore from 'expo-secure-store'
await SecureStore.setItemAsync('auth_token', token) // ENCRYPTED
What Goes Where
Data
Storage
Why
Auth tokens
expo-secure-store
Encrypted, OS-protected
User preferences
AsyncStorage
Not sensitive
Cached API data
AsyncStorage
Not sensitive, needs fast access
Problem history (MathMind)
expo-sqlite
Structured, offline-queryable
Encryption keys
expo-secure-store
Maximum protection
Offline-First Pattern (MathMind)
// 1. Try network, fall back to cache
async function getProblems(grade: number) {
try {
const online = await NetInfo.fetch()
if (online.isConnected) {
const data = await fetchFromSupabase(grade)
await cacheLocally(grade, data) // update cache
return data
}
} catch {} // network failed
return getCachedProblems(grade) // offline fallback
}
// 2. Queue mutations for sync
async function submitAnswer(answer: Answer) {
await saveToLocalDb(answer) // always save locally first
const online = await NetInfo.fetch()
if (online.isConnected) {
await syncToSupabase(answer)
} else {
await addToSyncQueue(answer) // sync when back online
}
}
App Store Deployment
# Build for production
eas build --platform ios --profile production
# Submit to App Store
eas submit --platform ios
# OTA update (JS-only changes, no native module changes)
eas update --branch production --message "Fix scoring display"
MathMind-Specific Considerations
Kids Category: requires COPPA compliance, no third-party analytics, no behavioral ads
Age rating: educational content, no user-generated content = likely 4+
Login for reviewer: provide test credentials in App Store Connect