Skip to content
Wayvero

Case study

Wayvero: route-overlap matching and a real trust model

A consumer carpool app is a hard startup, not a freelance job. The narrow versions are real, funded work: a corporate campus carpool, a university transport portal, a travel operator’s shared cabs. Wayvero is built to be white-labelled into exactly those.

Stack
Next.js 15, TypeScript, no database
Demo data
4 corridors, 41 pickup landmarks, 108 generated rides
Engine
Route segments in a 0.1° grid index, 3 km snap radius

01 The narrow version

Not a BlaBlaCar clone. The pitch is the narrow version done right: overlap matching and a real trust model, white-labelable for a campus, a company or a travel operator.

Where the incumbents are strong, and the gap this demo is built to show.

  • BlaBlaCar

    Strength
    Intercity trust and a large review base; India is among its biggest markets by users.
    Gap Wayvero highlights
    Matching is mostly city to city, landmark pickups are weak, and there is no corporate layer.
  • Quick Ride

    Strength
    Commute and cab in NCR and Bengaluru, with auto-match, recurring rides, number masking and SOS.
    Gap Wayvero highlights
    Consumer-first, dense UI; corporate reporting is opaque.
  • sRide

    Strength
    Corporate carpool with workplace verification, fuel split and route matching.
    Gap Wayvero highlights
    Closed and enterprise-only: there is nothing to see before a sales call.
  • Toogo, Zify, WhatsApp groups

    Strength
    Zero friction and community trust.
    Gap Wayvero highlights
    No verification, no cost split, no safety tooling.

The demo visibly matches the table stakes — OTP-verified profiles, two-way ratings, number masking, women-only rides, recurring commutes, trip sharing and SOS — and shows off what the incumbents don’t: the overlap drawn on the map, a “why this matched” explanation, pro-rata fares for partial trips and a company CO₂ dashboard.

02 Matching on partial route overlap

Matching only on origin and destination misses most viable rides. Someone driving New Delhi → Jaipur should show up for a Gurugram → Behror search.

Route-overlap match: a Dhaula Kuan Metro to Sindhi Camp Bus Stand ride serving a Rajiv Chowk to Behror Midway searchThe driver's route runs from Dhaula Kuan Metro (km 0) through Rajiv Chowk (km 21) and Behror Midway (km 118) to Sindhi Camp Bus Stand (km 237). The passenger's pickup and drop each lie within 3 km of the route and snap onto it. Pickup comes before drop in the direction of travel, so the highlighted stretch between them is the match.Dhaula Kuan Metrokm 0Rajiv Chowkkm 21Behror Midwaykm 118Sindhi Camp Bus Standkm 237Your pickupwithin 3 kmYour dropwithin 3 kmSchematic, not to scale
Right directionPickup at km 21 comes before drop at km 118.98 km sharedOf a 237 km route.₹270 for the stretchOf ₹650 for the whole ride.
  1. 1Index the routesEach ride’s route is split into segments. A segment goes into every 0.1° grid cell its bounding box touches, padded by the snap radius, so a lookup reads a single cell.
  2. 2Snap drop, then pickupFind segments within 3 km of the drop point first: most rides fail there, so the pickup lookup only runs when something passes the drop.
  3. 3Check direction and overlapThe pickup must come before the drop along the route, and the shared distance must be 0.7–1.6× the straight-line trip, which rejects routes that only brush both points.
  4. 4Price the stretchCheap filters (day, seats, women-only, visibility) run before any timezone maths. The fare is pro rata to the shared kilometres, rounded to ₹10 with a ₹50 floor.
const nearDrop = nearSegments(ctx, q.to, stats)
if (nearDrop.size === 0) return noMatches // most rides fail here, cheaply
const nearPickup = nearSegments(ctx, q.from, stats)

for (const [rideId, pickupSnap] of nearPickup) {
  const dropSnap = nearDrop.get(rideId)
  if (!dropSnap) continue
  if (pickupSnap.km >= dropSnap.km) continue // wrong direction

  const matchedKm = dropSnap.km - pickupSnap.km
  const ratio = matchedKm / tripKm
  if (ratio < MIN_OVERLAP_RATIO || ratio > MAX_OVERLAP_RATIO) continue

  // Cheap filters first; date maths only for rides that survive them.
  if (dayOffset !== null && ride.dayOffset !== dayOffset) continue
  if (ride.seatsTotal - ride.seatsBooked < q.seats) continue
  if (q.women && !ride.womenOnly) continue
  if (!canSee(ride, ctx.viewer, ctx.policy)) continue
  // …departure time at the pickup, fare, score
}
The core loop, trimmed from lib/matching/match.ts.

Is the grid worth it?

  • 12.1×faster lookup at p50
  • 4.9×faster lookup at p95
  • 3.8×faster end to end at p95

1,000 dated searches over 5,000 synthetic rides (36,460 route segments). Both strategies return identical results.

  • Naive scan

    Lookup p50
    6.60 ms
    Lookup p95
    7.20 ms
    End to end p50
    7.04 ms
    End to end p95
    7.82 ms
    Segments checked
    70,659
  • Grid index (0.1° cells)

    Lookup p50
    0.55 ms
    Lookup p95
    1.45 ms
    End to end p50
    0.92 ms
    End to end p95
    2.06 ms
    Segments checked
    5,068

Honest reading: the typical search is about 12× faster, but the slow tail only gains about 5×. That tail is Delhi-NCR, where the Jaipur, Chandigarh and commute corridors overlap and a query still checks thousands of segments — the case a finer grid or a real R-tree is for. In production the segments live in PostGIS with a GiST index and the same lookup is ST_DWithin(segment.geom, point, 3000), followed by the same direction and overlap checks in SQL.

03 Trust is the product

Ride-sharing is a safety product first. Every feature below answers a specific fear a first-time rider has.

A trust ladder you can see

  1. Tier 0NewA phone number, nothing more.Can request rides that need driver approval.
  2. Tier 1VerifiedPhone confirmed by OTP, plus a profile photo.Can instant-book and offer rides.
  3. Tier 2TrustedFive or more rides, rated 4.5 or higher.History that can’t be faked quickly.
  4. Alongside any tierWork-verifiedA workplace email on a registered company domain.Lets company commute rides stay inside the company.
  • Invisible, not disabled

    Women-only rides don’t appear for men at all — not in results, counts or nearby days. A direct link shows the same neutral “This ride isn’t available” page a full or cancelled ride would, so the ride can’t be probed.

  • Numbers stay masked

    Phones show as +91 98XXX XXX21 until a booking is confirmed; then a call and WhatsApp link appear. Until then chat redacts Indian mobile numbers, emails and UPI IDs, so contact can’t move off-platform early.

  • Blind ratings, both ways

    Passengers rate drivers and drivers rate passengers. Neither sees the other’s review until both are in, so nobody softens a rating out of fear of retaliation.

  • Share my trip

    A link for family shows the driver’s first name, the car and a masked plate with live progress — no phone numbers, no passenger surname — plus an SOS button that dials 112.

04 Demo mode, honestly

This build runs on Vercel with no database and no paid APIs. Anything that would be a server is a clearly labelled simulation; the engineering that matters is real.

What the demo simulates, and what the production build would use instead.

  • Database

    In this demo
    Typed fixtures from a seeded generator, plus what you do stored in this browser’s localStorage.
    In production
    Postgres + PostGIS. Route segments in their own table with a GiST index, queried with ST_DWithin(segment.geom, point, 3000).
  • Routing

    In this demo
    Hand-authored corridor polylines; each ride’s route is stitched from its corridor through its stops.
    In production
    OSRM (self-hosted) or Google Directions for the real road geometry.
  • Match cache

    In this demo
    In-memory FIFO memo of the last 50 searches.
    In production
    Redis, keyed by query and invalidated when a ride changes.
  • Phone OTP

    In this demo
    Any valid Indian mobile number; the code 246810 is shown on screen.
    In production
    MSG91 SMS OTP with rate limits per number and device.
  • Payments

    In this demo
    A real upi:// deep link and QR to a demo VPA, then “I’ve paid” or settle in cash.
    In production
    Razorpay UPI collect with webhook reconciliation.
  • Chat

    In this demo
    A local thread; the driver replies from a script after 1.5 s. Contact details are redacted until confirmation.
    In production
    WebSocket chat with the same redaction enforced on the server.
  • Live trip

    In this demo
    A simulated clock moves the car along the ride’s route at 120× speed.
    In production
    The driver app streams GPS; the share link reads the latest position.
  • Sign-in

    In this demo
    A persona switcher: Priya, Arjun, Neha, Rohan and Kavita.
    In production
    Phone-OTP sessions, with workplace email as a second factor.
  • Weekday commutes

    In this demo
    Series expand into dated runs in the browser, 14 days ahead.
    In production
    A nightly job materialises runs, re-plans each rider’s week and alerts them when a day loses its ride.

What is not simulated

The matching engine, pro-rata fares, visibility and company-policy rules, the booking rules and the commute planner are pure TypeScript functions that take the current time as a parameter, with unit tests. Every simulated surface carries a Demo badge naming the real integration, and Reset demo in the menu puts everything back.

05 For companies

What an office admin in Gurugram actually buys is a commute programme they can report on and control.

A report computed from rides, not typed in

  • Employees pooling, rides shared and seat fill.
  • Money saved against a cab baseline of ₹12 per passenger-km, net of fares paid.
  • CO₂ saved at 0.12 kg per passenger-km.
  • Four- or eight-week range, a weekly chart with a data-table fallback, and CSV export.

A policy that is actually enforced

  1. 1. Kavita, Acme’s admin, turns on Work email required.
  2. 2. Rohan has no acme.in email. He searches Cyber Hub → Sector 18 and the Acme commute rides are simply not in his results.
  3. 3. He opens a booking link directly anyway. The booking rules check the same policy and answer “This ride isn’t available.”
  4. 4. Priya, verified at acme.in, still sees and books them.

Recurring commutes

  • A driver posts their office drive once with the days it runs. Each day becomes its own ride with its own id, such as r-037-on-2026-09-17, so it is searchable, bookable and tracked separately — 14 days ahead.
  • A rider saves their commute. The planner lines up the next five days with a ride that stops within 2 km of both of their points and picks up within an hour of their time.
  • Book all books every open day or none of them, and names the day that failed if one can’t be booked.

06 Out of scope, and how I’d approach it

Real problems that are described here rather than half-built.

  • Payment disputes

    Collect through Razorpay before the ride, release to the driver after completion, and keep a short dispute window with a ledger per booking so support can see exactly what moved and when.

  • Live GPS and route deviation

    Stream driver GPS from the app. The matching engine’s point-to-segment distance already measures how far a point is from a route; alert the rider and their shared contacts when the car stays off route beyond a threshold.

  • Fraud

    An OTP ties an account to a SIM, not to a person. Add device fingerprinting, velocity limits on new accounts, and flags for rating patterns that repeat between the same pairs of users.

  • Insurance and commercial-vehicle rules

    Private cars can share fuel costs; carrying passengers for profit can breach commercial-vehicle rules. Keep prices near fuel-share guidance — the offer flows already suggest one — and get a legal review per state before launch.

07 Try it

Two minutes, six stops.

The tour walks through a partial match, a women-only ride disappearing, booking and chat, a live trip and the company dashboard. Everything you do stays in this browser; reset it from the menu.