Btaxi
A ride-hailing MVP for Cambodia, across rider, driver and admin.
I designed it and I built it: I wrote the spec and the business rules, ran the AI agent in Cursor that writes the code, worked with two contract developers and external QC, and shipped only what passed my tests.
Client UAT passed · launch on hold on the client's sideApp screens from my Figma file, admin screens from the live build, all shown in English with demo names, places and prices. Map data © OpenStreetMap contributors.
- How did I help
- End-to-end build
- Mobility · Cambodia
- Role
- Product designer & builder
- Team
- Me + an AI agent, 2 contract devs, external QC
- Surfaces
- Android, iOS, admin web
- Year
- 2026
- A ride-hailing MVP for Cambodia: a rider app, a driver app and a web admin, designed and built by me with an AI agent.
- Drivers top up by bank transfer with admin approval, because ABA Bank integration wasn't legally possible at MVP stage.
- 130 updates and 13 blocking bugs fixed in three months. Client UAT passed; the launch is on hold on the client's side.
The tour: No bank integration? → I build with an AI agent → Three bugs

One market.
Three apps. Local constraints.
The product had to work for locals, expats and tourists at the same time, on a startup budget.
- 01Three apps that must stay in syncRider, driver and admin all have to agree, or riders stop trusting the system.
- 02No budget for custom infrastructureSo I reused an existing ride-booking and GPS platform, and spent design time on the parts that needed local thinking.
- 03The payment people expect isn't availableABA Bank integration wasn't legally possible at MVP stage, even though it's how most people expect to pay in Cambodia.
The same ride,
seen from both seats.
While the rider watches the driver come, the driver gets the rider's pickup and a button for each step of the trip.

Rules first,
screens second.
Each of these started as a rule in the spec, then became the screen that makes the rule obvious.

A coupon comes off the base fare
The discount applies to the base fare of the vehicle the rider picks, and the fare is fixed before booking.
No bank integration?
Design a deposit flow admins can trust.
A semi-automated deposit with manual admin approval, so drivers can top up before a bank integration is legally possible.


Inside the two apps.
Book a ride, ride it, drive it, and top up the driver's wallet.

Book a tuk-tuk with a coupon
Pick a destination, choose a vehicle at a fixed price, add a coupon, book.
Profile,
documents, then review.
A new driver fills in a profile, uploads the ID, licence and vehicle papers, can add a referral, and waits for an admin to approve them.

One admin behind both apps.
Top-ups, drivers, rides, fares and coupons are run from one web admin. Captured from the live build, shown in English with demo data.

Approve a driver's top-up
Every bank transfer a driver reports waits here, with the amount and the time, until an admin approves or rejects it.
One system,
five scripts.
Semantic colours, responsive type for the app and the admin web, and a font-family variable per language: Manrope for English and Vietnamese, Noto Sans Khmer for Khmer, and Noto for Chinese, Japanese and Korean.

I build with an AI agent.
I don't hand-write the code. I write the spec and the rules, the agent writes each change, and nothing ships until it passes my tests.
- 01SpecI define what gets built: the screens, flows and states for all three apps.
- 02Business rulesPricing, payments and permissions written down as rules the build has to follow.
- 03Build with the agentAn AI agent in Cursor writes each change and opens a pull request. The contract devs build against the same spec.
- 04Agent-assisted QAI test each build against my rules, with an AI agent helping to check behaviour.
- 05FixAnything that breaks the spec goes back with the correct logic written out.
- 06ShipA backend developer merges it, it deploys to staging on its own, and a smoke test checks it.
54 test cases between the rules and the release.
Specs, tickets for the devs and the agent, and every test case live in one Notion hub. A change only moves on when its test case passes.

Three months,
written down.
Counted from my Notion logs, July to October 2026.
One row per change,
in four logs.
Backend, rider app, driver app and admin web each keep their own log: what changed, its priority, the files, the branch and whether it passed. My notes are in Vietnamese, the working language of the team.

A coupon that replaced the fare.
Because I owned the pricing rules, I could see the build breaking them, write out the correct logic and get it fixed before handoff.


Three bugs,
traced to where they started.
When a ride failed, the ticket only closed once the cause was found, the data was repaired and a fresh test passed.
- SymptomRiders were told no drivers were available, even with drivers online.
- Root causeBooking saved the order, then called a live-update service that had been deleted, and broke. Each failure left a driver stuck as busy.
- FixThe backend now carries on when that service fails, and 6 stuck records were repaired.
- ProofA smoke test on staging passed.
When the happy path breaks.

A wrong verification code
A wrong code turns every box red and offers Resend, instead of a message the rider has to read.
The spec is the product.
The devs and the AI agent only build what I actually write down. When I wrote the logic tightly, the build came back clean. When I left a rule a little fuzzy, QA is where it came back to bite me. So writing the rules is the real work, not the warm-up.
- Invest selectivelyReusing infrastructure freed design time for the parts that build local trust.
- Script is a technical problemKhmer support meant testing layout and rendering on budget Android, not just translating.
- Admin risk is product riskThe biggest blocker wasn't design or code. It was paperwork: the Apple Developer account and the business licence the SMS sender needs.
A multi-app MVP, scoped piece by piece.
Three connected apps are priced by what each one needs. Pick the pieces, and I send a written proposal within 48 hours of our call.
A build like this: multi-app, priced after a scoping call
















