← Back to Blog

Building Once, Deploying Everywhere: Lessons from .NET MAUI Hybrid Blazor

Hloriso N. Mohale
Hloriso N. Mohale 12 Aug 2026 · 7 min read

Every framework promises "write once, run anywhere." Most of them get you 70% of the way there and leave you to fight the remaining 30% alone, one platform-specific bug at a time. After shipping several production apps with .NET MAUI Hybrid Blazor - across web, Android, iOS, and Windows - I've settled on a shorter, more honest promise: build once, deploy everywhere, adapt where it actually matters.

Here's what that looked like in practice, and the lessons that would have saved me weeks if I'd known them going in.

1. Treat the shared UI layer as a contract, not a shortcut

Blazor Hybrid lets your Razor components run natively inside a MAUI shell, which means the same markup renders in a browser tab and inside a native WebView. That's the headline feature, and it's real. But it's tempting to treat "shared" as "identical," and that assumption breaks the first time you need a native file picker, a platform-specific permission prompt, or a share sheet.

The fix is architectural, not clever code: define your platform interactions as interfaces in the shared project, then implement them per platform using MAUI's dependency injection. The Razor components never know or care which platform they're running on - they just call the contract.

The apps that scale well are the ones where "platform-specific" means a small, well-labeled folder, not a scattering of #if conditionals through your business logic.

2. Startup performance is a first-class feature, not an afterthought

The WebView that hosts your Blazor components has to spin up before anything renders, and on lower-end Android devices that cold-start cost is noticeable. A few things moved the needle for us:

  • Trimming and AOT compilation where the target platform supports it, to cut both binary size and JIT overhead.
  • Lazy-loading feature modules instead of registering every service at startup.
  • Showing a native splash screen that hands off cleanly to the Blazor shell, rather than a blank white flash.

None of this is exotic. It's the same discipline you'd apply to any performance-sensitive product - it's just easy to skip when the framework makes the happy path so convenient.

3. Desktop is not "mobile with more screen space"

This was the lesson that cost us the most rework. Windows and macOS users expect resizable windows, keyboard shortcuts, right-click context menus, and layouts that use horizontal space intelligently. A mobile-first component tree, ported as-is to desktop, feels cramped and slightly wrong even when it technically works.

We ended up building a small set of responsive layout primitives - not a full design system, just enough to let the same component render as a bottom sheet on mobile and a side panel on desktop - driven by MAUI's device idiom detection rather than raw screen width.

4. State management decisions echo across every platform

Whatever state pattern you choose in the shared project, you're choosing it for web, mobile, and desktop simultaneously. That's a gift when it works and a liability when it doesn't. We standardised on a lightweight, testable state container rather than reaching for anything web-specific, precisely because it had to behave identically whether it was running in a browser tab or a native shell with a completely different lifecycle.

5. Test on real devices earlier than feels necessary

Emulators and the browser will lie to you about touch targets, font rendering, and memory pressure. Some of our sharpest bugs - a keyboard that covered an input field on a specific Android version, a WebView rendering quirk on an older iOS build - only ever showed up on physical hardware. Budgeting real-device testing from week one, not as a pre-release checklist item, paid for itself many times over.

The honest takeaway

.NET MAUI Hybrid Blazor delivers on the core promise: one codebase, one team, three platforms. But "cross-platform" doesn't mean "platform-agnostic everywhere." The teams that succeed with it are the ones who are deliberate about where they share and where they specialise, and who treat that boundary as a design decision rather than something the framework will figure out for them.

I go much deeper into these patterns - with full working examples - in Cross-Platform Powerhouse, if you want the long-form version of this argument.