Application development

One codebase, four platforms.

Web, desktop, iOS and Android from one component library and one team. The pitch has been around for decades, and in this stack it is mostly true. What the pitch usually omits is the tradeoff. This page names it.

We build applications on .NET and Blazor. One shared component library holds the screens and the rules. Each platform supplies a host that renders it: a web server for the browser, .NET MAUI for the installed apps. That is four platforms across five render contexts, because the browser is served two ways, which the technology page walks through. When the work is done you receive the source, the pipeline that deploys it, and the board that recorded every decision.

The tradeoff

Cheaper to change. Harder to make feel native.

A shared codebase bends the whole project toward a lower cost of change. Fix a business rule once and it is fixed on every screen. Add a feature and it is one branch, one review, one deployment, not four of each. One team holds the whole system in its head.

The cost lands on feel. The screens are shared components, not platform controls. An iPhone user knows what an iOS app feels like: the scroll physics, the transitions, the way the keyboard behaves. A shared UI gets close with deliberate work, and the work is real and belongs in the budget, but close is the honest ceiling. Anyone who tells you the gap is zero has not shipped one.

And there are applications where the trade is wrong. A consumer app competing on polish against rivals built natively for each platform. Anything that leans hard on device graphics or platform-specific hardware. An app that will only ever run on one platform, where sharing buys nothing and still costs feel. If your project is one of those, we will say so in the first conversation, because building it shared would spend your money proving our point instead of yours.

The mechanics

What one codebase actually means.

Not a cross-compiler. Not a generator that emits four projects you then maintain separately. One library of Razor components holds every screen and every rule, and each platform provides a host that renders that library. The component a dispatcher sees in a browser is the same component, the same file, that renders on a phone at the loading dock. Change it once and every surface changes.

Browser

Served by ASP.NET Core. Pages render on the server first, so the first paint arrives fast, then run interactively in the browser, with WebAssembly carrying the load where that serves the user. Nothing to install. This is where most users meet the system.

Windows desktop

An installed Windows application built with .NET MAUI. The shared components render inside WebView2, the same engine that drives Microsoft Edge, with full .NET access to the machine: file system, notifications, hardware.

iOS

An app built with .NET MAUI, distributed the way iOS apps are distributed. The shared components render inside WKWebView, Apple's web engine. Same screens, different engine, which is exactly why this surface gets its own testing.

Android

An app built with .NET MAUI, rendering the shared components in the Android system WebView. Device capabilities such as the camera and notifications arrive through .NET APIs instead of a second codebase.

What it does not buy

One codebase is not free parity.

The surfaces render the same components with three different web engines: Chromium in the browser and on Windows, WKWebView on iOS, the system WebView on Android. Engines disagree. A layout that is correct in Chromium can clip in WKWebView. A component that is interactive on the web can render as dead markup inside an app host if it is wired carelessly. These are known failure classes, and known failure classes have tests.

So each surface is treated as its own surface, tested rather than assumed, because a component that works is a claim and a test that passes is a record. The estimate for a four-surface application includes four surfaces' worth of verification. We put that in the number up front rather than let you find it mid-project.

The sales line is "write once, run anywhere." The true version is shorter and less catchy: write once, test everywhere. We budget for the true version.

The worked example

We run this architecture on our own product.

MyEventBingo is ours, built and operated by this firm. One shared component library serves the browser and the installed apps on Windows, iOS, and Android, with live state pushed to every connected screen over SignalR and the record kept in Azure SQL. It is the architecture on this page, running in public, and we wrote up how it is built: the ordering, the real-time contract, and the parts that were hard.

The handover

Delivered with the source and the pipeline.

An application you cannot deploy without us is a lease, not an asset. Every engagement here ends the same way: you hold the repository, the Azure DevOps board that tracked every change, and the pipeline that builds and deploys each surface. If you never call us again, the system still builds. That is what owning it means.

If you are weighing one codebase against per-platform builds, describe the application in a paragraph. We will tell you honestly which side of the tradeoff it falls on, including the answer that sends you somewhere else.