$npx -y skills add wshaddix/dotnet-skills --skill dotnet-blazor-patternsBuilding Blazor apps. Hosting models, render modes, routing, streaming rendering, prerender.
| 1 | # dotnet-blazor-patterns |
| 2 | |
| 3 | Blazor hosting models, render modes, project setup, routing, enhanced navigation, streaming rendering, and AOT-safe patterns. Covers all five hosting models (InteractiveServer, InteractiveWebAssembly, InteractiveAuto, Static SSR, Hybrid) with trade-off analysis for each. |
| 4 | |
| 5 | **Scope boundary:** This skill owns Blazor project setup, hosting model selection, render mode configuration, routing, enhanced navigation, streaming rendering, and AOT-safe patterns. Component architecture (lifecycle, state management, JS interop, EditForm) is owned by [skill:dotnet-blazor-components]. Authentication across hosting models is owned by [skill:dotnet-blazor-auth]. |
| 6 | |
| 7 | **Out of scope:** bUnit component testing -- see [skill:dotnet-blazor-testing]. Standalone SignalR patterns -- see [skill:dotnet-realtime-communication]. Browser-based E2E testing -- see [skill:dotnet-playwright]. UI framework selection decision tree -- see [skill:dotnet-ui-chooser]. |
| 8 | |
| 9 | Cross-references: [skill:dotnet-blazor-components] for component architecture, [skill:dotnet-blazor-auth] for authentication, [skill:dotnet-blazor-testing] for bUnit testing, [skill:dotnet-realtime-communication] for standalone SignalR, [skill:dotnet-playwright] for E2E testing, [skill:dotnet-ui-chooser] for framework selection, [skill:dotnet-accessibility] for accessibility patterns (ARIA, keyboard nav, screen readers). |
| 10 | |
| 11 | --- |
| 12 | |
| 13 | ## Hosting Models & Render Modes |
| 14 | |
| 15 | Blazor Web App (.NET 8+) is the default project template, replacing the separate Blazor Server and Blazor WebAssembly templates. Render modes can be set globally, per-page, or per-component. |
| 16 | |
| 17 | ### Render Mode Overview |
| 18 | |
| 19 | | Render Mode | Attribute | Interactivity | Connection | Best For | |
| 20 | |---|---|---|---|---| |
| 21 | | Static SSR | (none / default) | None -- server renders HTML, no interactivity | HTTP request only | Content pages, SEO, forms with minimal interactivity | |
| 22 | | InteractiveServer | `@rendermode InteractiveServer` | Full | SignalR circuit | Low-latency interactivity, full server access, small user base | |
| 23 | | InteractiveWebAssembly | `@rendermode InteractiveWebAssembly` | Full (after download) | None (runs in browser) | Offline-capable, large user base, reduced server load | |
| 24 | | InteractiveAuto | `@rendermode InteractiveAuto` | Full | SignalR initially, then WASM | Best of both -- immediate interactivity, eventual client-side | |
| 25 | | Blazor Hybrid | `BlazorWebView` in MAUI/WPF/WinForms | Full (native) | None (runs in-process) | Desktop/mobile apps with web UI, native API access | |
| 26 | |
| 27 | ### Per-Mode Trade-offs |
| 28 | |
| 29 | | Concern | Static SSR | InteractiveServer | InteractiveWebAssembly | InteractiveAuto | Hybrid | |
| 30 | |---|---|---|---|---|---| |
| 31 | | First load | Fast | Fast | Slow (WASM download) | Fast (Server first) | Instant (local) | |
| 32 | | Server resources | Minimal | Per-user circuit | None after download | Circuit then none | None | |
| 33 | | Offline support | No | No | Yes | Partial | Yes | |
| 34 | | Full .NET API access | Yes (server) | Yes (server) | Limited (browser sandbox) | Varies by phase | Yes (native) | |
| 35 | | Scalability | High | Limited by circuits | High | High (after WASM) | N/A (local) | |
| 36 | | SEO | Yes | Prerender | Prerender | Prerender | N/A | |
| 37 | |
| 38 | ### Setting Render Modes |
| 39 | |
| 40 | **Global (App.razor):** |
| 41 | |
| 42 | ```razor |
| 43 | <!-- Sets default render mode for all pages --> |
| 44 | <Routes @rendermode="InteractiveServer" /> |
| 45 | ``` |
| 46 | |
| 47 | **Per-page:** |
| 48 | |
| 49 | ```razor |
| 50 | @page "/dashboard" |
| 51 | @rendermode InteractiveServer |
| 52 | |
| 53 | <h1>Dashboard</h1> |
| 54 | ``` |
| 55 | |
| 56 | **Per-component:** |
| 57 | |
| 58 | ```razor |
| 59 | <Counter @rendermode="InteractiveWebAssembly" /> |
| 60 | ``` |
| 61 | |
| 62 | **Gotcha:** Without an explicit render mode boundary, a child component cannot request a more interactive render mode than its parent. However, interactive islands are supported: you can place an `@rendermode` attribute on a component embedded in a Static SSR page to create a render mode boundary, enabling interactive children under otherwise static content. |
| 63 | |
| 64 | --- |
| 65 | |
| 66 | ## Project Setup |
| 67 | |
| 68 | ### Blazor Web App (Default Template) |
| 69 | |
| 70 | ```bash |
| 71 | # Creates a Blazor Web App with InteractiveServer render mode |
| 72 | dotnet new blazor -n MyApp |
| 73 | |
| 74 | # With specific interactivity options |
| 75 | dotnet new blazor -n MyApp --interactivity Auto # InteractiveAuto |
| 76 | dotnet new blazor -n MyApp --interactivity WebAssembly # InteractiveWebAssembly |
| 77 | dotnet new blazor -n MyApp --interactivity Server # InteractiveServer (default) |
| 78 | dotnet new blazor -n MyApp --interactivity None # Static SSR only |
| 79 | ``` |
| 80 | |
| 81 | ### Blazor Web App Project Structure |
| 82 | |
| 83 | ``` |
| 84 | MyApp/ |
| 85 | MyApp/ # Server project |
| 86 | Program.cs # Host builder, services, middleware |
| 87 | Components/ |
| 88 | App.razor # Root component (sets global render mode) |
| 89 | Routes.razor # Router component |
| 90 | Layout/ |
| 91 | MainLayout.razor # Main layout |
| 92 | Pages/ |
| 93 | Home.razor # Static SSR by default |
| 94 | Counter.razor # Can set per-page render mode |