One core. Two apps that each belong on their own platform.
Every cross-platform framework asks you to trade something away — usually the feeling that the app was made for the phone it is running on. Duet makes a different trade: the business logic is guaranteed identical across iOS and Android, and the interface on each side is fully, natively that platform.
The cross-platform bargain has been the same for fifteen years. Write once, run anywhere, and accept that the result is slightly wrong in both places — a scroll that does not decelerate the way the OS does, a navigation pattern borrowed from the other platform, a date picker nobody on this platform has ever seen.
Most teams accept it, because the alternative is maintaining two codebases that drift apart. One team ships a feature, the other ships it three weeks later with a subtly different edge case, and six months in you cannot answer "does this work the same on Android?" without checking.
Duet is Modaal's answer to both problems at once: the part that should be identical is guaranteed identical, and the part that should be different is genuinely, natively different.
How it works
- 1
One core, defined once
Business logic, data models, validation, state and API contracts live in a core that is the same on both platforms. Not similar. The same.
- 2
Two native shells
Swift and SwiftUI on iOS. Kotlin and Compose on Android. Real native UI code, not a bridge, not a renderer, not a webview.
- 3
Each platform is fully itself
The iOS app follows Apple's Human Interface Guidelines and current Liquid Glass idiom. The Android app follows Material 3 Expressive. Neither is a translation of the other.
- 4
Parity, by construction
Because the core is shared rather than reimplemented, behaviour cannot drift. What works on iOS works the same way on Android, and the reverse.
What "identical core" actually buys you
The expensive part of maintaining two native apps is not writing the second one. It is keeping them honest about each other.
Feature parity decays quietly. Someone fixes a rounding bug in the iOS pricing logic and the Android version keeps the bug for two releases. A validation rule tightens on one side and not the other, and support starts seeing tickets that only reproduce on one platform. Nobody decided this would happen; it is just what two codebases do.
When the core is shared, that class of divergence stops being possible. A rule changes once. An edge case is handled once. The question "does this behave the same on Android?" has an answer you do not have to go and check.
What remains different is what should be different: how the app looks, how it navigates, how it feels under your thumb.
Why the UI should not be shared
This is where cross-platform frameworks make their mistake, and it is an understandable one — if sharing logic is good, sharing UI seems better.
But iOS and Android are not the same product with different logos. They have different navigation models, different gesture vocabularies, different typography conventions, different ideas about where a back action lives and what a modal means. Users do not consciously catalogue these things. They just know when an app feels off, and they trust it slightly less.
The gap widened recently rather than narrowing. Apple's Liquid Glass design language brought a new material and a rethought sense of depth and hierarchy across iOS. Android's Material 3 Expressive moved in its own direction, with its own motion and shape language, and Compose is now the first-class way to build it. A single shared UI layer cannot be current in both. It can be a reasonable approximation of both, which is a different and lesser thing.
Duet does not try. The iOS shell is SwiftUI written to Apple's guidelines. The Android shell is Compose written to Material 3 Expressive. Each one gets to be right.
How this compares to the alternatives
React Native, Flutter and similar. One codebase, one UI layer, rendered on both platforms. Genuinely good for shipping fast and for apps where platform idiom matters less than speed. The cost is that neither app is fully native, adopting a new OS design language means waiting for the framework, and platform-specific behaviour arrives as escape hatches. Duet's trade runs the other way: more surface area, native on both sides, no waiting.
Two separate native codebases. The honest, expensive option — and what serious teams do. You get full nativeness on both platforms and pay for it in duplicated effort and slow parity drift. Duet is an attempt to keep the first half and remove the second.
Apple-only tools. Several good products in this category build beautiful native Apple apps and have no Android story at all — by design, not oversight. That focus buys real platform depth. It also means that if Android ever appears on your roadmap, the tool cannot follow, and you are starting over in a second product with a second workflow.
Kotlin Multiplatform. The closest thing philosophically, and a genuinely good technology — shared logic, native UI on each side. The difference is what you have to build yourself: KMP gives you the capability, and you architect the shared core, wire up both shells and maintain the arrangement. Duet is that arrangement, scaffolded and maintained for you, with an agent writing into it.
What this looks like in practice
You describe a feature once. Modaal writes it into the shared core, then builds the iOS presentation in SwiftUI and the Android presentation in Compose — each following its own platform's conventions rather than a compromise between them.
You can start from either side. Bring an existing Modaal iOS app and add Android to it, start both together from scratch, or start Android-first and add iOS later. The core is the same either way, so there is no "primary platform" whose decisions the other one inherits.
And because Modaal generates real native projects, both outputs are ordinary codebases on your own disk. Open the iOS side in Xcode, the Android side in Android Studio. Add packages. Point your own CI at them. Hand either to an engineer who has never heard of Modaal.
Frequently asked questions
Duet is Modaal’s framework for building iOS and Android apps from one shared core. The business logic layer is identical across both platforms, while the user interface on each side is fully native — Swift and SwiftUI on iOS, Kotlin and Compose on Android — so each app follows its own platform’s design conventions rather than a compromise between them.
No. React Native and Flutter share the UI layer as well as the logic, rendering one interface on both platforms. Duet shares only the core and builds two genuinely native interfaces. That means more surface area, but each app follows its own platform’s current design language — Liquid Glass on iOS, Material 3 Expressive on Android — rather than approximating both.
Philosophically it is close — shared logic, native UI on each side. The practical difference is how much you build yourself. Kotlin Multiplatform gives you the capability and leaves the architecture, both shells and their ongoing maintenance to you. Duet is that arrangement already scaffolded, with an agent writing into it and keeping the two sides in step.
The core does, because it is shared rather than reimplemented on each side — so business logic, validation and data handling cannot drift the way they do between two separately maintained codebases. The interfaces deliberately do not behave identically, because iOS and Android users expect different navigation, gestures and layout conventions.
Modaal Free builds one platform of your choice — iOS or Android — with unlimited prompts and no expiry, so you can see the native output for yourself at no cost. Duet, meaning both platforms together from one shared core, is part of Pro at €9 a month billed annually.
Yes. You can bring an existing Modaal iOS app across, start both platforms together from scratch, or begin Android-first and add iOS later.
Android is in open beta now, with general availability in September 2026. You can join the beta from the waitlist — registering gives priority access.
Yes. Modaal generates ordinary native projects on your own disk — the iOS side opens in Xcode, the Android side in Android Studio. There is no proprietary format and no export step, because the code was never anywhere else.
Build both, without building twice
Start free on one platform today. Android is in open beta — join the waitlist for priority access.