Kandy Cycle
A peer-to-peer bicycle rental platform for cycling tourism in Kandy, Sri Lanka. Owners list their bikes, tourists book and pay, and curated routes are followed with live GPS tracking.

The problem
Cycling tourism is growing in Kandy, but there is no online way to rent a bicycle there. Tourists arrive and cannot find what is available, what it costs, or which roads are safe to ride. Local bike owners have no way to reach them at all. The bikes exist and the demand exists — nothing connects the two.
The wider problem is that much of Sri Lanka's tourism still runs on phone calls and manual booking. My dissertation asked whether a community-run platform could close that gap for one city, and what it would take to build one that people would trust with a payment.
My approach
Three decisions shaped everything else.
Booking is a state machine, not a flag. A rental moves pending → approved → paid → completed, and each transition has exactly one owner: the renter requests, the owner approves, Stripe confirms the payment, the handover completes it. Cancelling is only possible before payment. No screen ever has to guess what state a booking is in.
The payment webhook is the source of truth. Stripe Checkout handles the card, and an Express endpoint listens for Stripe's events and updates booking and payment status from those. I deliberately did not rely on the browser redirect after checkout. Someone closing the tab should not leave a paid booking looking unpaid.
Authorisation lives in the database. Supabase row-level security decides who can read and write what, so an owner can only edit their own listings and a renter only sees their own bookings. Those rules sit in Postgres rather than in React, so they hold no matter which screen calls them.
Then there is the part I cut. I specified dynamic route recommendation using Dijkstra and A*: a graph of Kandy's cycling network, junctions as nodes, roads as edges weighted by distance, elevation and scenic value, so a rider could ask for the fastest route or the prettiest one. I did not build it. With the deadline in view it came down to a half-working smart feature or a working simple one, and I shipped curated routes stored as GeoJSON and drawn with React Leaflet, with live GPS tracking over the top.
The graph design is written up in the dissertation. I would rather hand over something that works and say plainly what is missing.
The outcome
Ten functional test cases passed: registration, booking, payment, GPS recording, route following, route sharing, pickup verification, multi-step form validation, map rendering and real-time updates.
Measured: a 10.22-second build, a 1,045 kB bundle, 163 kB of CSS, and page loads of two to three seconds. GPS accuracy came in at ±5–10 metres against a ±5 metre target — recorded as missed rather than quietly rounded down.
The feature I am least sure about is pickup verification. It captures location, contact details and a timestamp when a bike changes hands, because that handover is where peer-to-peer rental actually breaks. It works, but it has never been tested by two strangers meeting on a street in Kandy, and that is the only test that counts.



