Your backend is C#. Your team is C#. Now the product needs a phone app, and three frameworks are waving: .NET MAUI, Flutter and React Native. Most comparisons are written by someone who loves one of them. This one is written by a .NET team that just shipped a MAUI app in public — twelve parts, three hosts, every dead end kept in — and is trying to be fair about the two roads not taken. Dated, as it must be: this is the picture as of September 2026.
The short answer: if your backend is C# and your screens are forms, lists, cards and status pages, .NET MAUI costs a .NET team the least in total, because it reuses the language, the data contracts, the tests, the CI and the people you already have. Flutter wins when the UI itself is the product — animation, pixel-level polish, a design that must be identical on every platform — or when you're hiring mobile specialists rather than retraining .NET ones. React Native wins when you already have a React web team, or when you need the largest third-party ecosystem and the most battle-tested consumer-scale track record. None of the three is a mistake; the mistake is choosing on the framework's merits instead of your team's.
What the three actually are
.NET MAUI is Microsoft's cross-platform UI framework for C#, the successor to Xamarin.Forms (whose support ended in 2024). One project targets Android, iOS, macOS and Windows. You build the UI either in XAML with native controls rendered per platform, or as Blazor Hybrid: your Razor components inside a WebView, with the C# running natively on the device. It ships and is versioned with .NET itself — the app in this story targets .NET 10 and MAUI 10.
Flutter is Google's toolkit, written in Dart, and its defining idea is that it draws every pixel itself with its own rendering engine rather than using the platform's controls. That's why a Flutter app looks identical on Android and iOS (and web, and desktop) and why its hot reload is so fast: there is no native view hierarchy to rebuild.
React Native is Meta's framework: JavaScript or TypeScript and React, rendering to real native views through a bridge that the "New Architecture" has made much faster. Expo is now the recommended way to start a project, and Microsoft itself maintains the Windows and macOS targets — a detail .NET teams tend not to know.
The comparison table
| .NET MAUI | Flutter | React Native | |
|---|---|---|---|
| Language | C#, same as the backend | Dart — a new language for the team | JavaScript / TypeScript |
| Reuse with a C# backend | Share DTOs, validation, client code and tests as projects | Regenerate from OpenAPI; validation written twice | Regenerate from OpenAPI; validation written twice |
| UI paradigm | Native controls (XAML) or your web UI in a WebView (Blazor Hybrid) | Draws everything itself; identical on every platform | Real native views driven from React |
| Tooling and hot reload | Visual Studio on Windows; VS Code or Rider elsewhere. Hot reload works, but is the weakest of the three (opinion) | The best hot reload in the business (widely held opinion); excellent CLI and DevTools | Fast Refresh; Expo's tooling is excellent; upgrades between versions are the sore spot (opinion) |
| Native feature access | Built-in C# APIs for the common device features; platform code in the same project | Plugins from pub.dev over platform channels | Expo modules and the community; native modules when needed |
| Performance and size | Native code; a real app's APK is tens of megabytes; cold start is the thing to watch | AOT-compiled Dart; smooth animation is its calling card | Hermes engine; excellent in practice at consumer scale |
| Hiring and community | Smallest mobile-specific pool — but you already employ C# developers | Large and growing pool; huge package ecosystem | The largest pool, drawn from the whole React world |
| Windows desktop | First-class | Supported | Supported, maintained by Microsoft |
| Risk | Microsoft's attention; a migration precedent (Xamarin.Forms) | Google's reputation for cancelling products; a 2024 layoff scare | JavaScript ecosystem churn; reliance on Expo for the good path |
| Wins when | C# team, forms-and-lists app, an existing Blazor product | UI is the product; hiring mobile specialists | React web team; ecosystem breadth; consumer scale |
Language and reuse: the part that's not opinion
This is where a C# backend tips the scales, and it's measurable. In ClinicLive Pocket the
phone and the server share a project called ClinicLive.Contracts whose project
file explains its own rule:
<!-- The wire contract between ClinicLive's public API and the Pocket app.
Deliberately tiny and dependency-free: the phone shares the SHAPE of the
data with the server, never the server's code. -->
Add a field to a DTO and both sides fail to compile until they agree. The typed API client, the SignalR client, the haversine that computes distance to the clinic and the parser for the QR ticket are all C#, tested by the same test project the server uses — 28 tests green at the end of the season, in one CI pipeline with three jobs. With Flutter or React Native you generate a client from an OpenAPI document (which works well), and then you write the validation rules a second time in Dart or TypeScript and keep them in sync by discipline. That's not a deal-breaker; teams do it every day. It's a tax, and a .NET team doesn't have to pay it.
There's a second reuse that only MAUI offers a Blazor shop: the screens themselves. If you already have Blazor components, Blazor Hybrid runs them inside the app, and the same Razor class library can also serve a browser. ClinicLive Pocket's five pages were written once and photographed on an Android emulator, a Windows window and Chrome — season three's Part 2 shows the pattern. If the render-mode side of that is unfamiliar, the sibling post Blazor Server vs WebAssembly vs Hybrid covers it.
UI paradigm: native, drawn, or web-in-a-view
Each framework makes a different bet about what a screen is. Flutter paints it — every button is Flutter's button, which is why Flutter apps are consistent and why they need Material and Cupertino widget sets to imitate each platform. React Native uses the platform's own views, so a switch on iOS is a real iOS switch. MAUI's XAML path does the same as React Native through per-platform handlers; MAUI's Blazor Hybrid path is the odd one out: it renders HTML in the platform's WebView, which is wonderful for reuse and honest about its limits. The retro's verdict on the app in this story: the screens were cheaper than cheap, and the edges cost what edges cost — insets CSS can't see, a status bar painted from Android XML rather than from tokens, a font choice that has to be the platform's own so the app doesn't feel like "a website in a trench coat."
Opinion, clearly labeled: for an app of forms, lists and one big number, users cannot tell the three paradigms apart. For an app whose product is motion — a camera-first experience, gesture-heavy interaction, a store listing that sells on feel — Flutter's drawn UI and React Native's native views both beat a WebView, and MAUI's XAML path is competitive but has the smallest library of ready-made polish.
Tooling and hot reload
Flutter's stateful hot reload is the feature every other framework is measured against, and that reputation is deserved. React Native's Fast Refresh is close, and Expo has turned project setup, device testing and even cloud builds for iOS into something a newcomer can do in an afternoon. MAUI's C# and XAML Hot Reload work, and they've improved every release, but in my experience they are the ones you'll occasionally restart the debugger for.
What a .NET team should weigh more than hot reload is the rest of the toolchain, because
that's where season three actually lost time. Not to the framework — to the edges around
it: a Windows build that failed with MSB3030 because the project path was
longer than MAX_PATH; a CI job that failed on
the name of a
workload (android versus maui-android); an AndroidX version
dance when Firebase joined the project. None of those were hard, but all of them were
MAUI-specific knowledge a Flutter or React Native developer never needs. Also worth
knowing: Visual Studio for Mac was retired in 2024, so a MAUI developer on a Mac works in
VS Code with the .NET MAUI extension or in Rider — a fine setup, but not the Visual Studio
experience a Windows teammate has.
Native feature access
All three reach the device; they differ in how much is in the box. MAUI ships C# APIs for the common features — device info, haptics, geolocation, connectivity, preferences, secure storage, notifications through small packages — and the pattern that made season three pleasant was wrapping each behind an interface the shared UI asks:
/// <summary>MAUI's answer: ask the device.</summary>
public sealed class PlatformInfo : IPlatformInfo
{
public string Platform => DeviceInfo.Platform.ToString();
public string Version => DeviceInfo.VersionString;
public bool IsPhone => DeviceInfo.Idiom == DeviceIdiom.Phone;
public string Host => "Native app";
}
Nine such interfaces carried the season: push via Firebase, a camera scanner via ZXing.Net.Maui, GPS and a directions intent, all in C#, with the platform-specific code living in the same project next to the platform it talks to. Flutter's equivalent is the plugin ecosystem on pub.dev — enormous, and the popular plugins are excellent — over platform channels to Kotlin and Swift. React Native has Expo's modules for the common cases and the community for everything else, with a native-module escape hatch. The honest finding from the retro is that the hard parts were the operating system's, not the framework's: Android's package-visibility rules, a force-stopped app that doesn't receive push, a Windows toast that needs a packaged identity. A Kotlin app meets the same rules. Whatever you pick, budget for the edges.
Performance and app size
I won't quote numbers I didn't measure. Here are the ones I did: ClinicLive Pocket's signed release APK is 33.8 MB, carrying a SignalR client, a barcode library and Firebase messaging; the self-contained Windows publish is 643 files and 235 MB, because it bundles the .NET runtime and the Windows App SDK; and adding the SignalR client took the Android cold start from about four seconds to about seven and a half (Part 4). Cold start, not frame rate, is where a MAUI app shows its cost; once running, the C# is native code and the UI is as fast as the WebView or the native controls underneath it.
Qualitatively: Flutter compiles Dart ahead of time and its rendering engine is built for 60-plus frames per second of custom animation; that's the thing it is famous for, and it is real. React Native with the Hermes engine and the New Architecture is fast enough that some of the most-used consumer apps on your phone run on it. If you need a number for your decision, build the hello-world of each with your real dependencies and measure size and cold start on a cheap phone — it takes a day and beats every benchmark blog.
Hiring and community
This is the row where MAUI is weakest on paper and where the paper misleads. Flutter and React Native have far larger mobile-specific communities, more tutorials, more packages, and more candidates whose résumé says "mobile." MAUI's community is smaller, and its Stack Overflow answers are sometimes still Xamarin-flavored. But a .NET team is not hiring into the mobile pool; it's asking its existing C# developers to build one more head for the same body. For that team, "can we hire for it" is already answered. The moment that changes — a dedicated mobile team, a consumer app that becomes the business — the larger pools matter, and Flutter or React Native become the safer hiring bet.
Risk: who's paying for the framework
Every framework here is owned by a giant with its own reasons. Microsoft ships MAUI on the yearly .NET cadence and has done so since 2022; the worry .NET teams voice is attention, because Microsoft ended Xamarin.Forms once already and MAUI's early releases were rough. It has matured since, and the fact that it is in .NET rather than beside it is its strongest guarantee. Google's risk is reputational: a round of layoffs in 2024 touched the Flutter and Dart teams and set off a public fork discussion, and the company's record with cancelled products makes people nervous — yet Flutter has kept shipping on schedule. Meta's React Native is load-bearing inside Meta's own apps, which is the best kind of insurance; its risk is the JavaScript ecosystem's pace, where upgrading a year-old project can be a project. Flag all of that as my reading, not a forecast.
When each one wins
- .NET MAUI — a C# team, a backend you already own, screens made of forms and lists, an existing Blazor product to share with, or a Windows desktop target that must be first-class. ClinicLive Pocket is this case exactly, and it took twelve parts and about $7.20 of model usage to build with AI assistance.
- Flutter — the UI is the product; you want one design pixel-identical on every platform; you're hiring mobile specialists; you value the best developer loop over language reuse.
- React Native — you have React people; you want the broadest ecosystem and Expo's paved road; you're building a consumer app at the scale where its track record matters most.
Honestly, it depends
Three caveats, because a decision post without them is a brochure. First, iOS needs a Mac for all three. Season three targeted iOS and the project compiles, but nothing was ever built or run on Apple hardware because there was no Mac on the bench — and Flutter or React Native would have hit the same wall. Cloud build services exist for every framework; budget for one.
Second, MAUI isn't the only C# option. Avalonia draws its own UI like Flutter does but in C#, and Uno Platform renders XAML across platforms including the web; neither is compared here because the team in this story never used them in anger, and comparing from the docs would be exactly the kind of post I promised not to write. Kotlin Multiplatform is worth a look if your Android developers are the ones who'll own the app.
Third, the honest limits of the MAUI app in this story are part of its evidence, not a footnote: Windows toasts never displayed because the app ships unpackaged; the emulator never rendered a QR poster, so on-device decoding is proven by a test instead of a photograph; and Google Maps crashed on the emulator after the app's part had worked. The retro lists all three and asks whether Hybrid was the right bet. Its answer — yes for this app, no for a camera-first one — is the same answer this post gives, one level up.
If you only remember one thing: the framework you already speak is worth more than the framework with the best demo. For a C# team building a C#-backed app of ordinary screens, MAUI's reuse beats Flutter's polish and React Native's ecosystem. When the app is the polish, or the team is the ecosystem, the answer flips.
Frequently asked
- Is .NET MAUI good enough for production in 2026?
- Yes, for the kind of app most business teams build: forms, lists, status screens and device features like push, location, camera and secure storage. ClinicLive Pocket shipped on Android and Windows as a signed release with CI in twelve documented parts. The caveats are real but ordinary: cold start needs attention, the Windows build needs a packaged identity for toasts, and iOS still needs a Mac to build.
- Should a C# team learn Flutter or React Native instead of using MAUI?
- Only if the app or the team calls for it. If the UI itself is the product, or you are hiring dedicated mobile specialists, Flutter and React Native have larger communities and a stronger polish story. If your backend is C# and the app is a companion to it, MAUI lets you share data contracts, validation, tests and even Blazor screens, which is usually the cheaper total for a .NET team.
- Can you build iOS apps with .NET MAUI on Windows?
- You can target iOS from a Windows project, but compiling, signing and running on Apple hardware requires a Mac, either on your desk, paired over the network, or rented from a cloud build service. That is Apple's rule and it applies equally to Flutter and React Native, so it should not decide between the three frameworks.
The MAUI side of this post is not hypothetical: From Prompt to Pocket builds ClinicLive's companion app part by part, with every prompt, every mistake and the meter. If your next decision is the database under the API the app calls, PostgreSQL vs SQL Server for .NET developers is the same kind of post for that choice.