Covers Blazor across supported .NET versions (8, 9, and 10): render modes (Static SSR, Interactive Server, Interactive WebAssembly, Interactive Auto), Razor components and lifecycle, dependency injection per render mode, SignalR circuit management, WebAssembly runtime (AOT, trimming, lazy loading), Blazor Hybrid (MAUI, WPF, WinForms), enhanced navigation, state management (scoped services, PersistentComponentState, cascading parameters), JS interop (IJSRuntime, module isolation), authenticati...
Pro scans all 12 files and shows the line behind each finding
Scanned 9/24/2026
npx -y skills add chrishuffman5/domain-expert --skill blazor --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Blazor?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/chrishuffman5-blazor)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: blazor
description: "Covers Blazor across supported .NET versions (8, 9, and 10): render modes (Static SSR, Interactive Server, Interactive WebAssembly, Interactive Auto), Razor components and lifecycle, dependency injection per render mode, SignalR circuit management, WebAssembly runtime (AOT, trimming, lazy loading), Blazor Hybrid (MAUI, WPF, WinForms), enhanced navigation, state management (scoped services, PersistentComponentState, cascading parameters), JS interop (IJSRuntime, module isolation), authentication patterns, and performance optimization. Use for \"Blazor\", \"blazor\", \"Razor component\", \"render mode\", \"Interactive Server\", \"Interactive WebAssembly\", \"Blazor WASM\", \"SignalR Blazor\", \".NET Blazor\", \"Blazor Hybrid\", \"MudBlazor\" questions."
license: MIT
---
# Blazor
This skill covers Blazor across all supported .NET versions (8, 9, and 10), including:
- Render modes: Static SSR, Interactive Server, Interactive WebAssembly, Interactive Auto
- Razor components: file structure, parameters, event handling, lifecycle hooks, cascading parameters
- Dependency injection: scoped vs singleton vs transient, lifetime differences per render mode
- SignalR for Interactive Server: circuits, reconnection, sticky sessions, backplane
- WebAssembly runtime: IL interpretation, AOT compilation, trimming, lazy loading, PWA support
- Blazor Hybrid: MAUI, WPF, WinForms via BlazorWebView
- Enhanced navigation and form handling (Static SSR interactivity without JS frameworks)
- State management: scoped services, PersistentComponentState, `[PersistentState]`, cascading values, browser storage via JS interop
- JS interop: IJSRuntime, IJSInProcessRuntime (WASM only), module isolation, DotNetObjectReference
- Authentication: CascadingAuthenticationState, AuthorizeView, per-render-mode auth patterns
- Performance: AOT, IL trimming, virtualization, lazy loading assemblies, compression, ShouldRender
- Component libraries: MudBlazor, Radzen, Syncfusion, Fluent UI Blazor
When a question is version-specific, read the matching file under `references/versions/`. When the version is unknown, give general guidance and note where behavior differs across versions.
## How to Approach Tasks
When you receive a request:
1. **Classify** the request type:
- **Troubleshooting** -- Load `references/diagnostics.md`
- **Performance** -- Load `references/best-practices.md` (performance section)
- **Architecture / Design** -- Load `references/architecture.md`
- **Render mode selection** -- Load `references/patterns/render-modes.md`
- **State management** -- Load `references/patterns/state-management.md`
- **JS interop** -- Load `references/patterns/js-interop.md`
- **Configuration** -- Reference `assets/Program.cs` or `assets/csproj-reference.xml`
2. **Identify version** -- Determine whether the user is on .NET 8, 9, or 10. If unclear, ask. Version matters for constructor injection (9+), `[PersistentState]` (10), RendererInfo (9+), and circuit persistence (10).
3. **Load context** -- Read the relevant reference file for deep knowledge.
4. **Analyze** -- Apply Blazor-specific reasoning, not generic ASP.NET advice. Consider the render mode, component lifecycle, SignalR circuit behavior, and DI lifetime semantics.
5. **Recommend** -- Provide actionable guidance with code examples. Prefer idiomatic Blazor patterns.
6. **Verify** -- Suggest validation steps (browser DevTools, `dotnet-trace`, SignalR logging).
## Core Expertise
### Render Modes
Blazor Web App (.NET 8+) unifies all rendering strategies. Each component or page opts into a render mode independently.
| Mode | Directive | Location | Interactivity |
|---|---|---|---|
| Static SSR | _(default)_ | Server, HTML streamed | None -- plain HTML |
| Interactive Server | `@rendermode InteractiveServer` | Server via SignalR | Full, real-time |
| Interactive WebAssembly | `@rendermode InteractiveWebAssembly` | Browser (.NET WASM) | Full, client-side |
| Interactive Auto | `@rendermode InteractiveAuto` | Server first, then WASM | Full, progressive |
Static SSR is the default. No `@rendermode` directive needed. No persistent connection. Fastest initial load and smallest payload. Use `<form>` with Enhanced Form Handling for interactivity.
Interactive Server runs inside a circuit -- a dedicated SignalR connection per user session. UI events round-trip to server; DOM diffs stream back as binary patches. Full access to server resources without CORS.
Interactive WebAssembly downloads the .NET runtime and app assemblies to the browser. After initial download, no server connection required for UI interactions. Must call APIs for server resources.
Interactive Auto renders as Interactive Server on first visit while WASM assets download in background. Subsequent visits use WASM from cache.
```razor
@* Per-page render mode *@
@page "/dashboard"
@rendermode InteractiveServer
@* Per-component render mode at usage site *@
<MyChart @rendermode="InteractiveWebAssembly" />
@* Disable prerendering *@
<MyChart @rendermode="new InteractiveServerRenderMode(prerender: false)" />
```
Prerendering is enabled by default. `OnInitializedAsync` runs twice -- once during prerender, once after hydration. Use `PersistentComponentState` to carry prerender data forward.
### Razor Components
Components are `.razor` files combining markup and C# logic. They accept parameters, emit events, and follow a defined lifecycle.
```razor
@page "/counter"
@rendermode InteractiveServer
<h1>Count: @currentCount</h1>
<button @onclick="Increment">+1</button>
@code {
private int currentCount = 0;
[Parameter] public int InitialValue { get; set; } = 0;
[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public EventCallback<int> OnChange { get; set; }
protected override void OnInitialized() => currentCount = InitialValue;
private void Increment() => currentCount++;
}
```
Lifecycle: `SetParametersAsync` > `OnInitialized(Async)` > `OnParametersSet(Async)` > `ShouldRender` > `OnAfterRender(Async)` > `Dispose(Async)`.
JS interop is only safe in `OnAfterRenderAsync` (DOM is ready). Use the `firstRender` flag.
### Dependency Injection
```csharp
builder.Services.AddScoped<IUserService, UserService>(); // per-circuit (Server) / per-session (WASM)
builder.Services.AddSingleton<IConfigService, ConfigService>(); // app lifetime
builder.Services.AddTransient<IEmailSender, SmtpEmailSender>(); // new instance every time
```
Scoped lifetime differs by render mode: per-circuit in Interactive Server, effectively singleton in WASM, per-request in Static SSR.
```razor
@inject IUserService UserService
@inject NavigationManager Nav
@inject IJSRuntime JS
```
Constructor injection available in .NET 9+. Never inject Scoped into Singleton. `HttpContext` is not available in interactive components -- use `AuthenticationStateProvider` instead.
### SignalR and Circuits
Each Interactive Server user gets a circuit -- an in-memory object graph holding all component state. 1000 concurrent users = 1000 circuits. Plan memory accordingly.
Sticky sessions are required for multi-server deployments. Use Azure SignalR Service or Redis backplane for scale-out.
### WebAssembly Runtime
Baseline WASM download is ~2 MB compressed. Typical app: ~4-6 MB. IL trimming reduces by 30-50%. AOT compilation increases download but provides 2-5x runtime speed improvement.
### JS Interop
```csharp
// Call JS from .NET
await JS.InvokeVoidAsync("console.log", "Hello from Blazor");
// Module isolation (recommended)
_module = await JS.InvokeAsync<IJSObjectReference>("import", "./js/myComponent.js");
await _module.InvokeVoidAsync("init", elementRef);
```
Always dispose `IJSObjectReference` and `DotNetObjectReference`. Use module isolation to avoid global namespace pollution.
## Common Pitfalls
**1. State loss during prerender-to-interactive transition**
Data fetched during prerender disappears when the component goes interactive. Use `PersistentComponentState` (.NET 8/9) or `[PersistentState]` (.NET 10) to persist and restore.
**2. OnInitializedAsync runs twice**
Once during prerender, once after hydration. Guard expensive operations: fetch only if data is null. Use `PersistentComponentState` for the handoff.
**3. Dispatcher exceptions from background threads**
Mutating component state from a non-Blazor thread throws `InvalidOperationException`. Wrap with `await InvokeAsync(StateHasChanged)`.
**4. HttpContext in interactive components**
`HttpContext` is only available during Static SSR prerender. In interactive modes, use `AuthenticationStateProvider` and `NavigationManager`.
**5. Scoped service lifetime confusion**
In WASM, scoped services are effectively singletons. In Server, they are per-circuit. Design services with this in mind.
**6. WASM download size surprises**
Enabling AOT increases download to 8-15 MB. Always test with production builds. Use lazy loading for large assemblies.
**7. Interactive child in static parent**
A child component cannot upgrade itself to a more interactive mode than its parent. The `@rendermode` at the usage site controls the render mode.
**8. Missing SignalR sticky sessions**
Without sticky sessions, reconnecting clients hit a different server that has no circuit. Configure load balancer affinity (ARR cookie on Azure, ip_hash on NGINX).
**9. Large render batches over SignalR**
Complex UIs with thousands of DOM elements create large SignalR messages. Use virtualization and pagination.
**10. Forgetting to dispose JS interop references**
`DotNetObjectReference` and `IJSObjectReference` are GC roots. Failing to dispose causes memory leaks.
## Version-Specific Guidance
| Version | Reference | What's version-specific |
|---|---|---|
| .NET 8 | `references/versions/dotnet-8.md` | Render mode system, streaming SSR, QuickGrid, enhanced navigation, sections, per-component granularity |
| .NET 9 | `references/versions/dotnet-9.md` | Constructor injection, RendererInfo API, WebSocket compression, MapStaticAssets, simplified auth serialization |
| .NET 10 | `references/versions/dotnet-10.md` | `[PersistentState]` attribute, circuit state persistence, ReconnectModal, 76% smaller JS bundle, passkeys, new JS interop methods, NavigationManager.NotFound() |
## Reference Files
Load these when you need deep knowledge for a specific area:
- `references/architecture.md` -- Render modes, Razor components, DI, SignalR, WASM, Hybrid, enhanced navigation. Read for "how does X work" questions.
- `references/best-practices.md` -- Mode selection, state management, JS interop patterns, performance, authentication. Read for design and quality questions.
- `references/diagnostics.md` -- Connection issues, WASM download debugging, render mode conflicts, state loss. Read when troubleshooting errors.
## Configuration References
- `assets/Program.cs` -- Annotated Blazor Web App startup configuration
- `assets/csproj-reference.xml` -- Project settings for trimming, AOT, compression, lazy loading
## Pattern Guides
- `references/patterns/render-modes.md` -- Decision tree for render mode selection, per-component configuration, tradeoff matrix
- `references/patterns/state-management.md` -- Scoped services, PersistentComponentState, cascading values, browser storage
- `references/patterns/js-interop.md` -- IJSRuntime, module isolation, DotNetObjectReference, synchronous WASM interop
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!