This React Native Expo project follows specific patterns and uses built-in features for consistency and reusability.
Technology Stack:
- React Native with Expo SDK 54
- TypeScript (strict mode)
- Expo Router v6 (flat config)
- Redux Toolkit for state management
- ESLint 9 with flat config
- React 19.1 and React Native 0.81.4
utils/config.ts- For all environment variables and app configurationutils/deviceInfo.ts- For platform detection, screen dimensions, and device info- Never hardcode values that should come from configuration
@/theme/colors- For all color values (supports dark/light mode)@/theme/fonts- For font loading and typography@/theme/images- For image assets and loading- Always use theme system instead of hardcoded styles
useColorSchemefrom@/hooks- For dark/light theme detectionuseDataPersistfrom@/hooks- For local storage operationsuseKeyboardfrom@/hooks- For keyboard state managementuseAppSlicefrom@/slices- For global state operations
- Redux Toolkit slices in
@/slices- For all global state - Use
useAppSlicefor accessing global state - Keep local state minimal, prefer global state for shared data
@/services- For all API calls and external integrations- Never make direct API calls from components
- Use the services layer for data transformation
@/types- For all TypeScript interfaces and types- Always define component prop interfaces
- Use strict TypeScript - project is configured for it
app/ # Expo Router routes (keep minimal, delegate to scenes)
components/
elements/ # Reusable UI components (Button, Image, etc.)
layouts/ # Layout-specific components (headers, navigation)
scenes/ # Screen components (main UI logic)
hooks/ # Custom React hooks
slices/ # Redux Toolkit slices
services/ # API and external services
theme/ # Colors, fonts, styling system
types/ # TypeScript type definitions
utils/ # Utility functions (config, deviceInfo)
- Define TypeScript interface for props
- Use function declarations (not arrow functions)
- Place hooks at the top
- Use early returns for conditional rendering
- Use
StyleSheet.createfor styles - Export default at bottom
- React and React Native
- Third-party libraries
- Internal imports with
@/paths - Relative imports
- Components: PascalCase (
Button.tsx) - Hooks: camelCase with "use" prefix (
useColorScheme.ts) - Utils: camelCase (
deviceInfo.ts) - Types: PascalCase (
User.ts)
- Check if similar component exists in
components/elements - Use existing built-in features instead of creating new ones
- Import theme colors instead of hardcoding
- Use TypeScript interfaces for all props
- Write tests for all new components
- Use Redux Toolkit for global state
- Use
useAppSlicefor state operations - Keep component state local only when not shared
- Use built-in hooks for common functionality
- Always import from
@/theme/colors - Use
StyleSheet.createfor performance - Use platform-specific styles when needed
- Support dark/light mode through theme system
- One test file per component
- Test behavior, not implementation
- Use descriptive test names
- Mock external dependencies
- Use flat config format (already configured)
- Keep route files minimal - delegate to scene components
- Use
<Redirect>for programmatic navigation - Handle deep linking through router
- No
console.login production code - Always handle loading and error states
- Write self-documenting code
- Keep functions focused and small
- Use TypeScript strictly
- Reuse First - Always check existing components and utilities before creating new ones
- Follow Patterns - Use established patterns in the codebase
- Use Built-ins - Leverage project's built-in features (theme, hooks, utils)
- Type Safety - Use TypeScript strictly for better code quality
- Test Everything - Write tests for all components
- Stay Consistent - Follow naming conventions and code structure
// From utils/deviceInfo.ts
import { isIos, isAndroid, windowWidth, windowHeight } from '@/utils/deviceInfo';// From utils/config.ts
import config from '@/utils/config';
// Access env and apiUrl// From @/theme
import { colors, loadFonts, loadImages } from '@/theme';// From @/hooks
import useColorScheme from '@/hooks/useColorScheme';
import { useDataPersist } from '@/hooks';- Project upgraded to Expo SDK 54
- Using React 19.1 with React Native 0.81.4
- ESLint 9 with flat config
- Directory "pages" was renamed to "scenes"
- TypeScript strict mode enabled (v5.9.2)
- Custom theme system with dark/light support
- SafeAreaView imported from react-native-safe-area-context (not React Native)
- Required peer dependencies: @expo/metro-runtime, react-native-worklets
npm run dev- Start Expo development server for all platforms with cache clearednpm run dev:ios- Start development server for iOS simulator onlynpm run dev:android- Start development server for Android emulator onlynpm run dev:web- Start development server for web browser onlynpm run dev:doctor- Run Expo diagnostics to check project health
npm run dev:build:mobile- Build iOS (IPA) and Android (APK) using EAS Build for developmentnpm run dev:build:web- Export static web application todist/directorynpm run dev:serve:web- Serve the built web app locally (run afterdev:build:web)npm run dev:deploy:web- Build and deploy web app to EAS Hosting
npm run dev:secret:push- Upload environment variables from.env.devto EAS secretsnpm run dev:secret:list- List all environment variables stored in EASnpm run dev:config:public- Display current Expo configuration for debugging
npm run lint- Run ESLint to check code quality and stylenpm run lint:staged- Run linting only on staged Git files (used in pre-commit)npm run format- Format code using Prettiernpm run test- Run Jest unit testsnpm run test:watch- Run Jest tests in watch mode for development
npm run prepare- Set up Husky Git hooks for pre-commit quality checks
- Check existing components in
components/elementsfor similar functionality - Use built-in utilities from
utils/,@/theme, and@/hooks - Follow the established patterns in the codebase
- Prefer extending existing components over creating new ones
- Always use the theme system for consistent UI