A complete Uber-like ride-sharing mobile application for iOS and Android, built with React Native, Expo, and TypeScript.
- Request rides with pickup and dropoff locations
- Select vehicle type (Economy, Comfort, Premium)
- Real-time ride tracking with driver location
- View ride history
- Profile management
- Bilingual support (English + Arabic)
- Accept ride requests
- Real-time location tracking
- Manage active rides with status updates
- View earnings and payment history
- Vehicle management
- Profile management
- Bilingual support (English + Arabic)
- Framework: React Native + Expo
- Language: TypeScript
- Navigation: React Navigation
- API Client: tRPC + React Query
- Real-time: Socket.IO
- Internationalization: react-i18next
- Maps: Expo Location + React Native Maps
- Notifications: Expo Notifications
- Node.js 18+ and npm/pnpm
- Expo CLI:
npm install -g expo-cli - iOS Simulator (macOS only) or Android Emulator
- Expo Go app on your physical device (optional)
cd uber-clone-mobile
npm install
# or
pnpm installCreate a .env file in the project root:
EXPO_PUBLIC_API_URL=http://YOUR_LOCAL_IP:3000/api/trpcImportant: Replace YOUR_LOCAL_IP with your computer's local IP address (not localhost). To find your IP:
- macOS:
ifconfig | grep "inet " | grep -v 127.0.0.1 - Windows:
ipconfig(look for IPv4 Address) - Linux:
ip addr show
Example: EXPO_PUBLIC_API_URL=http://192.168.1.100:3000/api/trpc
Make sure your backend server is running:
cd ../uber-clone
pnpm devThe backend should be accessible at http://YOUR_LOCAL_IP:3000
npm start
# or
expo startThis will open the Expo Dev Tools in your browser.
Option A: Physical Device (Recommended for Testing)
- Install Expo Go app from App Store (iOS) or Google Play (Android)
- Scan the QR code from Expo Dev Tools
- The app will load on your device
Option B: iOS Simulator (macOS only)
npm run iosOption C: Android Emulator
npm run androiduber-clone-mobile/
├── App.tsx # Main app entry point
├── app.json # Expo configuration
├── package.json # Dependencies
├── tsconfig.json # TypeScript config
├── babel.config.js # Babel config
└── src/
├── api/
│ └── trpc.ts # tRPC client setup
├── contexts/
│ └── SocketContext.tsx # Socket.IO context
├── hooks/
│ └── useAuth.ts # Authentication hook
├── i18n/
│ ├── index.ts # i18n configuration
│ └── locales/
│ ├── en.json # English translations
│ └── ar.json # Arabic translations
├── navigation/
│ ├── RootNavigator.tsx # Main navigation
│ ├── RiderTabNavigator.tsx # Rider tabs
│ └── DriverTabNavigator.tsx # Driver tabs
└── screens/
├── Auth/
│ ├── LoginScreen.tsx
│ └── RoleSelectionScreen.tsx
├── Rider/
│ ├── RiderDashboardScreen.tsx
│ ├── RiderActiveRideScreen.tsx
│ ├── RiderHistoryScreen.tsx
│ └── RiderProfileScreen.tsx
└── Driver/
├── DriverDashboardScreen.tsx
├── DriverActiveRideScreen.tsx
├── DriverEarningsScreen.tsx
├── DriverVehiclesScreen.tsx
└── DriverProfileScreen.tsx
- User opens app → LoginScreen
- Taps "Login" → Opens OAuth in browser (WebBrowser)
- After successful login, returns to app
- If no role selected → RoleSelectionScreen
- User selects Rider or Driver
- Navigates to appropriate dashboard
Note: OAuth flow requires the backend to handle the callback and set cookies properly.
- Drivers automatically broadcast location every 5 seconds during active rides
- Riders see driver's moving marker on the map
- Uses Expo Location API with high accuracy
- Real-time notifications via Socket.IO
- Status changes instantly update UI
- Supports: pending → accepted → driver_arriving → arrived → in_progress → completed
The app supports English and Arabic:
import { useTranslation } from 'react-i18next';
const { t, i18n } = useTranslation();
// Use translations
<Text>{t('rider.requestRide')}</Text>
// Change language
i18n.changeLanguage('ar');All translations are in src/i18n/locales/.
The app requires these permissions:
iOS (Info.plist):
NSLocationWhenInUseUsageDescription- For ride trackingNSLocationAlwaysUsageDescription- For driver location updatesNSCameraUsageDescription- For profile/vehicle photos
Android (AndroidManifest.xml):
ACCESS_FINE_LOCATION- For GPS locationACCESS_COARSE_LOCATION- For network locationCAMERA- For photos
These are automatically configured in app.json.
expo build:iosOr use EAS Build:
npm install -g eas-cli
eas build --platform iosexpo build:androidOr use EAS Build:
eas build --platform android- Ensure backend is running and accessible
- Check API URL in
.envuses your local IP (not localhost) - Disable firewall temporarily to test
- Ensure phone and computer are on the same WiFi network
- Go to phone Settings → App → Permissions
- Enable Location permission
- Restart the app
- Clear cache:
expo start -c - Reinstall dependencies:
rm -rf node_modules && npm install
- Ensure Xcode is installed
- Run:
sudo xcode-select --switch /Applications/Xcode.app
- Hot Reload: Changes auto-reload in development
- Debug Menu: Shake device or press
Cmd+D(iOS) /Cmd+M(Android) - Console Logs: View in terminal where
expo startis running - Network Debugging: Use React Native Debugger or Flipper
The app includes native camera functionality for profile and vehicle photos:
import { ImagePickerButton } from '../components/ImagePickerButton';
<ImagePickerButton
onImageSelected={(url) => console.log('Image uploaded:', url)}
label="Profile Photo"
aspectRatio={[1, 1]}
/>Native maps with turn-by-turn directions:
import { NativeMapView } from '../components/NativeMapView';
<NativeMapView
pickupLocation={{ latitude: 37.78, longitude: -122.43 }}
dropoffLocation={{ latitude: 37.79, longitude: -122.44 }}
driverLocation={{ latitude: 37.785, longitude: -122.435 }}
showRoute={true}
/>Expo Notifications for real-time ride updates:
import { useNotifications } from '../contexts/NotificationContext';
const { expoPushToken } = useNotifications();- ✅ Google Maps integration with directions
- ✅ Camera functionality for photos
- ✅ Push notifications for ride updates
- Implement payment integration (Stripe)
- Add ride rating system
- Implement in-app messaging between rider/driver
- Backend API:
../uber-clone(tRPC server) - Admin Panel:
../uber-clone(Web app)
MIT