Expo SDK
Build cross-platform mobile apps with Expo SDK and React Native.
Quick Start
// app/index.tsx — Expo Router file-based routing
import { router } from 'expo-router';
import { View, Text, FlatList, TouchableOpacity } from 'react-native';
import { useSQLiteContext } from 'expo-sqlite';
export default function HomeScreen() {
const db = useSQLiteContext();
const [items, setItems] = useState<Todo[]>([]);
useEffect(() => {
db.getAllAsync('SELECT * FROM todos ORDER BY created_at DESC')
.then(setItems);
}, []);
return (
<View className="flex-1 p-4">
<FlatList
data={items}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => (
<TouchableOpacity
=> router.push(`/todo/${item.id}`)}
className="p-3 bg-white rounded-lg mb-2 shadow"
>
<Text className={`text-lg ${item.completed ? 'line-through text-gray-400' : ''}`}>
{item.title}
</Text>
</TouchableOpacity>
)}
/>
<TouchableOpacity
=> router.push('/todo/new')}
className="bg-blue-500 p-4 rounded-full absolute bottom-8 right-8 shadow-lg"
>
<Text className="text-white text-2xl text-center">+</Text>
</TouchableOpacity>
</View>
);
}
# Create and develop
npx create-expo-app my-app --template blank-typescript
cd my-app
npx expo start
# Native builds
npx expo run:ios # iOS simulator
npx expo run:android # Android emulator
# Production builds
eas build --platform all
eas submit --platform ios
eas submit --platform android
# OTA updates
npx expo update
Key Concepts
Expo provides a managed workflow with built-in APIs (camera, location, SQLite, notifications, auth). Expo Router provides file-based navigation. EAS Build handles native compilation. OTA updates skip app store review.
When to Use
- Cross-platform iOS + Android apps from one codebase
- Apps needing native features (camera, GPS, biometrics)
- MVPs requiring fast iteration with OTA updates
- Teams wanting to avoid native build tooling setup
Step-by-Step
- Scaffold:
npx create-expo-app my-app --template blank-typescript, thencd my-app && npx expo start. - Add routing: install
expo-routerand use file-based routes underapp/(or run with the default router template). - Configure native APIs: run
npx expo install expo-camera expo-location expo-sqliteand add the plugin config inapp.json. - Develop on device: open in Expo Go or run
npx expo run:ios/run:androidfor a native dev build. - Store data locally: use
expo-sqlite(SQL viadb.getAllAsync) or AsyncStorage for key-value state. - Ship:
eas build --platform all, theneas submit; iterate withnpx expo update(OTA).
Examples
// app/todo/[id].tsx — dynamic route with local SQLite
import { useLocalSearchParams } from 'expo-router';
import { useSQLiteContext } from 'expo-sqlite';
import { View, Text } from 'react-native';
export default function TodoDetail() {
const { id } = useLocalSearchParams<{ id: string }>();
const db = useSQLiteContext();
const todo = db.getFirstSync('SELECT * FROM todos WHERE id = ?', [id]);
return (
<View className="p-4">
<Text className="text-xl">{todo?.title}</Text>
<Text>{todo?.completed ? 'Done' : 'Pending'}</Text>
</View>
);
}
# Native build & OTA
npx expo prebuild
eas build --platform android --profile preview
npx expo update
Validation
npx expo startlaunches Metro bundler successfully- App renders on both iOS simulator and Android emulator
- Native features (camera, SQLite) work on both platforms
eas buildproduces installable binaries