KrikoriosandClaude f50ff27e11 Build driver app, Uber-style dispatch, POI suggestions; fix map tiles
Driver side (was a stub):
- In-app driver onboarding: a driver-role user creates their own linked
  drivers profile (driver/profile+api GET/POST/PATCH).
- Driver dashboard: online/offline toggle, today's earnings, incoming
  request cards (accept/decline), active ride panel (start/complete trip).
  Polls /driver/rides every 4s while online.
- Location heartbeat (use-driver-location): watchPositionAsync pings
  /driver/location every ~5s; restarts the watch on app foreground so a
  backgrounded driver doesn't go permanently stale and miss requests.

Dispatch (auto-match nearest, Uber-style):
- Ride state machine: requested -> accepted -> en_route -> completed/cancelled
  with a nullable driver_id until matched (lib/dispatch.matchNextDriver).
- matchNextDriver locks the ride (SELECT FOR UPDATE), expires 15s-stale
  offers, picks the nearest eligible driver of the matching service by
  haversine, offers one at a time. Called from ride/create, ride/[id] GET
  (lazy match on the rider's poll), and ride/[id]/respond (on decline).
- ride/create is now a request endpoint (driver_id NULL, status=requested,
  service); drops the pre-match driver_id payment reconciliation.
- ride/[id] GET returns status/service/nullable driver; PATCH handles rider
  cancel + driver en_route/completed. ride/list backs the history tabs.

Rider flow (best experience):
- confirm-ride is now a request screen: single trip fare + nearest-driver
  ETA + cash/card + Request Ride -> live status. Periodically polls online
  drivers of the selected service and disables Request when none are
  online (prevents the "stuck searching forever" state).
- book-ride is the live ride-status screen (searching -> accepted ->
  en_route -> completed/cancelled + Cancel), polling every 3s.
- lib/request-ride unifies the Areeba card flow + cash path.
- Map reads /driver/nearby (real positions, service-filtered); lib/map
  adds calculateTripFare + service-aware fares.

POI suggestions:
- lib/places (Google Nearby Search) + nearby-suggestions chips for
  mall/hospital/pharmacy/restaurant on the home screen.

Service categories now drive both matching and a per-service fare
multiplier (car 1.0 / moto 0.7 / courier 0.85 / chauffeur 1.5).

Map tiles: react-native-maps rendered blank on Android because no Google
Maps key was set. Switched app.json -> app.config.js so
android.config.googleMaps.apiKey is injected from
EXPO_PUBLIC_GOOGLE_API_KEY at build time (keeps the key out of git).
Requires a native rebuild (expo run:android) to take effect.

Also includes the prior payment/auth hardening (server-authoritative
payment_orders ledger with double-spend guards, peppered OTP, register
TOCTOU fix, stats cents fix) that was left uncommitted.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-24 13:57:21 +03:00
2026-02-23 10:52:38 +05:30
2024-08-29 07:12:44 +00:00
2024-08-29 07:12:44 +00:00
2024-08-29 07:07:01 +00:00
2024-09-04 11:19:33 +00:00
2024-09-06 04:09:10 +00:00
2024-08-29 11:47:02 +05:30
2024-08-29 07:07:01 +00:00

Ryde - A Full Stack Uber clone using React Native and Expo

Ryde - A Full Stack Uber clone using React Native and Expo

Ask Me Anything! GitHub license Maintenance GitHub branches Github commits GitHub issues GitHub pull requests

📔 Table of Contents

‼️ Folder Structure

Here is the folder structure of Ryde.

uber-clone/
  |- .eas/
    |-- workflows/
  |- app/
    |-- (api)/
    |-- (auth)/
    |-- (root)/
    |-- _layout.tsx
    |-- +html.tsx
    |-- index.tsx
  |- assets/
  |- components/
    |-- custom-button.tsx
    |-- driver-card.tsx
    |-- google-text-input.tsx
    |-- input-field.tsx
    |-- map.tsx
    |-- oauth.tsx
    |-- payment.tsx
    |-- ride-card.tsx
    |-- ride-layout.tsx
  |- config/
    |-- index.ts
  |- constants/
    |-- index.ts
  |- lib/
    |-- auth.ts
    |-- fetch.ts
    |-- map.ts
    |-- utils.ts
  |- scripts/
    |-- reset-project.js
  |- store/
    |-- index.ts
  |- types/
    |-- image.d.ts
    |-- type.d.ts
  |- .env.example
  |- .env/.env.local
  |- .eslintrc.js
  |- .gitignore
  |- app.json
  |- babel.config.js
  |- bun.lockb
  |- eas.json
  |- environment.d.ts
  |- nativewind-env.d.ts
  |- package.json
  |- tailwind.config.js
  |- tsconfig.json

🧰 Getting Started

  1. Make sure Git and NodeJS is installed.
  2. Clone this repository to your local computer.
  3. Create .env file in root folder.
  4. Contents of .env:
# .env

# clerk publishable key
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_YOUR_KEY_HERE

# postgres db url (neon db)
DATABASE_URL="postgresql://username:password@hostname:port/uber-clone?sslmode=require"

# expo api server url (you can set it to any random url for development)
EXPO_PUBLIC_SERVER_URL="https://example.com/"

# geoapify api key
EXPO_PUBLIC_GEOAPIFY_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX

# google api key
EXPO_PUBLIC_GOOGLE_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

# areeba payment gateway (credentials issued after merchant onboarding)
AREEBA_API_BASE_URL="https://your-gateway-host.areeba.com"
AREEBA_MERCHANT_ID=your_merchant_id
AREEBA_API_PASSWORD=your_api_password
AREEBA_API_VERSION=100
  1. Open terminal in root directory. Run npm install --legacy-peer-deps or yarn install --legacy-peer-deps.

  2. Install Expo Cli using npm i -g expo-cli or yarn global add expo-cli to run your Expo app.

7. Clerk Publishable Key

  • Go to the Clerk Dashboard.
  • Sign in or sign up if you dont have an account.
  • Create a new application (or select your existing project).
  • Navigate to the "API Keys" section.
  • Copy the Publishable Key that starts with pk_test_.
  • Add it to your .env file:
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_YOUR_KEY_HERE

8. PostgreSQL Database URL (Neon Database)

  • Go to the Neon Dashboard.
  • Sign in or create an account.
  • Create a new project.
  • Once the project is created, go to the "Connection Details" section.
  • Copy the connection string and replace the placeholder values with your actual database credentials.
  • The URL will look something like this:
DATABASE_URL="postgresql://username:password@hostname:port/uber-clone?sslmode=require"

Replace username, password, hostname, and port accordingly.


9. Expo API Server URL

  • This can be any URL during development.
  • Set it to a random URL for local testing:
EXPO_PUBLIC_SERVER_URL="https://example.com/"

10. Geoapify API Key

  • Go to the Geoapify Dashboard.
  • Sign up or log in to your account.
  • Navigate to the "API Keys" section under your profile.
  • Generate a new API key.
  • Copy the key and add it to your .env file:
EXPO_PUBLIC_GEOAPIFY_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX

11. Google API Key

  • Go to the Google Cloud Console.
  • Create a new project (or use an existing one).
  • Navigate to the "APIs & Services" section and enable all of the required APIs:
    • Maps SDK for Android — draws the map itself. Without it Android renders an empty grey tile area and logcat shows an authorization failure; the app looks like the map "didn't load."
    • Maps SDK for iOS — only needed if components/map.tsx is switched from PROVIDER_DEFAULT (Apple Maps) to PROVIDER_GOOGLE.
    • Places API (New) — destination search in components/google-text-input.tsx. The legacy Places web service is unavailable to newer Google Cloud projects.
    • Directions API — route polyline and driver ETAs.
  • Go to the "Credentials" tab and click on "Create Credentials."
  • Select "API Key."
  • Copy the generated API Key and add it to your .env file:
EXPO_PUBLIC_GOOGLE_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

12. Areeba Payment Gateway

  • Contact Areeba to open a merchant account (Lebanon).
  • After onboarding, Areeba provides your gateway host, merchant ID, API password, and integration docs.
  • Add them to your .env file:
AREEBA_API_BASE_URL="https://your-gateway-host.areeba.com"
AREEBA_MERCHANT_ID=your_merchant_id
AREEBA_API_PASSWORD=your_api_password
AREEBA_API_VERSION=100
  1. Now app is fully configured 👍 and you can start using this app using expo start.

NOTE: Please make sure to keep your API keys and configuration values secure and do not expose them publicly.

📷 Screenshots:

Functional Login component Functional Register component

Modern UI/UX Choose a driver

Payment Integration with Stripe Easily Book your ride

⚙️ Tech Stack

React JS Typescript CSS Tailwind CSS Babel

🙌 Contribute

You might encounter some bugs while using this app. You are more than welcome to contribute. Just submit changes via pull request and I will review them before merging. Make sure you follow community guidelines.

💎 Acknowledgements

Useful resources and libraries that are used in Ryde:

Buy Me a Coffee

🚀 Follow Me

Follow Me Tweet about this project

📚 Learn more

To learn more about developing your project with Expo, look at the following resources:

Give A Star

You can also give this repository a star to show more people and they can use this repository.

🌟 Star History

Star History Chart

(back to top)

S
Description
No description provided
Readme MIT
7.3 MiB
Languages
TypeScript 90.9%
JavaScript 6.5%
CSS 2.4%
HTML 0.2%