author-component — Claude Code skill: what it does, how to install
Creates and reviews Blazor components without JavaScript interop. Useful when setting up parameters, RenderFragment slots, and proper async lifecycles.
npx skills add dotnet/skills --skill author-component -a claude-codeWhat author-component does
The skill establishes Blazor architecture rules for .razor files. Components under roughly 50 lines keep their logic inside an inline @code block. Once logic grows beyond that threshold, it separates into a code-behind partial class within a .razor.cs file. Data moves down via [Parameter], while child-to-parent communication relies on EventCallback<T>.
All async operations must be awaited directly. Blocking calls like .Result, .Wait(), or offloading to Task.Run are barred because they cause deadlocks or escape the synchronization context. Components handling subscriptions or polling loops must implement IAsyncDisposable and manage cancellation via CancellationTokenSource.
This tool focuses strictly on component architecture. It does not handle JavaScript interop, prerendering, or form validation workflows. Applying required or init modifiers to properties marked with [Parameter] triggers compiler error BL0007, so the rules reject them outright.
What it helps with
- write Blazor components with single-file or code-behind architecture
- wire upward events through EventCallback instead of plain delegates
- implement generic RenderFragment slots for child templates
- handle async debouncing and polling via CancellationTokenSource
Example prompts for the agent
- Create a Blazor table component with a generic RowTemplate slot and loading state handling
- Review UserCard.razor for parameter mutations and improper async disposal patterns
- Move the C# logic from Cart.razor into a separate Cart.razor.cs code-behind file
How to install author-component
1Skills CLI (Vercel)
npx skills add dotnet/skills --skill author-component -a claude-code2Manually: put the files in place
~/.claude/skills/author-component/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/author-component/
1Skills CLI (Vercel)
npx skills add dotnet/skills --skill author-component -a codex2Manually: put the files in place
.agents/skills/author-component/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add dotnet/skills --skill author-component -a cursor2Manually: put the files in place
.cursor/skills/author-component/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install dotnet/skills author-component2Manually: put the files in place
.github/skills/author-component/SKILL.md1Skills CLI (Vercel)
npx skills add dotnet/skills --skill author-component -a gemini-cli2Platform CLI
gemini skills install https://github.com/dotnet/skills --path plugins/dotnet-blazor/skills/author-componentManually: put the files in place
.devin/skills/author-component/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add dotnet/skills --skill author-component -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about author-component
How do I install author-component in Claude Code?
Run npx skills add dotnet/skills --skill author-component -a claude-code in your terminal.
What does the author-component skill do?
It guides the creation and review of Blazor components following .NET best practices. It checks parameter flow, EventCallback usage, RenderFragment slots, and cleanup via IAsyncDisposable.
Can I use author-component for JavaScript interop?
No, calling browser APIs and JS interop are outside this skill's scope. Use the dedicated use-js-interop skill for those tasks instead.
Source text
SKILL.md · MIT
---
license: MIT
name: author-component
description: >
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).
---
# Author Blazor Component
## Core Rules
- Data flows **down** via `[Parameter]`. Events flow **up** via `EventCallback<T>` (never `Action`/`Func`).
- Never mutate `[Parameter]` properties. Copy to a private field in `OnParametersSet`.
- Use `[Parameter] public T Prop { get; set; }` — never `required` or `init` (causes BL0007).
- Use `[EditorRequired]` for required parameters.
- Handle all states: loading, empty, loaded, error — each with `@if`/`@else`.
- Use `@key` on repeated elements in loops for efficient diffing.
- Use `IReadOnlyList<T>` (not `IEnumerable<T>`) for collection parameters.
## RenderFragment & Generics
```csharp
[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public RenderFragment<TItem>? RowTemplate { get; set; } // generic template
```
Use `@typeparam TItem` for generic components.
## File Patterns
- **Single-file:** `.razor` with `@code` block when logic < ~50 lines.
- **Code-behind:** `.razor` + `.razor.cs` with `partial class` when logic > ~50 lines.
## Disposal
Implement `IAsyncDisposable` (not `IDisposable`) when the component owns subscriptions, timers, or CTS.
In `DisposeAsync`: unsubscribe (`-=`), cancel CTS, dispose resources. Never call `StateHasChanged`.
## Async Patterns
- `await` every async operation. Never use `.Result`, `.Wait()`, `Task.Run`, `ContinueWith`, `Thread.Start`.
- **Debounce:** `Task.Delay` + `CancellationTokenSource`. Cancel old CTS, create new, await delay, do work. Never use `System.Threading.Timer` or `System.Timers.Timer`.
- **Polling:** Loop in `OnInitializedAsync` with `await Task.Delay(interval, token)` — stays on sync context.
- **External events** (`Action<T>`): Use `async void` handler + `await InvokeAsync(() => { state++; StateHasChanged(); })` + `catch` → `DispatchExceptionAsync`. Never `_ = InvokeAsync(...)`.
- Cancel CTS in `DisposeAsync`. Don't catch `ObjectDisposedException` — use CTS cancellation.
## Don'ts
- `required`/`init` on `[Parameter]` — runtime failure
- Mutate `[Parameter]` — copy to private field in `OnParametersSet`
- `Action`/`Func` for events — use `EventCallback<T>`
- `Task.Run`/`.Result`/`.Wait()`/Timer for debounce — deadlock or thread-pool escape
- Inline `style` attributes — use CSS classes or `data-*` attributes
- `catch { throw; }` — use `when` guard or let exceptions propagate
- Gold-plating: ARIA, wrapper divs, accessibility features not requested
- `_ = InvokeAsync(...)` — swallows exceptions; use `async void` + `DispatchExceptionAsync`
© dotnet · MIT · dotnet/skills