pdelabs logo
    sun

    Vamos Juntos

    Carpooling for Uruguay — matching people by route, not by address.
    whale-tale
    RoleFull product build — mobile, API and infrastructure
    PlatformsiOS · Android
    Timeline2020 – 2022
    mobileapigeorealtimeserverless
    Vamos Juntos is a carpooling app that connects drivers and passengers for shared rides, making travel cheaper and greener. It handles the whole journey: matching people by route and schedule, agreeing on a ride, and in-app messaging with shared location while it is happening.

    We built it end to end — the mobile apps, the API, the data model and the AWS and Firebase infrastructure underneath.
    App preview
    App preview

    The problem

    Two people match on corridors, not on endpoints

    Carpooling is not ride-hailing. A passenger going part of the way is still a match, and a driver twenty minutes off a passenger's origin may still be one. Useful matching means reasoning about overlapping paths across a country, not comparing two pairs of coordinates.

    Strangers are about to get in a car together

    Every trust affordance has to exist before anyone will use it once, let alone twice: verified identity, reviews in both directions, a way to report what went wrong, and a shared location during the ride so someone else can see where you are.

    Rides get planned before they exist

    Most searches return nothing, because the matching ride has not been posted yet. A carpooling app that only answers the query in front of it feels empty on day one and stays empty.

    What we built

    1. 01

      Matching on geography, with searches that outlive the query

      Route matching runs as dedicated geo services rather than as database predicates, and a search that finds nothing today is saved — so the user is notified when a matching ride is posted later. It turns an empty result into a pending one.
      • Dedicated geo and geocoding services behind the API
      • Saved ride searches that fire a notification on a later match
      • Map-first interface on the client, not a form with two text inputs
    2. 02

      Identity verified once, at the edge

      Firebase issues the token, and an API Gateway JWT authorizer validates it before any function runs. No handler hand-rolls token parsing, which is exactly where auth bugs come from when there are thirty of them.
      • Firebase JWT authorizer configured at the HTTP API layer
      • Sign-in with Google and Apple, plus phone-based registration
      • Handlers receive an already-authenticated identity
    3. 03

      A serverless API sized per function

      The API is a set of independently packaged Lambda functions deployed with the Serverless Framework to São Paulo — the closest AWS region to Uruguay, which matters more than it sounds when the client is on mobile data on a highway.
      • Each function packaged and optimised individually, so cold starts stay small
      • TypeScript end to end, with the entity and repository layers shared
      • Deployed to sa-east-1 for Latin American latency
    4. 04

      The full ride lifecycle, including when it goes wrong

      Rides, ride requests, passengers, reviews and complaints are each modelled explicitly. The complaint path is not an afterthought bolted on after the first bad trip — it shipped with the product.
      • Request and accept flow with seat accounting
      • Reviews in both directions, driver and passenger
      • A complaint path with its own handling, separate from reviews
    5. 05

      Realtime messaging with shared location

      Once a ride is agreed, riders and drivers coordinate in-app. Messaging runs on Firestore with push through Firebase Cloud Messaging, so the conversation survives the app being backgrounded — which it always is, because the user is travelling.
      • Firestore-backed messaging with live location sharing
      • Push notifications through Firebase Cloud Messaging
      • Crashlytics, Analytics and Remote Config for release safety
    6. 06

      Two client generations

      The product shipped first as a React Native app in TypeScript, then was rebuilt in Flutter as the team's needs changed. Both generations ran against the same API — which is the payoff for having drawn that boundary properly in the first place.
      • v1: React Native, Redux Toolkit, React Navigation, native maps
      • v2: Flutter with Riverpod and a GraphQL client
      • One API contract across both, no rewrite of the backend

    The stack

    Mobile
    React NativeTypeScriptRedux ToolkitReact NavigationFlutterRiverpod
    API
    AWS LambdaAPI GatewayServerless FrameworkTypeScript
    Data
    PostgreSQLFirestore
    Identity
    Firebase AuthGoogle Sign-InSign in with Apple
    Platform
    Firebase Cloud MessagingCrashlyticsAnalyticsRemote Config
    I couldn't be happier with the outstanding job pdelabs did in developing our carpooling app. Their team was always available, responsive, and really understood what we wanted, the development process was really smooth and we always knew what to expect. I highly recommend them for any software development needs.

    - Mario Guadalupe, founder

    Have something like this to build?

    Schedule a call now

    We love to take on new challenges, tell us yours.

    Schedule a call

    Or
    if your prefer taking it offline, write us
    via email
    We will get back to you in less than 24 hs.