> ## Documentation Index
> Fetch the complete documentation index at: https://docs.modaal.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# The Best Cross-Platform Frameworks in 2026

> Flutter, React Native, Compose Multiplatform, KMP, MAUI, Ionic, Skip and two native apps compared: who draws the screen, where logic runs, what proves parity.

The best cross-platform framework in 2026 depends on two questions most ranking pages never ask: who draws the screen — the platform's toolkit or the framework's own renderer — and where your logic runs — in a language runtime the app ships, or compiled against the platform. Answer those two and the field sorts itself; this page places every mainstream option on that grid, compares them side by side, and adds the axis none of the usual lists carry: what *proves* the two platforms behave the same.

*Last reviewed: September 1, 2026. Framework version and capability claims were checked against each framework's official documentation on this date.*

## How should you compare cross-platform frameworks?

<Frame caption="Who draws the screen × where the feature logic runs. React Native and Compose Multiplatform occupy the two mixed cells — a single native-vs-cross-platform line cannot place either.">
  <img src="https://mintcdn.com/modaal/uQZW84DTPYSQL62R/images/cross-platform-quadrant.svg?fit=max&auto=format&n=uQZW84DTPYSQL62R&q=85&s=e3ba64aa64ad834e638de407ccf49173" width="800" alt="Two-by-two grid placing cross-platform approaches by who draws the screen (platform toolkit vs framework renderer) and where logic runs (shipped runtime vs compiled). React Native, .NET MAUI and NativeScript top-left; Flutter and Ionic top-right; Compose Multiplatform bottom-right; Duet, two native apps, KMP shared-core practice, Rust cores and Skip bottom-left." data-path="images/cross-platform-quadrant.svg" />
</Frame>

The third question sits behind the grid: how do you know both apps behave the same? Two apps can behave identically **by convention** (two codebases kept in step by review and manual QA), **by construction** (one implementation, so there is nothing to compare — with the platform boundary exempt), or **by verification** (two implementations replay the same recorded fixtures, and CI compares the results byte-for-byte). Every approach in the table below is a position on the grid plus one of those three answers — [Should you share code between iOS and Android?](/articles/share-code-ios-android) develops the three-way distinction from the business side.

## How do the frameworks compare?

<div className="sticky-col">
  |                                              | **[Flutter](/articles/duet-vs-flutter)**                                                                                                                       | **[React Native](/articles/duet-vs-react-native)**                                                                                                                                        | **[Compose Multiplatform](/articles/duet-vs-compose-multiplatform)**                                                                                                                                                             | **Ionic / Capacitor**                                                                                                                       | **.NET MAUI**                                                                                                                                         | **KMP + MVI stacks** (Decompose, MVIKotlin, Circuit)                                          | **Skip**                                                                                                                             | **Two native apps**                                             | **Duet**                                                                                                                                   |
  | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
  | **Who draws the screen**                     | The framework — Impeller canvas on every target but web                                                                                                        | The platform — Fabric composes native views                                                                                                                                               | The framework — Skia canvas on iOS; on Android it *is* Jetpack Compose                                                                                                                                                           | A web view                                                                                                                                  | The platform — handlers map controls to `UIButton` / `MaterialButton`                                                                                 | Per team — native UI per platform, or Compose                                                 | The platform — SwiftUI transpiled to Compose on Android                                                                              | The platform, twice                                             | The platform — SwiftUI and Jetpack Compose, authored per platform                                                                          |
  | **Where feature logic lives**                | Once, in Dart, on the shipped Dart runtime                                                                                                                     | Once, in JavaScript/TypeScript, on the shipped Hermes engine                                                                                                                              | Once, in Kotlin, compiled — no bundled VM                                                                                                                                                                                        | Once, in JavaScript, in the web runtime                                                                                                     | Once, in C#, on the shipped .NET runtime                                                                                                              | Once, in Kotlin, compiled                                                                     | Once, in Swift — transpiled, or natively compiled via the Swift Android SDK                                                          | Twice, once per platform                                        | Once, in Kotlin, compiled into both apps                                                                                                   |
  | **What proves the two platforms agree**      | One implementation; code behind platform channels sits outside it                                                                                              | One implementation; code in native modules sits outside it                                                                                                                                | One implementation, UI included                                                                                                                                                                                                  | One implementation                                                                                                                          | One implementation; platform handlers sit outside it                                                                                                  | Shared unit tests; no parity gate between the two apps' behavior                              | One source of truth; the transpiler is the guarantee, UI included                                                                    | Code review and manual QA                                       | Recorded fixtures replayed on both platforms; CI compares byte-for-byte                                                                    |
  | **A native, perf-heavy island**              | Drawing stays in Dart (shaders, painters); a camera, video or GPU island is a `Texture` or a platform view fed by Swift/Kotlin plugin code                     | Animations can run on the native driver; a native island is a Fabric Native Component plus a Native Module, written per platform                                                          | Drawing stays shared (Compose `Canvas`); on iOS a native island is a `UIKitView` built in Kotlin through Objective-C interop (Swift only for Swift-only APIs) inside a Skia-drawn screen, on Android it is `AndroidView` interop | A Capacitor plugin in Swift/Kotlin, with native UI in its own view controller beside the web view rather than inside the page               | A handler customization or custom control reaching the `PlatformView`, per platform in C#; customizations are global unless the control is subclassed | Native already: ordinary Swift/Kotlin, with whatever seam the team's own architecture defines | Native already on iOS; on Android, hand-written Compose through `ComposeView` or `#if SKIP` blocks beside the transpiled UI          | Native already, written twice                                   | Native already: ordinary SwiftUI/UIKit and Compose/Android code; the reducer decides, a worker runs the pipeline, and the seam is recorded |
  | **Native code you write and compile for it** | Yes: Swift/Objective-C and Kotlin/Java in the host projects, compiled by Xcode and Gradle in the Flutter build; a plugin spares the writing, not the compiling | Yes: Objective-C++ and Kotlin/Java, compiled by Xcode and Gradle in the app build; an npm library spares the writing, not the compiling                                                   | Usually Kotlin only: Kotlin/Native's Objective-C interop builds UIKit views from Kotlin; Swift only for Swift-only APIs, compiled by Xcode                                                                                       | Yes: Swift/Objective-C and Java/Kotlin in the generated native projects, compiled in Xcode and Android Studio or by the CLI's build command | Platform-specific C# against the platform bindings, compiled by the .NET build per platform; no Swift or Kotlin                                       | Yes: Swift in Xcode, Kotlin in Gradle, as in any native app                                   | iOS: Swift in Xcode. Android: Kotlin is optional — `#if SKIP` blocks are Swift that transpiles to Kotlin; Gradle compiles either way | Yes, always                                                     | Yes, by design: Swift compiled by Xcode, Kotlin compiled by Gradle                                                                         |
  | **SwiftUI and Compose in the island**        | Yes, wrapped: `UIHostingController` inside an iOS platform view, `ComposeView` inside an Android one; a full-screen Compose activity is also documented        | Yes, wrapped: `UIHostingController` and `ComposeView` inside a Fabric Native Component with Objective-C++ glue; with Expo, Expo UI builds UI directly with SwiftUI and Compose from React | Compose is the Android UI; SwiftUI on iOS through `UIHostingController` passed to `UIKitViewController`, written in Swift                                                                                                        | Only as a native screen a plugin presents outside the web view, written in Swift or Kotlin                                                  | The handler surface is UIKit and Android Views through the .NET bindings                                                                              | They are the interface, by construction                                                       | They are the interface: SwiftUI on iOS, Compose on Android, transpiled or hand-written                                               | They are the interface, by construction                         | They are the interface: SwiftUI on iOS, Jetpack Compose on Android, by construction                                                        |
  | **Best fit**                                 | UI-neutral apps with little per-platform variation, one team writing Dart end to end, desktop and web from the same code                                       | Web/TypeScript teams, UI-neutral apps, the npm ecosystem, over-the-air updates                                                                                                            | Kotlin-first teams that want one UI implementation with little per-platform variation, plus desktop                                                                                                                              | Existing web apps and teams; content-driven interfaces                                                                                      | .NET shops; enterprise LTS alignment                                                                                                                  | Kotlin teams assembling their own architecture                                                | Swift-first teams that want Android from their existing SwiftUI source                                                               | Two independent platform teams; maximal per-platform investment | Rules-dense products that need native UI and a mechanical answer to "do the apps agree?"                                                   |
</div>

Approaches the table leaves as mentions: **NativeScript** (JS runtime driving native views — alive under the OpenJS Foundation, 9.0 announced November 2025, but absent from most current adoption lists) and **Lynx** (ByteDance's engine, open-sourced March 2025, powering TikTok surfaces; its ecosystem outside ByteDance is early). **Duet** is Modaal's cross-platform parity framework for native iOS and Android apps — the [overview](/articles/duet) covers the product; this page keeps it to one column among nine.

## Which approaches escape to native for a heavy screen?

The island row splits the table three ways. **Native already** — Duet, two native apps, the KMP shared-core practice, and Skip on iOS: a Metal view, a camera pipeline or a video editor is ordinary platform code with no bridge, written per platform. **Escape through the framework's bridge** — Flutter (a [`Texture`](https://api.flutter.dev/flutter/widgets/Texture-class.html) or a [platform view](https://docs.flutter.dev/platform-integration/ios/platform-views), which the docs say "come with performance trade-offs"), React Native (a [Fabric Native Component](https://reactnative.dev/docs/fabric-native-components-introduction) plus a Native Module), Compose Multiplatform on iOS (a [`UIKitView`](https://kotlinlang.org/docs/multiplatform/compose-uikit-integration.html) built in Kotlin through Objective-C interop, or in Swift for Swift-only APIs), .NET MAUI (a [handler](https://learn.microsoft.com/en-us/dotnet/maui/user-interface/handlers/customize) reaching the `PlatformView`), Ionic/Capacitor (a [plugin](https://capacitorjs.com/docs/ios/custom-code) whose native UI lives in its own view controller beside the web view): the island is written per platform anyway, plus the bridge that carries its parameters and results, and its logic leaves the shared implementation. **Drawn by the framework** — Flutter and Compose Multiplatform keep a drawing-heavy screen shared when it needs no platform API: GLSL shaders and painters in Dart, `Canvas` on Skia in Kotlin. The pairwise pages give each escape's mechanics; [Duet's side](/articles/duet-vs-flutter#what-if-one-screen-must-be-native-and-fast) is the same on all three: the reducer decides, a worker runs the pipeline, and the recorded seam is what CI compares.

Whether the island means writing and compiling native code, per framework: **Flutter, React Native and Ionic/Capacitor** — yes, in Swift or Objective-C(++) and Kotlin or Java, compiled by Xcode and Gradle in the app build, unless an existing plugin or library covers the island, which spares the writing and not the compiling. **Compose Multiplatform** — usually Kotlin only, because Kotlin/Native's [Objective-C interop](https://kotlinlang.org/docs/native-objc-interop.html) builds UIKit views from Kotlin, with Swift reserved for Swift-only APIs. **.NET MAUI** — platform-specific C# against the platform bindings, [compiled by .NET per platform](https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/invoke-platform-code); no Swift or Kotlin. **Skip** — Swift on iOS as usual, and on Android either Kotlin or Swift in `#if SKIP` blocks that transpile to Kotlin. **KMP shared-core stacks, two native apps and Duet** — yes, by design: Swift compiled by Xcode, Kotlin compiled by Gradle.

Whether the island can be SwiftUI or Jetpack Compose rather than UIKit and Android Views: for **Duet, two native apps, KMP shared-core stacks and Skip** they are the interface already. **Flutter and React Native** get them wrapped — a SwiftUI view through [`UIHostingController`](https://developer.apple.com/documentation/swiftui/uihostingcontroller), Compose through [`ComposeView`](https://developer.android.com/develop/ui/compose/migrate/interoperability-apis/compose-in-views) — inside a platform view or a Fabric Native Component; React Native's own guides mention Swift nowhere, while Expo, the framework its documentation recommends, adds Swift and Kotlin modules and [Expo UI](https://docs.expo.dev/versions/latest/sdk/ui/), "a set of components that allow you to build UIs directly with Jetpack Compose and SwiftUI from React". **Compose Multiplatform** is Compose on Android and takes SwiftUI on iOS through `UIHostingController` passed to `UIKitViewController`, written in Swift. **Ionic/Capacitor** gets them only as a native screen a plugin presents outside the web view. **.NET MAUI**'s handler surface is UIKit and Android Views through the .NET bindings.

## Is the shared-core shape new?

No. The bottom-left cell — platform draws, compiled shared core — is established practice under several names. Kotlin Multiplatform shared-logic practice is [officially supported by Google](https://developer.android.com/kotlin/multiplatform) and carries the mainstream case studies: Forbes (80%+ shared logic), McDonald's, Cash App (moved from shared JavaScript to KMP starting 2018), Google Docs on iOS, and 9GAG — which chose KMP after trying Flutter and React Native. The same shape exists with a Rust core: [Crux](https://github.com/redbadger/crux) captures effects as values executed by native shells — the same effects-as-data idea Duet uses — and Mozilla's [UniFFI](https://github.com/mozilla/uniffi-rs) and Signal's libsignal ship Rust cores under native apps at scale. One detail in JetBrains' own materials is worth reading as data: its shared-logic case-study list is long and mainstream, while its shared-UI list is short and recent — shared logic under native UI is the mainstream KMP shape.

What lacks close prior art is the verification layer: a recorded behavior corpus that both platforms replay, byte-compared in CI, as the *gate* for parity. The KMP and Rust stacks above share code and share tests; none of them ships a mechanism whose job is to fail the build when the two apps' behavior diverges. That layer — not the shared core — is Duet's contribution, and it is why the table gives Duet a different "what proves agreement" cell than the stacks it otherwise resembles.

## What does the table not score?

**App size.** Shipped runtimes have documented weight: Flutter's own FAQ measured a minimal release APK at \~4.3 MB (ARM32) / 4.8 MB (ARM64) and a minimal IPA download at \~10.9 MB — figures the FAQ dates to March 2021. Duet's compiled core measured +3 MB on the Android app of the shipped product Modaal's pages quote. React Native and Compose Multiplatform publish no equivalent official minimal-app figures, so this page quotes none.

**OS-release-day behavior.** A native interface inherits a new OS version's controls, behaviors and accessibility features on the OS's schedule. A framework-drawn interface adopts them when the framework does — Compose Multiplatform's FAQ presents the same fact from the other side, noting a canvas-drawn UI "will stay the same" across OS updates. Both readings are true: consistency for the canvas, currency for the native toolkit. Accessibility follows the same line — CMP maps its semantics to native iOS Accessibility Services (VoiceOver and Full Keyboard Access work; the mapping is maintained by the framework), while native toolkits get new platform accessibility features without a bridge.

**Hiring and team shape.** The runtime rows map to talent pools: JavaScript/TypeScript (React Native, Ionic) is the largest; Dart expertise is mostly Flutter expertise; Kotlin rows draw from the Android population; Skip and Duet's iOS half draw from the Swift population. No numbers here age well enough to print — match the row to the team you can actually staff.

**The iteration loop.** Hot reload is a real productivity difference: mature in Flutter (stable on the web target since 3.35), stable and default in Compose Multiplatform since 1.10.0. Compiled-core stacks, Duet included, iterate with per-platform previews and fast logic tests instead.

## Who owns each framework in 2026?

Ownership moved enough in the last two years that most comparison pages are out of date:

* **React Native** is governed by the **React Foundation** under the Linux Foundation (February 2026), with Amazon, Meta, Microsoft, Expo, Callstack and others as founding members. "Meta's framework" is no longer the governance story.
* **Flutter** remains Google-led, with **Canonical named lead maintainer of Flutter Desktop** (May 2026) — stewardship is widening rather than narrowing.
* **Compose Multiplatform** is JetBrains', extending Google's Jetpack Compose; the two companies co-anchor the Kotlin ecosystem.
* **Ionic** has operated under **OutSystems since November 2022**; Ionic 9 (August 2026) carries support commitments into 2027.
* **.NET MAUI** is Microsoft's, on .NET's LTS cadence (MAUI 10, November 2025). The precedent worth knowing when weighing any vendor framework: **Xamarin support ended May 1, 2024**, and its apps required migration.
* **Skip** became free and open source (MPL-2.0) in January 2026 and releases actively.
* **Duet** is Modaal's, open on GitHub with versioned contracts, in open beta.

## What do the usage surveys say?

Quote surveys with their year, because the traps are real. Stack Overflow's 2024 survey — the last edition with a cross-platform category — put Flutter at 9.4% and React Native at 8.4% of all respondents; **the 2025 survey dropped the category**, so any page citing a 2025 Stack Overflow cross-platform figure is miscited. JetBrains reports Kotlin Multiplatform usage among its developer-ecosystem respondents doubling from 7% (2024) to 18% (2025). The widely re-cited Statista cross-platform chart's latest data year is 2023 (Flutter 46%, React Native 35% of cross-platform developers) — current pages re-cite it as if fresh; it is not.

## How do AI coding agents change the choice?

Two properties matter, and they pull in different directions. Fluency: an agent has seen more JavaScript, React and Flutter than anything else, and one-language codebases are easy for it to move through. Verifiability: an agent compounds its own mistakes unless the project gives it mechanical gates, and this is where the frameworks now differ visibly. Compose Multiplatform 1.12.0 ships an experimental MCP server that lets an agent drive hot reloads, screenshot the app and inspect the semantic tree — agent-operable *UI tooling*. Duet's recorded corpus is agent-checkable *behavior gating*: a screen cannot wire to logic without a passing recording, and every push replays the corpus on both platforms — the argument in full is on [the testable-apps page](/articles/testable-android-apps#why-does-this-suit-ai-coding-agents). The [iOS architecture comparison](/articles/best-ios-app-architecture) scores the same axis across architectures rather than frameworks.

## Which should you pick?

* **Interface-heavy, brand-driven product; one team end to end:** Flutter — or Compose Multiplatform if the team is Kotlin-first.
* **Web engineering team; modest native-module needs:** React Native (start with Expo, per the project's own recommendation) — or Ionic if the product is close to a web app already.
* **An existing web app to repackage:** Ionic/Capacitor.
* **A .NET organization:** MAUI, with eyes open about the Xamarin precedent and the LTS calendar.
* **A Swift team that wants Android from its existing SwiftUI source:** Skip.
* **A Kotlin team that wants full control of its stack:** KMP with Decompose or MVIKotlin — you assemble the architecture and the test strategy yourself.
* **A rules-dense product that needs native UI on both platforms and provable behavior parity:** Duet — the pairwise pages ([vs Flutter](/articles/duet-vs-flutter), [vs React Native](/articles/duet-vs-react-native), [vs Compose Multiplatform](/articles/duet-vs-compose-multiplatform)) argue each match-up in full.
* **Two independent platform teams, by organizational design:** two native codebases, with manual QA priced in as the parity mechanism.

## Common questions

<AccordionGroup>
  <Accordion title="Which cross-platform framework has the best performance?" icon="gauge">
    This page prints no benchmark verdicts: the rendering models differ enough that microbenchmarks mislead, and the ranking pages that score "performance" cite each other rather than measurements. The structural facts that do hold: compiled rows carry no interpreter between your logic and the CPU; canvas renderers control their own frame pipeline; web views are bound by the browser engine. Measure your own workload if performance is the deciding axis.
  </Accordion>

  <Accordion title="Is cross-platform cheaper than native?" icon="coins">
    At launch, a single implementation is cheaper than two — that is arithmetic. Total cost depends on what the product needs later: per-platform code behind channels and modules, interface rework to fit platform expectations, and the QA budget for whatever the framework's parity answer is. The share-code page walks the cost side, including the measured \~40% dual-platform change premium in Duet's model — against a 100% baseline of doing everything twice.
  </Accordion>

  <Accordion title="Why isn't Xamarin in the table?" icon="clock-rotate-left">
    Xamarin's support ended May 1, 2024; .NET MAUI is its successor and holds the table column. Xamarin remains relevant only as the migration precedent quoted in the governance section.
  </Accordion>

  <Accordion title="What about PWAs — skipping the stores entirely?" icon="globe">
    A progressive web app is a real option for content-driven products and dodges this page's question entirely — no second codebase, no framework row. The trade is capability and distribution: store presence, platform APIs, background behavior and platform-native interface expectations. Teams that need those come back to this table; teams that do not can stop at the web.
  </Accordion>

  <Accordion title="Every list ranks Flutter and React Native first. Why doesn't this one rank at all?" icon="list-ol">
    Because the approaches do not compete on one axis. Flutter and React Native lead every adoption survey quoted above, and if popularity is your tiebreaker, that is data. This page's position is that the two grid questions and the parity question predict your costs better than a rank — and that the right column for a web team, a Kotlin team and a Swift team is simply a different column of the table.
  </Accordion>
</AccordionGroup>

<Note>
  Duet projects are scaffolded by [Modaal](https://modaal.dev) — [starting a Duet project](/articles/duet#starting-a-duet-project) walks through the two template cards.
</Note>

## Sources and further reading

* [Flutter FAQ](https://docs.flutter.dev/resources/faq) and [Impeller](https://docs.flutter.dev/perf/impeller) — rendering, app-size figures, governance
* [React Native documentation](https://reactnative.dev/docs/getting-started) and the [React Foundation announcement](https://www.linuxfoundation.org/press/linux-foundation-announces-the-launch-of-the-react-foundation)
* [Compose Multiplatform and Jetpack Compose](https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-multiplatform-and-jetpack-compose.html) and the [1.12.0 release post](https://blog.jetbrains.com/kotlin/2026/08/compose-multiplatform-1-12-0/)
* [Kotlin Multiplatform on developer.android.com](https://developer.android.com/kotlin/multiplatform) and [JetBrains' case studies](https://kotlinlang.org/case-studies/)
* [Ionic documentation](https://ionicframework.com/docs) and [Capacitor documentation](https://capacitorjs.com/docs)
* [.NET MAUI documentation](https://learn.microsoft.com/en-us/dotnet/maui/) and the [Xamarin support policy](https://learn.microsoft.com/en-us/lifecycle/products/xamarin)
* [Skip documentation](https://skip.tools/docs/) — the transpiled and natively compiled modes
* [Crux](https://github.com/redbadger/crux) and [UniFFI](https://github.com/mozilla/uniffi-rs) — the Rust-core prior art
* [Stack Overflow Developer Survey 2024](https://survey.stackoverflow.co/2024/technology) — the last edition with the cross-platform category
* Escape-to-native routes, per framework: Flutter [platform views](https://docs.flutter.dev/platform-integration/ios/platform-views) and [`Texture`](https://api.flutter.dev/flutter/widgets/Texture-class.html); React Native [Fabric Native Components](https://reactnative.dev/docs/fabric-native-components-introduction); JetBrains' [UIKit integration](https://kotlinlang.org/docs/multiplatform/compose-uikit-integration.html); .NET MAUI [handler customization](https://learn.microsoft.com/en-us/dotnet/maui/user-interface/handlers/customize); Capacitor [custom native code](https://capacitorjs.com/docs/ios/custom-code); Skip [cross-platform topics](https://skip.dev/docs/platformcustomization/)
* [Kotlin/Native interoperability with Swift/Objective-C](https://kotlinlang.org/docs/native-objc-interop.html), [.NET MAUI invoking platform code](https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/invoke-platform-code) and the [Capacitor workflow](https://capacitorjs.com/docs/basics/workflow) — which language the island is written in and what compiles it
* Apple's [`UIHostingController`](https://developer.apple.com/documentation/swiftui/uihostingcontroller), Android's [`ComposeView`](https://developer.android.com/develop/ui/compose/migrate/interoperability-apis/compose-in-views), [Expo Modules API](https://docs.expo.dev/modules/overview/) and [Expo UI](https://docs.expo.dev/versions/latest/sdk/ui/) — how SwiftUI and Compose enter a framework-drawn or React-driven screen
* [The Duet framework on GitHub](https://github.com/modaal-agent/duet) — both flavors, the recording toolchain and the versioned contracts

## Read next

<CardGroup cols={2}>
  <Card title="Duet vs Flutter" icon="code-compare" href="/articles/duet-vs-flutter">
    The canvas-and-runtime model against the native-UI shared-core model, in depth.
  </Card>

  <Card title="Duet vs React Native" icon="atom" href="/articles/duet-vs-react-native">
    Both draw native views — the comparison is where logic runs and what checks the boundary.
  </Card>

  <Card title="Duet vs Compose Multiplatform" icon="clone" href="/articles/duet-vs-compose-multiplatform">
    Same language decision, opposite UI decision — the nearest relative in the field.
  </Card>

  <Card title="The best iOS app architecture" icon="sitemap" href="/articles/best-ios-app-architecture">
    The same comparison discipline one level down: TCA, RIBs, VIPER, MVVM, MVC and Clean, scored.
  </Card>

  <Card title="Modaal alternatives" icon="newspaper" href="https://modaal.dev/alternatives">
    The same comparison one level up: the app builders, not the frameworks they emit, on modaal.dev.
  </Card>
</CardGroup>
