↗

Flutter + Laravel: shipping iOS and Android from one API

A product that runs on the web, iOS and Android can easily turn into three products: three codebases, three sets of business rules, and three places for the same bug to hide. For a small team, or a single developer, that is not sustainable.

RestorePartnerPro is a referral marketplace with a web platform and apps for both mobile platforms. I built all of it on my own and have run it for more than two years, with 300+ leads a month flowing through it. The reason that is manageable is one architectural decision: one Laravel API and one Flutter codebase. Here is why that combination works, and the habits that keep it healthy.

The shape of the system

There is exactly one place where a lead’s rules live. Web, iOS and Android can’t disagree about what a lead is, because none of them decides.

Why Flutter for the apps

Flutter compiles to native code for both platforms from one codebase. For a business app, with forms, lists, detail screens, notifications, maps and photos, it covers almost everything you need, and a feature is built once and ships to both stores together.

The practical gains for a lean team:

When would I not use Flutter? If the app is mostly a thin wrapper around heavy platform-specific features, such as advanced AR, deep Bluetooth work or very custom native UI. Those cases are rarer than people expect, and it is worth asking the question honestly at the start.

Why Laravel for the API

Laravel gives you the backend pieces a mobile product needs without assembling them yourself: authentication (Sanctum works well for mobile tokens), validation, queues for notifications and emails, policies for permissions, and an admin panel built in the same codebase. Most importantly, it keeps business logic on the server, which matters more for mobile than for web.

Rule one: keep the apps thin

A web deploy reaches every user in seconds. A mobile release goes through app review, and then sits waiting for users to update. Some users never do.

That changes how you design. Anything that might change, such as pricing rules, validation, which actions are allowed and what a status means, belongs on the server. The app asks the API and displays the answer. When a rule changes, you deploy the backend and every client, including the old app versions in people’s pockets, behaves correctly.

Rule two: design the API for the screens

When one person builds both ends, there is no excuse for an API that makes the app do five requests to draw one screen. Shape responses around what the screens need, and keep them consistent with Laravel’s API Resources:

class LeadResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'status' => $this->status,
            'status_label' => $this->status->label(),
            'submitted_at' => $this->created_at->toIso8601String(),
            'referrer' => new ReferrerResource($this->whenLoaded('referrer')),
            'can' => [
                'update' => $request->user()->can('update', $this->resource),
            ],
        ];
    }
}

Two habits worth copying from that example. Send display-ready values like status_label, so wording changes don’t need an app release. And send permissions in the payload (can.update), so the app shows or hides buttons based on the server’s rules instead of duplicating them.

Rule three: never break old app versions

Because old versions stay installed, the API has to stay backwards compatible:

Rule four: share the boring parts

On the Flutter side, keep one API client with authentication, error handling and retries in one place, and generate or hand-write typed models that mirror your API Resources. On the Laravel side, the same Resources serve the web front end and the apps. Every screen benefits when the plumbing is done once.

What this buys you

The payoff isn’t elegance; it is time. With one backend and one mobile codebase:

If you are planning a product that needs web, iOS and Android, this is the setup I recommend for most teams. The RestorePartnerPro case study shows how it worked in production.

Let's talk about yours.

Book a free 30-minute call. Within 48 hours you'll have a written plan with scope, timeline and a fixed price.