
Expo Best Practices
- 127 installs
- 1 repo stars
- Updated February 20, 2026
- ofershap/expo-best-practices
Helps with ai & agent building tasks.
About
expo-best-practices is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- expo-best-practices
- AI & Agent Building
- AI-coding skill
Expo Best Practices by the numbers
- 127 all-time installs (skills.sh)
- +4 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #3,734 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/ofershap/expo-best-practices --skill expo-best-practicesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 127 |
|---|---|
| repo stars | ★ 1 |
| Last updated | February 20, 2026 |
| Repository | ofershap/expo-best-practices ↗ |
What it does
Helps with ai & agent building tasks.
Files
When to use
Use this skill when working with Expo or React Native code. It teaches current best practices and prevents common mistakes that AI agents make with outdated patterns, manual native setup, and deprecated APIs.
Critical Rules
1. Use Expo Router for navigation
Wrong (agents do this):
import { createStackNavigator } from "@react-navigation/stack";
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}Correct:
app/
_layout.tsx
index.tsx
settings.tsxUse the app/ directory convention. Files become routes automatically. New Expo projects include Expo Router by default.
Why: Expo Router is built on React Navigation, provides file-based routing, typed routes, deep linking, and integrates with Expo CLI. Manual React Navigation setup is redundant and misses Expo Router features.
2. Use expo-router layouts for navigation structure
Wrong:
// Each screen manually defines its own layoutCorrect:
// app/_layout.tsx
import { Stack } from "expo-router";
export default function RootLayout() {
return <Stack />;
}Why: _layout.tsx defines shared navigation structure, tabs, stacks, and nested layouts. It centralizes navigation configuration.
3. Use EAS Build for native builds
Wrong:
expo build:ios
expo build:androidCorrect:
eas build --platform ios
eas build --platform androidWhy: expo build is deprecated. EAS Build is the current cloud build service with better caching, credentials management, and native module support.
4. Use Expo config plugins for native configuration
Wrong:
# Manually editing
ios/MyApp/Info.plist
android/app/src/main/AndroidManifest.xmlCorrect:
// app.config.ts
import { ConfigPlugin } from "expo/config-plugins";
const withMyApiKey: ConfigPlugin<{ apiKey: string }> = (config, { apiKey }) => {
config = withInfoPlist(config, (c) => {
c.modResults["MY_API_KEY"] = apiKey;
return c;
});
return config;
};
export default {
plugins: [["withMyApiKey", { apiKey: process.env.API_KEY }]],
};Why: Direct edits to native files are overwritten on prebuild. Config plugins modify native files at build time and survive prebuild.
5. Platform-specific code: use platform extensions or Platform.select
Wrong:
if (Platform.OS === "ios") {
return <IOSComponent />;
}
return <AndroidComponent />;Correct:
MyComponent.ios.tsx
MyComponent.android.tsxOr:
import { Platform } from "react-native";
const styles = StyleSheet.create({
container: Platform.select({
ios: { paddingTop: 20 },
android: { paddingTop: 0 },
}),
});Why: Platform file extensions let the bundler include only the correct code per platform. Platform.select keeps conditional logic in one file when appropriate.
6. Use expo-image instead of React Native Image
Wrong:
import { Image } from "react-native";
<Image source={{ uri: url }} style={styles.image} />;Correct:
import { Image } from "expo-image";
<Image source={url} contentFit="cover" style={styles.image} />;Why: expo-image adds caching, placeholders, blurhash, and better performance. React Native's Image lacks these features.
7. Use expo-font for custom fonts
Wrong:
# Manual font linking via native projectsCorrect:
import * as Font from "expo-font";
await Font.loadAsync({
CustomFont: require("./assets/fonts/CustomFont.ttf"),
});Why: expo-font handles loading and avoids manual native configuration.
8. Use expo-secure-store for sensitive data
Wrong:
import AsyncStorage from "@react-native-async-storage/async-storage";
await AsyncStorage.setItem("authToken", token);Correct:
import * as SecureStore from "expo-secure-store";
await SecureStore.setItemAsync("authToken", token);Why: AsyncStorage is not encrypted. expo-secure-store uses the platform keychain/Keystore for tokens and secrets.
9. Use expo-notifications for push notifications
Wrong:
// Manual Firebase/APNs setup, native configurationCorrect:
import * as Notifications from "expo-notifications";
const token = await Notifications.getExpoPushTokenAsync();Why: expo-notifications abstracts push setup across iOS and Android. Manual Firebase/APNs configuration is error-prone and platform-specific.
10. Use app.json or app.config.ts for configuration
Wrong:
# Editing Info.plist or AndroidManifest.xml directlyCorrect:
{
"expo": {
"name": "MyApp",
"slug": "my-app",
"plugins": ["expo-router"]
}
}Why: Expo manages native config from app.json/app.config.ts. Direct edits are overwritten on prebuild.
11. Use expo-updates for OTA updates
Wrong:
import codePush from "react-native-code-push";
export default codePush(MyApp);Correct:
import * as Updates from "expo-updates";
await Updates.checkForUpdateAsync();Why: expo-updates integrates with EAS and Expo's update service. CodePush requires separate setup and is redundant in Expo projects.
12. Use TypeScript with typed navigation params
Wrong:
router.push("/profile");Correct:
import { router } from "expo-router";
router.push({ pathname: "/profile/[id]", params: { id: userId } });Define route params in your route files. Expo Router provides typed route helpers when used with TypeScript.
Why: Typed params prevent runtime errors and improve editor support.
Patterns
- Create routes under
app/with file names that map to URLs - Use
_layout.tsxfor shared layout, tabs, and stacks - Put platform-specific components in
Component.ios.tsxandComponent.android.tsx - Use
expo config pluginsinapp.json/app.config.tsfor any native config change - Use
eas.jsonfor EAS Build profiles
Anti-Patterns
- Do not set up React Navigation manually in Expo projects
- Do not use
expo build(use EAS Build) - Do not edit
ios/orandroid/directly in managed workflow - Do not use AsyncStorage for auth tokens or secrets
- Do not use React Native's Image when expo-image is available
- Do not use CodePush in Expo projects (use expo-updates)