Create or review Blazor components (.razor files) with correct architecture. USE FOR: writing new Blazor components that do NOT involve JavaScript interop, implementing parameters and EventCallback, RenderFragment slots, component lifecycle (OnInitializedAsync, OnParametersSet), async patterns, IAsyncDisposable, CancellationToken, CSS isolation, code-behind. DO NOT USE FOR: creating new projects (use create-blazor-project), JavaScript interop or calling browser APIs from Blazor (use use-js-interop), forms and validation (use collect-user-input), prerendering issues (use support-prerendering), HTTP data fetching patterns (use fetch-and-send-data), coordinating state between unrelated components (use coordinate-components).
How this skill is triggered — by the user, by Claude, or both
Slash command
/0xcraft-claude-plugin:author-componentThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- Data flows **down** via `[Parameter]`. Events flow **up** via `EventCallback<T>` (never `Action`/`Func`).
[Parameter]. Events flow up via EventCallback<T> (never Action/Func).[Parameter] properties. Copy to a private field in OnParametersSet.[Parameter] public T Prop { get; set; } — never required or init (causes BL0007).[EditorRequired] for required parameters.@if/@else.@key on repeated elements in loops for efficient diffing.IReadOnlyList<T> (not IEnumerable<T>) for collection parameters.[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public RenderFragment<TItem>? RowTemplate { get; set; } // generic template
Use @typeparam TItem for generic components.
.razor with @code block when logic < ~50 lines..razor + .razor.cs with partial class when logic > ~50 lines.Implement IAsyncDisposable (not IDisposable) when the component owns subscriptions, timers, or CTS.
In DisposeAsync: unsubscribe (-=), cancel CTS, dispose resources. Never call StateHasChanged.
await every async operation. Never use .Result, .Wait(), Task.Run, ContinueWith, Thread.Start.Task.Delay + CancellationTokenSource. Cancel old CTS, create new, await delay, do work. Never use System.Threading.Timer or System.Timers.Timer.OnInitializedAsync with await Task.Delay(interval, token) — stays on sync context.Action<T>): Use async void handler + await InvokeAsync(() => { state++; StateHasChanged(); }) + catch → DispatchExceptionAsync. Never _ = InvokeAsync(...).DisposeAsync. Don't catch ObjectDisposedException — use CTS cancellation.required/init on [Parameter] — runtime failure[Parameter] — copy to private field in OnParametersSetAction/Func for events — use EventCallback<T>Task.Run/.Result/.Wait()/Timer for debounce — deadlock or thread-pool escapestyle attributes — use CSS classes or data-* attributescatch { throw; } — use when guard or let exceptions propagate_ = InvokeAsync(...) — swallows exceptions; use async void + DispatchExceptionAsyncCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub d1ssolve/craft-agents