Copy this file into the root of your project as CLAUDE.md.
CLAUDE.md
Project
An Expo Router app targeting iOS and Android. TypeScript strict. EAS Build for native builds. EAS Update for OTA updates. State via Zustand for UI, TanStack Query for server data.
Commands
pnpm installpnpm start— Expo dev serverpnpm ios— open iOS simulatorpnpm android— open Android emulatorpnpm test— Jest withjest-expopnpm typecheckeas build --profile development --platform ios— make a dev client buildeas update --branch <name>— ship an OTA update
Code style
- TypeScript strict.
- Components use function declarations, not arrow expressions, for top-level exports.
- Always import from
react-nativeorexpo-*— never fromreact-native-webdirectly. - File-system routing via Expo Router. Routes live in
app/. File names match route names ((tabs),[id].tsx, etc.). - StyleSheet via
react-nativeStyleSheet.createornativewind(if installed). No inline style objects in hot paths.
Stack rules
Navigation
- Use
expo-routerexclusively. Don't import from@react-navigation/nativedirectly. - Stack, tab, and modal layouts go in
_layout.tsxfiles. - Use typed routes (
expo-router'stypedRoutesexperimental flag is on).
Native modules
- Prefer Expo SDK modules over community packages where one exists.
- If adding a native module not in Expo, it must be supported by Expo's prebuild / config plugins. No "bare" workflow ejection.
Data
- TanStack Query for all network state. Query keys centralized in
src/queries/keys.ts. - Persist auth tokens with
expo-secure-store. NeverAsyncStoragefor secrets.
Updates
- OTA updates ship JS/asset changes. Native changes require a new EAS Build.
- Use update channels matching environments:
production,staging,preview.
Before editing
- Identify whether the change needs a new native build (Info.plist, AndroidManifest, native deps) or can ship as OTA.
- Test on both iOS and Android — platform-specific issues are common.
- Check
app.json/app.config.tsbefore changing any config-plugin-touched setting.
Constraints
- Do not eject. Stay on Expo's managed workflow.
- Do not commit native folders (
ios/,android/) — they are generated. - Do not use
Dimensions.get('window')in render paths — useuseWindowDimensions()for orientation-safe values. - Avoid heavy animations on the JS thread. Use Reanimated worklets.