Guidance for writing MkDocs documentation for BlazorWebFormsComponents. Use this when creating or updating component documentation, migration guides, or utility feature docs in the /docs folder.
71
65%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
Optimize this skill with Tessl
npx tessl skill review --optimize ./.github/skills/documentation/SKILL.mdThis skill provides guidance for writing documentation for the BlazorWebFormsComponents library. Use this when creating or updating component documentation, migration guides, or utility feature docs.
The documentation serves developers migrating ASP.NET Web Forms applications to Blazor. Every document should:
When documenting a component, use this exact structure:
# [ComponentName]
[One paragraph describing what this component does and why it exists in this library]
Original Microsoft implementation: https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.[componentname]?view=netframework-4.8
## Features Supported in Blazor
- [List each supported feature as a bullet point]
- [Include supported events with brief description]
- [Note any Blazor-specific enhancements]
### Blazor Notes
[Any Blazor-specific implementation details or behavioral differences]
## Web Forms Features NOT Supported
- **[FeatureName]** - [Brief explanation of why not supported or what to use instead]
- **PostBackUrl** - Not supported; Blazor uses component events instead
- **ViewState serialization** - Not needed; state is preserved in component fields
## Web Forms Declarative Syntax
```html
<asp:[ComponentName]
[All attributes from original Web Forms control]
[Alphabetically ordered]
[Include runat="server" at the end]
/><[ComponentName]
[Supported attributes only]
[Same order as Web Forms section for easy comparison]
/>[Practical advice for migration] [Common pitfalls to avoid] [Performance considerations if any]
@* Description of what this example shows *@
<[ComponentName] Property="value" OnEvent="Handler" />
@code {
void Handler()
{
// Implementation
}
}@* More complex example *@## Writing Style Guidelines
### Tone
- Professional but approachable
- Acknowledge that migration is work, but this library helps
- Be direct about what's NOT supported rather than hiding it
### Code Examples
- Always show WORKING code that can be copy-pasted
- Include `@code` blocks with event handlers
- Use realistic property names and values
- Comment complex sections
### Web Forms Syntax Blocks
- Copy the FULL attribute list from Microsoft docs
- Include ALL attributes even if not supported (helps with migration)
- Keep attributes alphabetically ordered within logical groups
- Always include `runat="server"` at the end
### Blazor Syntax Blocks
- Show only SUPPORTED attributes
- Maintain same order as Web Forms for easy comparison
- Omit `runat` attribute (not used in Blazor)
- Use Blazor event syntax (`OnClick` not `OnClick="Handler"`)
## Migration Guide Template
```markdown
# Migrating [Feature/Pattern]
## Overview
[What this guide covers and who it's for]
## Prerequisites
- [Required knowledge]
- [Required tools/versions]
## Step-by-Step Migration
### Step 1: [Action]
**Before (Web Forms):**
```aspx
[Web Forms code]After (Blazor):
[Blazor code][Explanation of changes]
[Continue pattern...]
Problem: [Description] Solution: [How to fix]
## Utility Feature Documentation Template
```markdown
# [FeatureName]
## Background
[Why this feature existed in Web Forms]
[What problem it solved]
## Web Forms Usage
```csharp
// How it was used in Web Forms[How this library implements the feature] [Key differences from Web Forms]
// How to use in Blazor[How to update existing code] [Recommended Blazor alternatives if applicable]
[Recommendations for properly refactoring away from this legacy pattern]
## File Naming Conventions
- Use PascalCase for component docs: `Button.md`, `GridView.md`
- Use kebab-case for guides: `migration-readiness.md`, `master-pages.md`
- Exception: `readme.md` for index pages (lowercase)
## MkDocs Integration
After creating documentation:
1. Add entry to `mkdocs.yml` in appropriate `nav:` section
2. Maintain alphabetical order within categories
3. Use descriptive nav labels matching the component name
```yaml
nav:
- Editor Controls:
- Button: EditorControls/Button.md # Format: "Label: path/file.md"
- NewComponent: EditorControls/NewComponent.mdUse these sparingly for important callouts:
!!! note "Migration Tip"
Helpful information for migration
!!! warning "Breaking Change"
Something that differs significantly from Web Forms
!!! danger "Not Supported"
Feature that cannot be migrated directly
!!! tip "Best Practice"
Recommended Blazor pattern to use insteadLink to related documentation:
[Button](../EditorControls/Button.md)[Getting Started](../Migration/readme.md)[Live Demo](https://blazorwebformscomponents.azurewebsites.net)When creating sample pages in samples/AfterBlazorServerSide/Components/Pages/ControlSamples/, follow this structure to help developers see both the working demo AND the code that creates it:
@page "/samples/[componentname]/[scenario]"
<PageTitle>[ComponentName] - [Scenario]</PageTitle>
<h1>[ComponentName] Sample</h1>
<p>[Brief description of what this sample demonstrates]</p>
<div class="demo-container">
<h2>Demo</h2>
@* The actual working component demo *@
<Button Text="Click Me" OnClick="HandleClick" />
@if (ClickCount > 0)
{
<p>Button clicked @ClickCount times</p>
}
</div>
<div class="code-container">
<h2>Source Code</h2>
<pre><code class="language-razor">@@page "/samples/[componentname]/[scenario]"
<h1>[ComponentName] Sample</h1>
<Button Text="Click Me" OnClick="HandleClick" />
@@if (ClickCount > 0)
{
<p>Button clicked @@ClickCount times</p>
}
@@code {
private int ClickCount = 0;
private void HandleClick()
{
ClickCount++;
}
}</code></pre>
</div>
@code {
private int ClickCount = 0;
private void HandleClick()
{
ClickCount++;
}
}Two Sections Required:
Code Block Formatting:
<pre><code class="language-razor"> for syntax highlighting< becomes <, > becomes >@ symbols by doubling them: @@code, @@if, @@page@code block with event handlersKeep Demo and Code in Sync:
Organization:
demo-container and code-container for stylingComplex Samples:
@page "/samples/gridview/basic"
<PageTitle>GridView - Basic Example</PageTitle>
<h1>GridView Sample</h1>
<p>This sample demonstrates basic GridView usage with static data.</p>
<div class="demo-container">
<h2>Demo</h2>
<GridView DataSource="@Products" AutoGenerateColumns="true" />
</div>
<div class="code-container">
<h2>Source Code</h2>
<pre><code class="language-razor">@@page "/samples/gridview/basic"
<GridView DataSource="@@Products" AutoGenerateColumns="true" />
@@code {
private List<Product> Products = new()
{
new Product { Id = 1, Name = "Product A", Price = 10.99m },
new Product { Id = 2, Name = "Product B", Price = 20.99m }
};
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
}</code></pre>
</div>
@code {
private List<Product> Products = new()
{
new Product { Id = 1, Name = "Product A", Price = 10.99m },
new Product { Id = 2, Name = "Product B", Price = 20.99m }
};
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
}CRITICAL: Every documented component MUST have a corresponding sample page in the AfterBlazorServerSide project.
Samples are located in samples/AfterBlazorServerSide/Components/Pages/ControlSamples/[ComponentName]/
The folder structure mirrors the documentation categories:
ControlSamples/[ComponentName]/ControlSamples/[ComponentName]/ControlSamples/[ComponentName]/ (or ControlSamples/Validations/)ControlSamples/[ComponentName]/ControlSamples/[ComponentName]/Basic Sample: Index.razor - The main/default sample for the component
@page "/ControlSamples/[ComponentName]"Additional Scenarios: [ScenarioName].razor - Named after what they demonstrate
@page "/ControlSamples/[ComponentName]/[ScenarioName]"Style.razor, Events.razor, JavaScript.razorNavigation Helper: Nav.razor - Optional component listing all samples for this component
Every sample page MUST include:
@page "/ControlSamples/[ComponentName]" or @page "/ControlSamples/[ComponentName]/[Scenario]"<PageTitle>[ComponentName] - [Scenario]</PageTitle><h1>[ComponentName] Sample</h1> or <h2>[ComponentName] - [Scenario]</h2>@page "/ControlSamples/[ComponentName]"
@page "/ControlSamples/[ComponentName]/[Scenario]"
<PageTitle>[ComponentName] Sample</PageTitle>
<h2>[ComponentName] - [Scenario Description]</h2>
<p>[Brief description of what this sample demonstrates]</p>
@* Optional: Navigation to other samples for this component *@
<Nav />
@* The working demo *@
<div class="demo-section">
<[ComponentName]
Property1="value"
Property2="@someValue"
OnEvent="HandleEvent" />
</div>
@* Optional but recommended: Show the results or state *@
@if (!string.IsNullOrEmpty(Message))
{
<div class="result">@Message</div>
}
@code {
private string Message = "";
private void HandleEvent()
{
Message = "Event handled!";
}
}
<hr />
@* Optional: Display the code being used *@
<p>Code:</p>
<code>
<[ComponentName] Property1="value" OnEvent="HandleEvent" />
</code>When a component has multiple features to demonstrate, create separate sample pages:
ControlSamples/
Button/
Index.razor # Basic button usage
Style.razor # Styling examples
JavaScript.razor # JavaScript integration
Nav.razor # Navigation between samplesEach scenario page should focus on ONE specific feature or use case.
CRITICAL: After creating sample pages, they MUST be added to the navigation tree.
Location: samples/AfterBlazorServerSide/Components/Layout/NavMenu.razor
Add <TreeNode> entries under the appropriate category section:
<TreeNode Text="[Category] Components">
@* For a component with a single sample *@
<TreeNode Text="[ComponentName]" NavigateUrl="/ControlSamples/[ComponentName]" />
@* For a component with multiple samples *@
<TreeNode Text="[ComponentName]" NavigateUrl="/ControlSamples/[ComponentName]" Expanded="false">
<TreeNode Text="Basic Usage" NavigateUrl="/ControlSamples/[ComponentName]" />
<TreeNode Text="[Scenario 1]" NavigateUrl="/ControlSamples/[ComponentName]/[Scenario1]" />
<TreeNode Text="[Scenario 2]" NavigateUrl="/ControlSamples/[ComponentName]/[Scenario2]" />
</TreeNode>
</TreeNode>Navigation Categories:
<TreeNode Text="Editor Components"> - For editor controls<TreeNode Text="Data Components"> - For data-bound controls<TreeNode Text="Validation Components"> - For validators<TreeNode Text="Navigation Components"> - For navigation controls<TreeNode Text="Login Components"> - For login/authentication controlsOrdering: Add new components alphabetically within their category.
@* Adding a new editor control *@
<TreeNode Text="Editor Components">
<TreeNode Text="Button" NavigateUrl="/ControlSamples/Button">
<TreeNode Text="JavaScript Click" NavigateUrl="/ControlSamples/Button/JavaScript" />
<TreeNode Text="Style" NavigateUrl="/ControlSamples/Button/Style" />
</TreeNode>
<TreeNode Text="Label" NavigateUrl="/ControlSamples/Label" /> @* New component *@
<TreeNode Text="TextBox" NavigateUrl="/ControlSamples/TextBox" />
</TreeNode>
@* Adding a new data control with multiple samples *@
<TreeNode Text="Data Components">
<TreeNode Text="GridView" NavigateUrl="/ControlSamples/GridView" Expanded="false">
<TreeNode NavigateUrl="/ControlSamples/GridView" Text="Simple GridView" />
<TreeNode NavigateUrl="/ControlSamples/GridView/AutoGeneratedColumns" Text="Autogenerated Columns" />
<TreeNode NavigateUrl="/ControlSamples/GridView/TemplateFields" Text="Template Fields" />
</TreeNode>
</TreeNode>CRITICAL: After creating samples, update the component list on the home page.
Location: samples/AfterBlazorServerSide/Components/Pages/ComponentList.razor
Add links to the appropriate category column:
<div class="col-md-3">
<h3>[Category] Controls</h3>
<ul>
<li><a href="/ControlSamples/ExistingComponent">ExistingComponent</a></li>
<li><a href="/ControlSamples/NewComponent">NewComponent</a></li> @* Add alphabetically *@
<li><a href="/ControlSamples/OtherComponent">OtherComponent</a></li>
</ul>
</div>Categories:
Ordering: Add links alphabetically within each category.
CRITICAL: After documenting a component, update the main README.md at the repository root.
Location: README.md (repository root)
If adding a component that isn't already listed, add it to the appropriate category:
## Blazor Components for Controls
There are a significant number of controls in ASP.NET Web Forms, and we will focus on creating components in the following order:
- Editor Controls
- [AdRotator](docs/EditorControls/AdRotator.md)
- [Button](docs/EditorControls/Button.md)
- [NewComponent](docs/EditorControls/NewComponent.md) <-- Add alphabetically with link
- [TextBox](docs/EditorControls/TextBox.md)If a component exists in the list without a documentation link, add the link:
Before:
- CheckBoxList
After:
- [CheckBoxList](docs/EditorControls/CheckBoxList.md)Match the category in the README to where you placed the documentation:
Editor Controls → docs/EditorControls/Data Controls → docs/DataControls/Validation Controls → docs/ValidationControls/Navigation Controls → docs/NavigationControls/Login Controls → docs/LoginControls/Ordering: Keep components alphabetically sorted within each category.
When documenting a new or existing component, follow this complete workflow:
docs/[Category]/[ComponentName].mdmkdocs.ymlnav: section- ComponentName: Category/ComponentName.mdsamples/AfterBlazorServerSide/Components/Pages/ControlSamples/[ComponentName]/Index.razor for basic usage@page directive with correct routesamples/AfterBlazorServerSide/Components/Layout/NavMenu.razor<TreeNode> entries under appropriate categorysamples/AfterBlazorServerSide/Components/Pages/ComponentList.razor/ControlSamples/[ComponentName]README.md (root)- [ComponentName](docs/Category/ComponentName.md)# 1. Create documentation
docs/EditorControls/Label.md
# 2. Update mkdocs.yml
nav:
- Editor Controls:
- Label: EditorControls/Label.md
# 3. Create sample page
samples/AfterBlazorServerSide/Components/Pages/ControlSamples/Label/Index.razor
# 4. Update NavMenu.razor
<TreeNode Text="Label" NavigateUrl="/ControlSamples/Label" />
# 5. Update ComponentList.razor
<li><a href="/ControlSamples/Label">Label</a></li>
# 6. Update README.md
- [Label](docs/EditorControls/Label.md)Before submitting documentation:
mkdocs.yml navBefore submitting sample pages:
@ symbols doubled in code block@code block with all handlersControlSamples/[ComponentName]/@page directive with correct route<PageTitle> elementBefore submitting README updates:
[ComponentName](docs/Category/ComponentName.md)9bf8669
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.