Cross-platform app development · UAE

One app for iPhone and Android.

Cross-platform app development shares the screens, the state and the business logic. Identity, the two payment sheets and right to left sit at the seam, and they decide the framework.

Map what can be shared, before you pick a framework

What cross-platform app development is

What cross-platform app development covers.

One codebase, one team and one release train cover most of an app. What the operating system owns is written per platform, whichever framework you choose.

Cross-platform · one codebaseONE SOURCErutab/marketmainshared code95%one source, both storesFlutterReact NativeBOTH STORESApp StoreRutab Market4.8GETGoogle PlayRutab Market4.7InstallOne codebase, both stores, the seam written twice.

One shared codebase.

Screens, state, navigation and the client that talks to your API. A Business Bay brokerage on a mainland DET licence, putting its own listings in front of clients, sits almost entirely in this column, which is what one codebase genuinely covers.

The parts written twice.

Anything the operating system owns: the identity app-switch, the two payment sheets, notifications, background limits. A Dubai Marina clinic group on a mainland licence, taking a verified sign-in and an instalment payment, holds most of its risk here.

Two app stores.

Two review queues, two privacy declarations, two organisation accounts. One build feeds both, so the slower reviewer sets the launch date rather than the engineering.

The scope

Six things a shared build gives you.

What a cross-platform engagement actually produces. Three outputs from the shared layer, one at the seam, and two that only exist because there are two stores.

One codebaseboth storesCode shared across platforms92%shared UI & logic, one teamShared 92%Platform-specific 8%Ships toApp StoreiOS · v1.0Google PlayAndroid · v1.0one build, maintained once, live on both stores

Built once for both.

Screens, state, navigation and the API client in a single project maintained by one team

Output

one codebase both stores build from

One projectOne team
Cost & timeline~50% lessBuild effortTwo native builds2× teamsCross-platform≈ halfTime to launchTwo native builds20 wksCross-platform11 wksone build instead of two, on a single runway

One team, one launch date.

One team on one runway instead of two teams working to two calendars

Output

what the shared layer saves is what funds the seam

One runwayBoth stores
Near-native performancecompiled nativeMetricNativeCrossFrame rate60 fps60 fpsCold start0.4s0.5sScroll jank0.1%0.3%within a hair of nativecompiled to native, so users cannot tell the difference

Real native speed.

The shared layer compiles to a native binary rather than running as a page inside a shell

Output

a parity scorecard measured on handsets, not a claim

Native binaryMeasured
Native modulesno feature off-limitsNative moduleiOSAndroidcameraMedia capturepayApple Pay & cardsflutter_localizationsRight to leftlocal_authBiometricsfirebase_messagingPush notificationsnative modules bridge whatever the framework stops short of

Native code at the seam.

Camera, biometrics, the payment sheets and push reached through modules written once per platform

Output

a module manifest agreed before the build

Per platformListed first
Both stores, one launchshippedFrom one build · launched 12 JulApp StoreiOS 17RMRutab Marketv1.0 · 4.8LiveGoogle PlayAndroid 14RMRutab Marketv1.0 · 4.7Liveone team, one release date, both app stores together

Both stores, one plan.

One release train feeding two review queues, with the slower one holding the date

Output

both listings live on the same day

Two reviewsOne date
Flutter or React Nativedecided on fitFit by criterionFlutterRNCustom, branded UIExisting React / web teamPixel-identical on bothLargest plugin ecosystemchosen on your team & productthe right framework, decided with you, not by habit

The framework choice explained.

Flutter or React Native chosen after the module manifest exists, with the reasons and the cost of reversing it

Output

a decision you can hold us to

FlutterReact Native

Shared, or written twice

Where one codebase stops.

The per-platform column is the real build, whichever framework you choose. The shared column is the part one codebase genuinely covers.

The seamWritten per platformThe shared layerWritten once, both platforms
Screens and logicNothing, unless a screen has to follow a platform convention the other does not have.One set of screens, one state layer, one client talking to your API.
Arabic and right to leftAndroid still needs the right-to-left flag in the manifest and a mirrored resource set of its own.Shared, if the layout uses start and end from the first screen rather than left and right.
UAE PASS sign-inThe app-switch: a URI scheme registered in the iOS app, a queries entry in the Android manifest.The authorisation flow and the session it returns to your app.
Apple Pay and Google PayTwo payment sheets, two merchant identities and two sets of certificates, set up separately.The cart, the order and the reconciliation code sitting behind both.
Document captureThe camera and photo permission strings, declared in the iOS binary and in the Android manifest.The form, the validation rules and where the file is stored.
Push and background workTwo notification services, two entitlement sets and two sets of background-execution limits.The message payload and what the app does when it opens.
What we recommend.

The per-platform column is the build, whichever framework sits above it, which is why the framework is chosen after this list exists rather than before it. A Dubai Silicon Oasis software firm on a free zone licence, with a live iOS product and nothing on Android, reads it for a different question: what the second platform inherits, not what the first is rewritten in. Still weighing whether this has to be an app? That question comes first, and the pillar sets out how the engagement runs.

What we find at the seam

Where the sharing stops.

Webzenia has worked with Gulf clients since 2018. These four decide where the shared layer stops, and none of them is settled by picking a framework.

  1. 01of 04
    Identity sits at the seamBoth platforms

    Permissions decide what cannot be shared.

    Signing a user in through the national identity app means leaving your app and coming back. That is a scheme registered in the iOS binary and an entry in the Android manifest, not a line of shared code, and no framework removes it.

    Our methodThe app-switch declared per platform, in staging as well as production.
  2. 02of 04
    Money is written twiceFinance inherits it

    Each wallet needs its own merchant account.

    Apple Pay and Google Pay are set up separately, certified separately and settle separately. The choice reaches engineering as an integration and reaches the finance team as a second monthly reconciliation nobody asked them about.

    Our methodWallets and gateway agreed with finance before the sheet is built.
  3. 03of 04
    Arabic is structureNot a translation

    Plan Arabic layouts from the first screen.

    A layout written with start and end mirrors on its own. One written with left and right does not, and the correction is every screen a second time, which is the retrofit that makes Arabic look expensive when it was only late.

    Our methodBoth directions built from the first screen and tested on handsets.
  4. 04of 04
    The order of the decisionList, then framework

    Your integrations decide the framework.

    Once the rails are written down the choice narrows on its own: what has a maintained binding, what your team can staff, and what the seam costs under each. Webzenia writes the list first and records the call with its reversal cost.

    Our methodThe framework decision written down, with what reversing it would cost.

What the engagement covers

Inside the build.

The engagement in six stages. The rail table comes first, because the framework choice is a consequence of it and not the other way round.

Scope · MVPSTEP 01MVP · V1Onboarding & loginBrowse catalogueCart & checkoutOrder trackingPLATFORMSAndroidiOSTIMELINE8 wksto MVP v1We pin the MVP, the platforms and the plan.

Scope and integrations.

We settle what the app has to reach, then mark every rail shared or per platform. A JLT commodities trader under DMCC building a partner portal reaches almost nothing the operating system owns; a consumer checkout reaches most of it.

  • Scope
  • Rail table
Build · cross-platformSTEP 02BUILDStackDart · FlutterCodebaseone · 2 OSCIpassingOne Flutter codebase, both platforms.

The framework and the build.

Flutter or React Native, chosen against the table and recorded with the reasons. The shared layer is then built once: screens, state, navigation and the API client.

  • Recorded
  • Shared layer
Integrate · servicesSTEP 03PPaymentscards, BNPLliveAAuthOTP loginliveMMapslocationliveNNotifypush · FCMliveWired to payments, auth and the rest.

Native code per platform.

The identity app-switch, the two payment sheets, notifications and background work, each written natively on both sides and bridged into the shared layer.

  • Swift
  • Kotlin
QA · both platformsSTEP 04DEVICE LABPixel 7Android 14iPhone 15iOS 18Galaxy A14Android 13iPad AiriPadOS 17CRASH-FREE · 7D99.6%sessions cleanTested across Android and iPhone.

Tested on handsets, both directions.

Tested in English and in Arabic on physical devices, because a mirrored layout and a longer string are the two things a simulator is most confident and most wrong about.

  • Real devices
  • Both scripts
Launch · both storesSTEP 05SShopApp4.8 · 2,400 reviewsLiveInstallBoth stores+ moreLive on Google Play and the App Store.

Both store reviews.

Two submissions, two privacy declarations and two review queues, planned as one release. The slower reviewer sets the date, so it is planned for rather than discovered.

  • App Store
  • Google Play
Handover · yoursSTEP 06HANDED OVERRepo · transferredStore console · your accountDocs · completeSUPPORT99.9% SLAa team that answersCode, store access and support, in your name.

Handover, with the seam documented.

The written record of what is shared, what is native and why, alongside the code. The next team inherits the boundary instead of rediscovering it one bug at a time.

  • Documented
  • Boundary

Our stack

The tools we use.

Two frameworks for the shared layer, two languages for the seam, one backend both platforms read. Select one to see when we argue against it.

Flutter
Why Flutter

Flutter draws its own widgets, so one visual result holds on both platforms, and its directional widgets mirror a layout right to left without a second stylesheet.

How we excel

We build in Flutter when the interface has to be identical in both directions and on both platforms, and we use the directional insets from the first screen rather than converting a laid-out app later.

Both directionsOne visual resultRenders
FlutterOwn engine
React NativePlatform views
Two native buildsTwice
A web view shellBrowser

How the build runs

From scope to both stores.

The framework is chosen in week two, not week zero. Everything before it establishes what the app has to reach, because that is the question the choice answers.

01Weeks 1 to 2Scoped

Listing the integrations.

We list everything the app has to reach and mark each rail shared or per platform: the identity app-switch, the wallets and gateway, capture, notifications, background work. Then the framework is chosen against that table and written down with the reasons and what reversing it would cost. Nothing is built in this phase, which is deliberate.

  • Railslisted and marked
  • Frameworkchosen after the list
  • Decisionrecorded with its reasons
02Weeks 3 to 10Built

Building the shared layer.

The shared layer is built once: screens, state, navigation and the client that talks to your API, in both directions from the first screen. The seam is written natively on both sides and bridged, so a feature is never dropped to keep the codebase pure. Builds go to physical handsets, in English and in Arabic, while there is still time to change them.

  • Shared layerbuilt once
  • Seamnative on both sides
  • Testedhandsets, both directions
03Month 3 onwardRunning

Launching on both stores.

One build produces two submissions, and the two do not clear at the same speed. We plan the release around the slower queue rather than the optimistic one, hold the faster listing until both are ready where a simultaneous launch matters, and keep the version numbers in step afterwards so a fix does not land on one platform and wait a fortnight on the other.

  • Submissionstwo, planned as one
  • Dateset by the slower queue
  • Versionskept in step after launch

Reported against the rail table, so you can see what is shared and what is not.

The seam, in writing
Rail tableBoth directionsTwo queues

Our commitment

Our promises, in writing.

A cross-platform build goes wrong at the seam. These four are written into the scope rather than agreed on a call.

  • Integrations listed before the framework.

    You get the shared and per-platform split in writing before anyone commits to Flutter or React Native. A framework recommended before the integration list exists is a preference, and it is yours to audit.

  • The framework choice, recorded.

    The decision is written down with the reasons and what changing it later would cost you. A five-year commitment made in week two should not arrive as a sentence in a proposal.

  • Native code where it matters.

    Where the framework stops short we write a module in Swift and in Kotlin. No feature is quietly dropped, downgraded or replaced with a web view to keep the shared codebase tidy.

  • No hidden second codebase.

    A per-platform branch inside shared code is a decision we write down and you approve, not one an engineer makes on a Thursday. Unrecorded forks are how one codebase becomes two without anyone deciding to.

Common questions

Cross-platform apps, answered.

Next step

Get your app scoped.

Send the list of what the app has to connect to. We will come back with the shared and per-platform split, and the framework it points at.

Tell us what you need.

+971
Chat on WhatsApp