Starter Architecture

Start with a packaged C# WinUI 3 app and one testable core library. Do not begin with modular architecture, custom installers, WebView2, or background features unless the product already needs them.

MyApp/
  MyApp.sln
  src/
    MyApp/
      App.xaml
      App.xaml.cs
      MainWindow.xaml
      MainWindow.xaml.cs
      Package.appxmanifest
      Services/
        AppSettings.cs
        NavigationService.cs
      Views/
        HomePage.xaml
        SettingsPage.xaml
      ViewModels/
        HomeViewModel.cs
        SettingsViewModel.cs
    MyApp.Core/
      Models/
      Services/
      Storage/
  tests/
    MyApp.Core.Tests/
    MyApp.WinUITests/

Responsibilities

AreaOwnsShould not own
App.xaml.csStartup, activation routing, top-level service wiringBusiness rules or direct UI details
MainWindowWindow creation, root navigation frame, title bar hooksData access or long-running jobs
ViewsXAML layout and control events forwarded to view modelsPackage/runtime decisions
View modelsUI state, commands, validation, service callsWindow.Current, direct HWND logic, platform bootstrap
Core libraryBusiness logic, parsing, storage abstractions, pure testsMicrosoft.UI.Xaml types
WinUI test appXAML/UI-thread tests using [UITestMethod]Pure business logic tests that can run faster in Core tests
Package manifestIdentity, capabilities, activation, file/protocol associationsSecrets or environment-specific config

Project File Shape

Keep version values fresh from official docs or the generated template. This is a shape, not a pinned version prescription:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net10.0-windows10.0.19041.0</TargetFramework>
    <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
    <UseWinUI>true</UseWinUI>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.WindowsAppSDK" Version="RECHECK_CURRENT_STABLE" />
  </ItemGroup>
</Project>

Gotcha: Do not copy this TargetFramework or package version blindly. The official quickstart and generated templates are the authority at implementation time.

Minimal Service Wiring

Manual wiring is enough for v1:

public sealed class AppServices
{
    public AppServices()
    {
        Settings = new AppSettings();
        Navigation = new NavigationService();
    }

    public AppSettings Settings { get; }
    public NavigationService Navigation { get; }
}

Move to a dependency injection container only when construction becomes repetitive or tests need too many manual replacements.

Windows Integration Boundaries

FeatureStarter stance
SettingsUse packaged app storage or a small settings service; do not assume unpackaged storage behavior
NotificationsAdd only when the app has a concrete notification scenario and manifest activation plan
WindowingCentralize AppWindow and HWND interop in one service
WebView2Keep optional; isolate navigation policy and user data folder choices
Background workDo not port UWP IBackgroundTask; use Windows App SDK lifecycle/activation patterns or a separate service model
StoreKeep manifest identity clean from day one, even before submission

What To Exclude From V1

  • Custom installer.
  • Sparse package.
  • Self-contained runtime output.
  • WebView2 unless web content is core to the product.
  • Full MVVM framework unless the app already has enough screens to justify it.
  • Multi-project modularization beyond one UI project and one core/testable library.