EVAPP.
A ride-sharing mobile app: passengers find trips, book seats and pay in credits held until the driver accepts.
- ROLE
- Full-Stack Developer: payments, profile and search
- TEAM
- Team of 4 engineers
- DATE
- Nov 2023 to Apr 2024
- TRACK
- Full-Stack
- STACK
- React Native, Expo, TypeScript, Node.js, Express, MongoDB, Vercel

FIG. 03B ARCHITECTURE
- React Native (Expo), frontend. Connects to Express on Vercel (REST · JWT), Google Maps · Cloudinary (HTTPS).
- Express on Vercel, backend. Connects to MongoDB Atlas (MONGOOSE). See note 1.
- Google Maps · Cloudinary, external. See note 2.
- MongoDB Atlas, storage. See note 3.
NOTES
Decision
Seats are paid in credits that go on hold when a passenger requests a seat, and only move to the driver when they accept it. If the driver rejects, the credits go back, so no one pays for a ride that isn't confirmed.
Trade-off
The app sends profile photos straight to Cloudinary with an unsigned preset and calls Google Places and Directions itself, so the API only stores URLs. That kept the backend small, but the keys live in the client and anyone can pull them out.
What I got wrong
I first sent profile images through the account-update endpoint, inside the password-change logic, so a request with only an image failed the password check and didn't work. I changed it so the app uploads to Cloudinary and the API only saves the returned URL, which made the endpoint simpler and kept file data off the server.
RESULTS
- PULL REQUESTS MERGED
- 59
- REST ENDPOINTS
- 16
- SCREENS BUILT
- 4
PROJECT 07 / 08