Customize your project context
npx github:Pranavoro/tailormd init mobile-expo# My App TailorMD recipe: **Mobile Expo** ## Stack - **Expo SDK:** SDK 52 - **Navigation:** Expo Router - **State management:** Zustand - **EAS channel:** production ## Folder map ``` app/ # Expo Router file-based routes (if Expo Router = Expo Router) (tabs)/ (auth)/ src/ components/ # reusable UI hooks/ stores/ # Zustand state services/ # API clients utils/ assets/ # images, fonts ``` ## Non-negotiables - Test on both iOS and Android simulators before ship - No secrets in client bundle — use env + EAS secrets - Handle offline and slow-network states gracefully - Respect platform conventions (safe areas, back gesture, haptics) - Native modules require explicit approval — prefer Expo-managed packages - OTA updates go to production channel only after QA pass ## Naming and style - Components: `PascalCase.tsx` - Hooks: `useCamelCase.ts` - Screens/routes: `kebab-case` (Expo Router) or `PascalCase` (React Navigation) - Store slices: descriptive nouns (`useAuthStore`) - Assets: `kebab-case.png` / `.webp` ## Commands ```bash npx expo start # dev server npx expo run:ios # native iOS build npx expo run:android # native Android build npm run test # jest / vitest npm run lint eas build --profile preview # test build eas update --channel production ``` ## Ship checklist Before merging or deploying: - [ ] Runs on iOS and Android simulators - [ ] No TypeScript errors - [ ] Lint and tests pass - [ ] No secrets in diff or client bundle - [ ] Loading, error, and empty states handled - [ ] Safe area and keyboard avoidance verified - [ ] App icon and splash screen correct - [ ] EAS build succeeds for target channel (production) ## Navigation (Expo Router) - **Expo Router:** file-based routes in `app/`; use layouts for shared chrome - **React Navigation:** typed param lists; no magic string route names ## State (Zustand) - Server state via fetch/query layer; UI state in Zustand - Avoid prop drilling — colocate state with the screen that owns it - Persist auth tokens securely (SecureStore, not AsyncStorage)