AgentStack
SKILL verified MIT Self-run

Blazor

skill-managedcode-dotnet-skills-blazor · by managedcode

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…

No reviews yet
0 installs
5 views
0.0% view→install

Install

$ agentstack add skill-managedcode-dotnet-skills-blazor

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Blazor? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

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

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

@* 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
  1. Design components for reusability:
  • Small, focused components
  • Parameters for customization
  • Events for communication
  1. Handle state correctly:
  • Component state lives in component
  • Shared state via services (DI)
  • Persist state across prerender with [PersistentState]
  1. 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

@* 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

@* 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+)

@* 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

// 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

```

  1. Use @key for list diffing:

```razor @foreach (var item in items) {

} ```

  1. Debounce rapid events:

```csharp private Timer? _debounceTimer;

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

  1. Lazy load assemblies (WASM):

``csharp var assemblies = await LazyAssemblyLoader .LoadAssembliesAsync(["MyHeavyFeature.wasm"]); ``

JS Interop

Calling JavaScript from C#

@inject IJSRuntime JS

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

Calling C# from JavaScript

[JSInvokable]
public static string GetMessage() => "Hello from C#!";
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.

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

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.