# Blazor

> Build and review Blazor applications across server, WebAssembly, web app, and hybrid scenarios with correct component design, state flow, rendering, and hosting choices. USE FOR: building interactive web UIs with C# instead of JavaScript; choosing between Server, WebAssembly, or Auto render modes; designing component hierarchies and state. DO NOT USE FOR: unrelated stacks; generic tasks that do n…

- **Type:** Skill
- **Install:** `agentstack add skill-managedcode-dotnet-skills-blazor`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [managedcode](https://agentstack.voostack.com/s/managedcode)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [managedcode](https://github.com/managedcode)
- **Source:** https://github.com/managedcode/dotnet-skills/tree/main/catalog/Frameworks/Blazor/skills/blazor
- **Website:** https://skills.managed-code.com

## Install

```sh
agentstack add skill-managedcode-dotnet-skills-blazor
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Blazor

## Trigger On

- building interactive web UIs with C# instead of JavaScript
- choosing between Server, WebAssembly, or Auto render modes
- designing component hierarchies and state management
- handling prerendering and hydration
- integrating with JavaScript when necessary

## Documentation

- [Blazor Overview](https://learn.microsoft.com/en-us/aspnet/core/blazor/?view=aspnetcore-10.0)
- [Render Modes](https://learn.microsoft.com/en-us/aspnet/core/blazor/components/render-modes?view=aspnetcore-10.0)
- [Performance Best Practices](https://learn.microsoft.com/en-us/aspnet/core/blazor/performance?view=aspnetcore-10.0)
- [State Management](https://learn.microsoft.com/en-us/aspnet/core/blazor/state-management?view=aspnetcore-10.0)
- [JS Interop](https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/?view=aspnetcore-10.0)

### References

- [patterns.md](references/patterns.md) - Detailed component patterns, state management strategies, and JS interop techniques
- [anti-patterns.md](references/anti-patterns.md) - Common Blazor mistakes and how to avoid them

## Render Modes (.NET 8+)

| Mode | Where It Runs | Best For |
|------|---------------|----------|
| `Static` | Server (no interactivity) | SEO pages, marketing content |
| `InteractiveServer` | Server via SignalR | Real-time apps, thin clients |
| `InteractiveWebAssembly` | Browser via WASM | Offline-capable, client-heavy |
| `InteractiveAuto` | Server first, then WASM | Best of both worlds |

### Applying Render Modes

```razor
@* Per-component *@
@rendermode InteractiveServer

@* Or in App.razor for global *@

```

### InteractiveAuto Architecture

```
First Request:
  Browser → Server (Interactive Server) → Fast response

Subsequent Requests:
  Browser → WASM (downloaded in background) → No server needed
```

## Workflow

1. **Choose render mode based on requirements:**
   - Need SEO? Start with Static or prerendering
   - Need real-time? Use InteractiveServer
   - Need offline? Use InteractiveWebAssembly
   - Want both? Use InteractiveAuto

2. **Design components for reusability:**
   - Small, focused components
   - Parameters for customization
   - Events for communication

3. **Handle state correctly:**
   - Component state lives in component
   - Shared state via services (DI)
   - Persist state across prerender with `[PersistentState]`

4. **Validate in both environments** (for Auto mode)

## Current Upstream Notes

- Treat `dotnet/aspnetcore` `v9.0.17` as servicing. For new guidance, keep using the `.NET 10` Blazor docs and the imported official Blazor task skills for project creation, component authoring, user input, auth, data, JS interop, and prerendering.
- When existing apps update servicing packages, recheck render-mode assumptions, SignalR circuit behavior, and any interactive-auto client/server service split.

## Component Patterns

### Basic Component
```razor
@* Counter.razor *@

    Clicked @count times

@code {
    private int count = 0;

    [Parameter]
    public int InitialCount { get; set; } = 0;

    protected override void OnInitialized()
    {
        count = InitialCount;
    }

    private void IncrementCount() => count++;
}
```

### Parameter and Event Callbacks
```razor
@* Parent.razor *@

@* ChildComponent.razor *@
@code {
    [Parameter] public string Value { get; set; } = "";
    [Parameter] public EventCallback ValueChanged { get; set; }

    private async Task UpdateValue(string newValue)
    {
        await ValueChanged.InvokeAsync(newValue);
    }
}
```

### State Persistence (.NET 8+)
```razor
@* Prevents double-fetch during prerender + hydration *@
@code {
    [PersistentState]
    public List Products { get; set; } = [];

    protected override async Task OnInitializedAsync()
    {
        // Only fetches once, persisted across prerender
        Products ??= await Http.GetFromJsonAsync>("api/products");
    }
}
```

## Data Access Pattern for Auto Mode

```csharp
// Shared interface
public interface IProductService
{
    Task> GetProductsAsync();
}

// Server implementation (direct DB access)
public class ServerProductService : IProductService
{
    private readonly AppDbContext _db;
    public async Task> GetProductsAsync()
        => await _db.Products.ToListAsync();
}

// Client implementation (HTTP call)
public class ClientProductService : IProductService
{
    private readonly HttpClient _http;
    public async Task> GetProductsAsync()
        => await _http.GetFromJsonAsync>("api/products");
}

// Registration
// Server: builder.Services.AddScoped();
// Client: builder.Services.AddScoped();
```

## Anti-Patterns to Avoid

| Anti-Pattern | Why It's Bad | Better Approach |
|--------------|--------------|-----------------|
| Large components | Hard to maintain, slow renders | Split into smaller components |
| Direct DB access in WASM | No DB in browser | Use HTTP API |
| Ignoring `ShouldRender` | Unnecessary re-renders | Override when needed |
| Sync JS interop in Server | Blocks SignalR circuit | Use `IJSRuntime` async |
| No error boundaries | One error crashes app | Use `` |
| Forgetting prerender state | Double API calls | Use `[PersistentState]` |

## Performance Best Practices

1. **Virtualize large lists:**
   ```razor
   
       
   
   ```

2. **Use `@key` for list diffing:**
   ```razor
   @foreach (var item in items)
   {
       
   }
   ```

3. **Debounce rapid events:**
   ```csharp
   private Timer? _debounceTimer;

   private void OnInput(ChangeEventArgs e)
   {
       _debounceTimer?.Dispose();
       _debounceTimer = new Timer(_ => InvokeAsync(DoSearch), null, 300, Timeout.Infinite);
   }
   ```

4. **Lazy load assemblies (WASM):**
   ```csharp
   var assemblies = await LazyAssemblyLoader
       .LoadAssembliesAsync(["MyHeavyFeature.wasm"]);
   ```

## JS Interop

### Calling JavaScript from C#
```csharp
@inject IJSRuntime JS

await JS.InvokeVoidAsync("alert", "Hello from Blazor!");
var result = await JS.InvokeAsync("prompt", "Enter name:");
```

### Calling C# from JavaScript
```csharp
[JSInvokable]
public static string GetMessage() => "Hello from C#!";
```

```javascript
DotNet.invokeMethodAsync('MyAssembly', 'GetMessage')
    .then(result => console.log(result));
```

## Deliver

- interactive Blazor components with appropriate render mode
- efficient state management and data flow
- proper handling of prerendering scenarios
- performant list rendering with virtualization

## Validate

- components render correctly in chosen mode
- state persists correctly across prerender/hydration
- no unnecessary re-renders (check with browser tools)
- JS interop works in both Server and WASM
- error boundaries catch component failures
- Auto mode works in both environments

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [managedcode](https://github.com/managedcode)
- **Source:** [managedcode/dotnet-skills](https://github.com/managedcode/dotnet-skills)
- **License:** MIT
- **Homepage:** https://skills.managed-code.com

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-managedcode-dotnet-skills-blazor
- Seller: https://agentstack.voostack.com/s/managedcode
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
