Skip to content

MeCar

MeCar: bringing a car rental platform back from a failed build

A Saudi car rental platform arrived with a backend on an end-of-life PHP release, an iOS app but no Android, and a booking flow that did not complete. We rebuilt it into a working product: PHP 8.2, Android shipped from the existing Flutter codebase, Tabby and Tamara at checkout, delivery as a first-class option, and push notifications.

MeCar logo
  • Laravel
  • PHP 8.2
  • Flutter
  • Dart
  • Android
  • iOS
  • MySQL
  • Tabby
  • Tamara
  • Push notifications
  • Wallet & loyalty
  • Arabic / English RTL
  • REST APIs
  • 10,000

    users reached within two months of relaunch, as reported by the client

  • 2

    mobile platforms live, up from iOS only

  • 8.2

    PHP version the backend runs on, up from an end-of-life 5.x release

The challenge

MeCar rents cars across Saudi Arabia, with customers either collecting a vehicle or having it brought to them. The product had already been built once, by a previous development team, and it was not working. Not slow, not rough at the edges: it did not do the job it existed to do.

A booking platform that could not take a booking

The clearest symptom was the simplest one. Of the flow a rental business actually needs, from browsing a vehicle through to paying for it and receiving it, vehicle registration was the part we found working reliably. Much of what sat downstream of it was broken, unfinished or failing under conditions the original build had not anticipated. A rental platform that cannot complete a rental is not a product with bugs. It is a product that has not shipped.

A backend on a PHP release that was already years past end of life

The Laravel backend was running on a PHP 5.x release. PHP 5 stopped receiving security support at the end of 2018, so this was not a matter of being a version or two behind. It meant no security patches, no path to modern libraries, and a framework version pinned to the runtime holding it back. Every fix applied to that stack would have been work spent on ground that was already sinking.

One platform in a two-platform market

The mobile app was built in Flutter, which is a cross-platform framework, and yet only the iOS build had ever been shipped. In a market where Android holds a substantial share of users, that is not half a product, it is a large share of the addressable market that could not become customers at all. The cross-platform investment had been made and never collected.

Missing the things users read as competence

There was no splash screen, so the app opened on a blank frame while it initialised. There was no notification system, so the business had no way to reach a customer after they closed the app: no booking confirmation, no reminder, no delivery update. There was no way to put a message in front of users inside the product. Individually these read as polish. Together they are what makes an app feel finished, and their absence is what makes users decide it is not.

Payment methods the market expects

Buy now pay later is mainstream in Saudi Arabia rather than a fringe option, and Tabby and Tamara are the names customers look for. Neither was integrated. For a rental, where the customer is committing to a sum up front and often placing a deposit, the absence of instalment options is a direct constraint on conversion.

The solution

We took over the codebase and treated it as a rescue rather than a maintenance contract. The order mattered: platform first, because everything else would have been built on sand, then the missing product, then the things that turn a working app into one people trust.

The runtime and framework, brought to the present

We moved the backend to PHP 8.2, the current release at the time. Jumping from 5.x to 8.2 is not a version bump, it crosses two major versions of deliberate breaking changes: functions removed outright, comparison semantics changed, and error handling that converts what used to be a quiet warning into a thrown error. The framework had to move with it, because a Laravel release old enough to run on PHP 5 cannot run on 8.2 at all.

The value is not the version number. It is that the application is back on a supported, patched runtime where modern libraries install, current payment SDKs are usable, and the next five years of maintenance are ordinary work rather than archaeology.

The booking flow, made to work end to end

We worked through the product from browsing to payment to handover, fixing what was broken and building what had never been finished, until a customer could complete a rental without hitting a dead end. This is the least glamorous part of a rescue and the only part that decides whether it succeeded.

Android, from the codebase that was already there

Because the app was Flutter, the Android platform was already paid for and simply had never been delivered. We built, tested and shipped it, which meant handling the platform differences the original build had never had to face: permissions, notification behaviour, back-navigation, device and screen fragmentation, and store requirements. MeCar went from serving one platform to serving both.

Delivery as a first-class option

MeCar's business is not only customers arriving to collect a car. Vehicles are delivered too, and the product needed to reflect that. We added delivery as a proper option in the booking flow rather than an afterthought, so the choice between collection and delivery is made by the customer at the point of booking and carried through the rest of the process.

Tabby and Tamara at checkout

We integrated both providers so customers can pay in instalments. Rental adds a wrinkle that ordinary retail does not: there is a deposit, there are amendments, and there are refunds that may be partial. An instalment integration that only handles the happy path creates a finance problem later, so the work included making the awkward paths behave correctly rather than just producing a successful first payment.

Notifications, splash screen and in-app messaging

We built a push notification system, so the business can confirm a booking, remind a customer and update them on a delivery, and so it has a route back to a user who has closed the app. We added a splash screen, so the app opens on something considered rather than a blank frame. And we added in-app pop-ups, so MeCar can put an offer or a message in front of users without shipping a release to do it.

A wallet, loyalty and referrals

Once the platform was sound, the work moved to the things that make a rental customer come back rather than rent once. We built a wallet, so a customer can hold a balance and pay from it, which removes friction from every booking after the first. We built a loyalty programme that earns points on rentals and converts them into wallet credit, and a refer-and-reward scheme that pays out when an invited friend completes their first booking. Each of these is straightforward on its own. What makes them work is that they share one balance and one ledger rather than being three disconnected features, which is a decision that is cheap at design time and expensive later.

Arabic and English

We added English alongside Arabic, so customers can browse and book in either. In this market that is not a translation task. Arabic is right to left, so the layout mirrors, and a rental app is full of dates, times, durations, currency and vehicle specifications that all have to read correctly in both directions.

The unglamorous conversion work

Later releases went after the specific places customers were dropping out: registration and account creation simplified, phone verification fixed so it works with the country code the user actually selected rather than assuming one, and vehicle details made shareable by direct link so a customer can send a car to whoever is paying. Individually small. Together they are the difference between a signup flow that works for everyone and one that quietly fails for a segment of your market.

Inside the platform

The splash screen, which the app did not have before. It opened on a blank frame while it initialised.
The splash screen, which the app did not have before. It opened on a blank frame while it initialised.
Booking: city, dates, daily or monthly hire, and the delivery toggle that lets a customer have the car brought to an address rather than collecting it.
Booking: city, dates, daily or monthly hire, and the delivery toggle that lets a customer have the car brought to an address rather than collecting it.
The fleet, filtered by pickup location and manufacturer, with daily pricing and offers shown per vehicle.
The fleet, filtered by pickup location and manufacturer, with daily pricing and offers shown per vehicle.

Results & impact

The platform went from not functioning to running as a live rental business across Saudi Arabia, on both mobile platforms, on a supported runtime, taking the payment methods its market expects.

  • The client reports reaching 10,000 users within two months of the relaunched product going live.
  • Both mobile platforms live, up from iOS only, with Android built from the Flutter codebase the business had already invested in.
  • The backend on PHP 8.2, from a PHP 5.x release that had been out of security support since 2018.
  • Tabby and Tamara available at checkout, including the deposit, amendment and partial-refund paths that instalment payments complicate for a rental business.
  • Delivery bookable in the product, matching how the business actually operates rather than only supporting collection.
  • A route back to users through push notifications and in-app messaging, where previously there was none once the app was closed.
  • Wallet, loyalty and referrals sharing one balance and one ledger, so repeat rental has a reason to happen.
  • Arabic and English throughout, including the right-to-left layout work that a rental app full of dates, durations and pricing actually requires.

Most of this is publicly checkable rather than something you have to take on trust. The app's release notes on the App Store record the releases as they shipped: instalment payments through Tamara and Tabby, delivery to a customer's location, the new splash screen, the wallet, the loyalty programme, referrals, English language support, and later the registration, phone-verification and deep-link fixes.

The honest summary of an engagement like this one: almost none of the value was in new invention. It was in taking something that had been built badly and making it work, then removing the reasons it would fail again. That is unfashionable work, and for a business with a product it cannot sell, it is the only work that matters.

Capabilities behind this build

The disciplines this engagement drew on — explore how we apply them.

Technologies we work in

Chosen per problem, not per fashion.

Tell us what cannot fail.

A technical conversation with the engineers who would do the work. If we are not the right fit, we will say so on the call.

  1. 01A senior engineer reads it. Not a form queue, and not an account manager.
  2. 02We reply either with questions or with a straight answer that we are not the right fit.
  3. 03If it looks like a fit, a technical call with the person who would actually run the delivery.
  4. 04Then scope, effort and risk in writing, before anyone signs anything.

Two fields required. We reply to real enquiries. No list, no sequence.