Developer planning .NET MAUI cross-platform app architecture at a laptop

The pitch for .NET MAUI sounds almost too good: one C# codebase, four platforms, native performance. Every experienced developer has been burned by a framework that overpromised and underdelivered — so let's skip the marketing slide and get into the actual mechanics.

I've shipped MAUI apps that run on iOS, Android, Windows, and macOS. The "60% time savings" claim is real — but only under specific conditions. Here's what those conditions are, and how to engineer your project to meet them.

What the "60% Time Savings" Actually Means

The 60% figure isn't a marketing number pulled from thin air. It reflects a real phenomenon: when you build well-structured MAUI apps, you genuinely share 80–95% of your codebase across platforms. The savings come from not writing — and not maintaining — four separate implementations of the same logic.

But the key word is well-structured. Poorly structured MAUI projects can achieve as little as 50–60% code sharing, which narrows the advantage significantly. The teams who see the largest gains are the ones who know exactly what to centralise and what to leave platform-specific.

What You Can (and Can't) Share Across Platforms

Being honest about this upfront is what separates efficient MAUI projects from frustrated ones.

You can share almost everything in the business layer:

  • All business logic, validation rules, and data transformations
  • ViewModels and all MVVM plumbing
  • Service layer: API clients, repositories, caching logic
  • Navigation logic (Shell routes)
  • Most UI — pages, layouts, controls defined in XAML
  • Resource files: strings, colours, styles, fonts

What typically needs platform-specific treatment:

  • Custom native UI controls (anything that needs to reach down to UIKit, Jetpack Compose, or WinUI)
  • Push notification registration (APNs vs. FCM vs. WNS differ)
  • Platform-specific permissions flows (iOS camera access request UX is different from Android)
  • Hardware APIs: biometrics, barcode cameras, NFC, background location
  • App Store-specific requirements: in-app purchase, review prompts

How to Structure a MAUI Project for Maximum Code Reuse

The project structure is where most teams either compound or resolve their problems. Here's the folder layout that works well for medium-to-large MAUI apps:

MyApp/ ├── Platforms/ │ ├── Android/ ← Android-specific code only │ ├── iOS/ ← iOS-specific code only │ ├── Windows/ ← Windows-specific code only │ └── MacCatalyst/ ├── Features/ ← Feature-first organisation │ ├── Dashboard/ │ │ ├── DashboardPage.xaml │ │ └── DashboardViewModel.cs │ ├── Profile/ │ └── Orders/ ├── Services/ ← Shared abstractions + implementations │ ├── Interfaces/ │ └── Implementations/ ├── Models/ ← Shared data models ├── Resources/ ← Fonts, images, styles, strings └── MauiProgram.cs ← DI registration + app setup

The key principle: everything under Features/ and Services/ is purely shared code. Platform-specific code lives only in Platforms/. When developers know which folder to open for which kind of problem, the cognitive load drops significantly.

CommunityToolkit.Mvvm — Your Biggest Productivity Booster

If there's one NuGet package that pays for itself in the first hour, it's CommunityToolkit.Mvvm. It uses C# source generators to eliminate most of the MVVM boilerplate that would otherwise bloat your ViewModels.

Instead of writing INotifyPropertyChanged implementations by hand and wiring up ICommand objects manually, you annotate properties with [ObservableProperty] and methods with [RelayCommand]. The source generator handles the rest at compile time — zero runtime reflection, full IDE support, and ViewModels that are half the lines of code.

// Before: ~40 lines of boilerplate for one property + command // After: clean, readable, maintainable [ObservableProperty] private string _userName = string.Empty; [RelayCommand] private async Task LoadProfileAsync() { UserName = await _profileService.GetNameAsync(); }

How to Handle Platform-Specific Code Without Spaghetti

Even in a well-shared codebase, you'll need platform-specific behaviour. The clean way to handle this is through interfaces and partial classes — not #if ANDROID directives scattered through shared code.

The pattern: define an interface in shared code, implement it in each Platforms/ folder, and register via DI in MauiProgram.cs.

The Rule of Thumb

If you catch yourself writing #if ANDROID or #if IOS in a shared service or ViewModel, stop and extract an interface instead. Those directives in shared code are the leading cause of "why is the Android build behaving differently from iOS" bugs six months later.

Performance Strategies That Actually Matter

MAUI performance is good by default — but these patterns separate fast apps from sluggish ones on lower-end devices:

Compiled Bindings

Add x:DataType to your XAML data templates. This enables compile-time binding validation and eliminates reflection-based binding resolution at runtime. On a list page with 50+ items, this is a measurable frame-rate improvement.

CollectionView over ListView

Always use CollectionView for scrollable lists — never ListView. CollectionView uses native recycling mechanisms and supports both vertical and horizontal layouts. On Android, the difference in scroll performance is especially noticeable.

Shell Lazy Loading

Register pages as lazy in Shell so they're not initialised until the user navigates to them. For apps with 20+ screens, this dramatically improves cold start time.

Image Optimisation

Use SVG files for icons (MAUI resizes them at build time for each platform's density requirements). For photos, provide density-qualified images in the Resources/Images folder and let the build system handle the rest.

What Senior MAUI Teams Do Differently

After working with a dozen MAUI teams across different companies, the patterns that distinguish high-output teams are consistently the same:

  • They define their service interfaces before writing any XAML. The architecture drives the UI, not the other way around. This prevents the tangled ViewModels that make cross-platform inconsistencies hard to track down.
  • They write unit tests for ViewModels and services from day one. Because ViewModels are pure C# with no platform dependencies, they're trivially testable — and the tests catch regressions that only appear on one platform.
  • They instrument crash reporting early. App Center (now rebranding into Visual Studio App Center) on both iOS and Android from the first internal build. You want to know about crashes before they reach users, not after.
  • They resist feature creep during the architecture phase. The first sprint is always project setup, CI/CD, and one end-to-end flow working on all four platforms. Once the pipeline is proven, velocity accelerates.

"The apps we're most proud of aren't the ones with the most features — they're the ones where the shared codebase stayed clean for two years and adding a new platform took days, not months."

If your team needs a senior MAUI engineer who's already made these architectural decisions in production apps — not just read about them — let's talk about what you're building.

Alex M.
Alex M.
Senior .NET MAUI Developer · 7 Years Experience

Alex has architected and shipped 14 production MAUI and Xamarin apps across healthcare, logistics, and fintech. He contributes to the .NET MAUI open-source project on GitHub and speaks at regional .NET meetups about cross-platform architecture patterns.