Cashback & Loyalty App Platform

Cashback & Loyalty App Platform
FlutterDartTypeScriptVuePHPPostgreSQLRubyFastlane

Project Overview

Our client runs a cashback platform that lets offline shops — cafés, salons, boutiques, neighbourhood retail — reward their customers and, just as importantly, finally get to know them. Brick-and-mortar businesses rarely have the customer data that online stores take for granted: who their regulars are, when they last visited, what brings them back. The platform closes that gap by putting a cashback and loyalty program in every participating shop's hands, and a branded app in every customer's pocket.

Rather than ship a single app, the business model calls for a family of applications: a flagship consumer app where shoppers discover participating shops and track their cashback, a dedicated merchant app for shops to connect and run their own rewards, and a growing catalogue of white-label apps — each one a fully branded, independently published cashback app for a partner brand or retail chain, all powered by the same product.

By the time the project matured, the ecosystem spanned 15+ live mobile applications. The engineering challenge was never building one app well — it was building one codebase that could become any number of branded cashback apps without the maintenance cost growing linearly with each new partner.

We were responsible for the entire system end to end: the shared consumer app, the merchant app, the white-label fleet, the cashback rules engine and backend services, and the internal admin tooling that turned "launch a new branded app" from a multi-day engineering task into a self-service form.

Consumer app home with cashback balance and invite-friends bonus

Consumer app home with cashback balance and invite-friends bonus

Shop details with per-purchase cashback rate

Shop details with per-purchase cashback rate

Vouchers and shop news feed

Vouchers and shop news feed

Single white-label application setup

Single white-label application setup

Admin UI white-label applications list

Admin UI white-label applications list

One Codebase, Many Apps

The flagship consumer app and every white-label variant run on a single codebase. There are no forks, no per-brand branches, and no copy-pasted projects to keep in sync. What differs between apps — branding, theme, brand identity, feature flags, reward configuration, and store-listing metadata — is expressed entirely as configuration that lives outside the code.

We built the client around a flavor-and-configuration system: a single binary blueprint that resolves its brand identity at build time from a per-app config bundle. Colors, typography, logos, splash screens, app icons, bundle identifiers, and enabled feature sets are all injected per flavor. A bug fixed once, or a feature shipped once, lands in every app in the fleet on the next release — there is no per-brand divergence to maintain.

Crucially, the levers that define each brand are operated by managers with no programming skills. Through the admin UI, a non-technical operator sets a new app's icons, colors, brightness (light or dark theme), and select labels — and those choices flow straight into the build with no developer involvement. The people who own a brand's look and feel can change it directly, instead of filing a ticket and waiting on engineering.

This is the core economic lever of the project: the marginal cost of the sixteenth app is close to zero, because it is the same code as the first, with a different configuration.

Native Build Configuration in Dart

A white-label fleet lives or dies on the native build configuration — the Android and iOS settings that the stores actually care about. Application IDs and bundle identifiers, app display names, version and build numbers, signing setup, icon and splash assets, and per-flavor entries in build.gradle and the Xcode project all have to be correct for every single app, every single build.

Rather than maintain that by hand, we wrote custom Dart tooling that programmatically manages the Android- and iOS-related build configuration. Given a brand's config bundle, the tool rewrites the relevant Gradle, manifest, Info.plist, and asset-catalogue entries to match the target flavor before the build runs. Keeping this logic in Dart means it shares the same source of truth as the Flutter client and runs as a first-class step of our build process — so a brand's native configuration is generated deterministically from its config, never edited by hand.

The Merchant App

Offline shops needed their own tool — not a stripped-down consumer view, but a purpose-built app for running a rewards program and understanding their customers. From the merchant app, a shop owner connects to the platform in minutes, defines their cashback and discount rules, confirms customer purchases to grant cashback, and finally sees who their customers are: new versus returning, how often they visit, and how each promotion performs. For many of these businesses it is the first structured view of their customer base they have ever had. We built it on the same Flutter foundation and shared component library as the consumer apps, so design-system updates and platform fixes propagate across both audiences, while the merchant-specific workflows live in their own modules.

Configurable Cashback & Discount Rules

The heart of the platform is a flexible rules engine that lets each shop design its own rewards with no help from us. Through the merchant app, a shop composes rules such as:

  • Per-purchase cashback — a percentage or fixed amount returned to the customer's balance on every qualifying purchase.
  • Birthday bonus — a reward credited automatically around a customer's birthday to bring them back through the door.
  • Invitation bonus — a referral reward that pays out when an existing customer invites a friend who joins and makes their first purchase.

Rules are data, not code: each shop picks its own combination, sets the amounts, caps, and validity windows, and the engine evaluates them at purchase time. Because the rules live in configuration, a shop can launch a birthday campaign or change a cashback rate itself, instantly, across its app — and we never ship a release to support it.

The Admin UI & Automated Build Pipeline

The standout piece of the system is the internal admin UI. Onboarding a new white-label brand used to be an engineering errand — create the configuration, register the bundle identifiers, generate signing assets, set up the store listings, and add the new target to CI. We collapsed all of that into a single web application that managers operate without writing code.

A manager fills in a form — brand name, theme, assets, store metadata, feature selection — and the system does the rest:

Configuration generation: The admin UI persists the new brand's configuration and assets and produces the per-flavor config bundle the Flutter client consumes.

Pipeline registration: The new app target is registered into the CI/CD pipeline automatically. The build system picks up the new flavor, runs our custom Dart tooling to apply the native Android and iOS configuration, and produces signed artifacts for both platforms.

Self-service launches: What previously required a developer in the loop for every new brand became a form-driven, repeatable process. The business can scale the number of published apps without scaling the size of the engineering team.

Build & Deploy Automation with Fastlane

The entire build-and-release process is automated end to end with Fastlane — the open-source toolchain for automating mobile build and deployment. We use it to standardize every step that would otherwise be manual and error-prone across 15+ apps: managing signing and provisioning, building and signing the iOS and Android binaries, and submitting each app to the App Store and Google Play along with its metadata and screenshots.

Because every app shares one Fastlane configuration parameterized per flavor, releasing the whole fleet is a single, repeatable operation. A new white-label brand inherits the exact same battle-tested deploy path as the flagship app — no bespoke release scripting required.

The admin UI is a Vue application backed by our PHP services and a PostgreSQL data store, with Ruby and Fastlane tooling orchestrating the build-and-release automation.

Backend & Services

Underpinning every app is a shared backend that runs the cashback ledger, the rules engine, customer profiles, and per-brand configuration. A single set of services backs the entire fleet, with brand context resolved per request — so a customer in any white-label app, the flagship app, or a shop using the merchant app is talking to the same battle-tested API surface, scoped to their brand. The ledger records every accrual and redemption so balances are always auditable, and customer profiles give each shop the insight into their audience that offline retail usually lacks.

Deferred Deep Linking & the Invitation Bonus

The feature this unlocked was the invitation bonus. Referrals are how the platform grows: a happy customer invites a friend, who taps the invite link — but almost never has the app installed yet. With a plain deep link, that invite context was lost the moment the friend hit the store: they would install, open the app, land on a generic home screen, and the connection between inviter and invitee was gone — and with it the invitation bonus both sides were promised. The most viral moment in the product was broken at its most important step. We fixed it with deferred deep linking so the invitation survives the install.

Because the whole fleet shares one codebase, the feature was built once and every branded app — flagship, merchant, and all white-label variants — inherited it automatically. We implemented it with first-party mechanisms rather than a third-party service: a lightweight iOS App Clip captures the invite link before the full app exists and hands it off through a shared App Group container, while the Google Play Install Referrer API carries the payload on Android. A pending-link queue holds the invitation until the app is ready and the new customer has signed up and logged in — only then is the referral attributed and the invitation bonus credited to both the inviter and the new customer, so the reward resolves correctly even though it spans an install and a fresh login on a cold start.

We wrote up the full technical approach — including why the common solution stopped working — in Deferred Deep Linking After Firebase Dynamic Links: App Clips + Play Install Referrer.

Results

The client can now launch a fully branded, store-ready cashback app for a new partner in a fraction of the time it once took — without pulling engineers off product work for each launch. The shared-codebase architecture keeps 15+ apps in lockstep: one fix, one feature, one release reaches them all. The admin UI turned a recurring engineering bottleneck into a self-service capability, and the automated pipeline made each new launch a predictable, repeatable event rather than a bespoke project. And the offline shops that once flew blind now run their own cashback and discount campaigns and, for the first time, know who their customers are.

This is the kind of platform we build as a white-label app development engagement — one Flutter codebase powering an entire fleet of branded apps.

Project Details

Client
Undisclosed (NDA)
Date
August 1, 2025
Duration
8 Months

Interested in a similar project?

Let's discuss how we can help bring your vision to life.

Get in Touch