mirror of
https://github.com/dotnet/skills.git
synced 2026-09-20 09:49:54 +08:00
760ff44ffc
Integrates the 9 Blazor skills from PR #357 (javiercn/author-component) with fixes for the systemic activation failure (all skills showing NOT ACTIVATED): Key fixes: - Improve skill descriptions with explicit USE FOR/DO NOT USE FOR patterns that match the activation keyword style used by working skills in the repo - Add license: MIT to all skill frontmatter per repo conventions - Add marketplace entries (.github/plugin, .claude-plugin, .cursor-plugin) - Add CODEOWNERS entry for @dotnet/aspnet - Add README.md plugin entry - Add both playwright and microsoft-docs MCP servers to allowed-external-deps.txt MCP server analysis: - The eval framework (AgentRunner.cs:302-307) already skips non-stdio MCP servers - playwright (type: 'local') and microsoft-docs (type: 'http') are both filtered out during evaluation, so they don't affect eval results - Root cause of NOT ACTIVATED is likely description quality, not MCP servers Skills included: - author-component: Blazor component authoring patterns - collect-user-input: Forms, validation, EditForm patterns - configure-auth: Authentication/authorization across render modes - coordinate-components: Cross-component state sharing - create-blazor-project: New project scaffolding with correct render modes - fetch-and-send-data: API calls and async data lifecycle - plan-ui-change: Component decomposition planning - support-prerendering: Prerender-to-interactive handoff - use-js-interop: IJSRuntime, IJSObjectReference, .razor.js modules Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
101 lines
5.2 KiB
YAML
101 lines
5.2 KiB
YAML
scenarios:
|
|
- name: "Equipment inventory loaded once"
|
|
prompt: |
|
|
I have an existing Blazor Web App with Interactive Server (per-page).
|
|
|
|
I need an interactive /inventory page that shows a table of equipment items
|
|
(Id, Name, Location, LastInspected date). The data comes from an EquipmentService
|
|
you should create (just return fake data, 5-10 items).
|
|
|
|
The page should show "Loading inventory..." until data is ready, then display
|
|
the table. The important thing is that when the page first loads I see the HTML
|
|
instantly (fast initial paint), but the equipment data should NOT be fetched
|
|
twice — once during the initial server render and again when the page becomes
|
|
interactive. It should only call the service once and carry that data across.
|
|
assertions:
|
|
- type: "file_exists"
|
|
path: "**/Inventory.razor"
|
|
- type: "file_contains"
|
|
path: "**/Inventory.razor"
|
|
value: "PersistentState"
|
|
- type: "file_contains"
|
|
path: "**/Inventory.razor"
|
|
value: "InteractiveServer"
|
|
- type: "file_contains"
|
|
path: "**/Inventory.razor"
|
|
value: "??="
|
|
rubric:
|
|
- "Uses [PersistentState] attribute on the data property and the ??= pattern in OnInitializedAsync to avoid duplicate data fetches during prerender-to-interactive handoff"
|
|
- "Component correctly shows loading state when data is null, then displays the equipment table when loaded"
|
|
- "Does NOT disable prerendering — preserves the fast initial HTML response while avoiding duplicate loads"
|
|
- "Creates a proper EquipmentService registered in DI, not inline data generation"
|
|
timeout: 600
|
|
|
|
- name: "Privacy page that reads cookies in a global interactive app"
|
|
prompt: |
|
|
I have an existing Blazor Web App with Interactive Server (global interactivity).
|
|
|
|
I need a /privacy page that displays the privacy policy and reads a "consent"
|
|
cookie from the incoming HTTP request to show whether the user has already
|
|
accepted cookies.
|
|
|
|
The challenge is that the app uses global interactivity, but this page needs
|
|
to read HttpContext (for the cookie). HttpContext is only available during
|
|
static server-side rendering, not in interactive components. So this specific
|
|
page needs to opt out of interactive rendering and stay fully static, while
|
|
the rest of the app remains interactive.
|
|
|
|
Make sure App.razor is updated so that the routing knows to skip the interactive
|
|
render mode for this page.
|
|
assertions:
|
|
- type: "file_contains"
|
|
path: "**/Privacy.razor"
|
|
value: "ExcludeFromInteractiveRouting"
|
|
- type: "file_contains"
|
|
path: "**/Privacy.razor"
|
|
value: "HttpContext"
|
|
- type: "file_contains"
|
|
path: "**/App.razor"
|
|
value: "AcceptsInteractiveRouting"
|
|
rubric:
|
|
- "Privacy page uses @attribute [ExcludeFromInteractiveRouting] to opt out of interactive routing and force static SSR"
|
|
- "App.razor conditionally applies the render mode using HttpContext.AcceptsInteractiveRouting() — returns null for excluded pages so they render statically"
|
|
- "Privacy page accesses HttpContext to read cookies — this only works because the page is excluded from interactive routing"
|
|
- "The pattern preserves global interactivity for all other pages while allowing this specific page to be static"
|
|
timeout: 600
|
|
|
|
- name: "Notifications page with live polling"
|
|
prompt: |
|
|
I have an existing Blazor Web App with Interactive Server (per-page).
|
|
|
|
I need an interactive /notifications page that:
|
|
- Loads an initial set of notifications from a NotificationService (create it with fake data)
|
|
- After the page becomes interactive, starts a background polling loop that
|
|
checks for new notifications every 5 seconds and updates the UI
|
|
- Shows a notification count badge and a list of notification messages
|
|
|
|
Important constraints:
|
|
- The initial notifications should appear in the fast server-rendered HTML
|
|
and NOT be fetched again when the page becomes interactive
|
|
- The polling loop must not run during the initial server render — only after
|
|
the page is live and interactive in the browser
|
|
- When the user navigates away, the polling should stop cleanly (no leaked tasks)
|
|
assertions:
|
|
- type: "file_exists"
|
|
path: "**/Notifications.razor"
|
|
- type: "file_contains"
|
|
path: "**/Notifications.razor"
|
|
value: "RendererInfo.IsInteractive"
|
|
- type: "file_contains"
|
|
path: "**/Notifications.razor"
|
|
value: "PersistentState"
|
|
- type: "file_contains"
|
|
path: "**/Notifications.razor"
|
|
value: "InteractiveServer"
|
|
rubric:
|
|
- "Uses RendererInfo.IsInteractive to guard the polling loop startup — polling only begins after the component is interactive, not during prerender"
|
|
- "Uses [PersistentState] with ??= pattern to persist initial notification data across the prerender-to-interactive handoff"
|
|
- "Polling uses Task.Delay in an async loop with CancellationTokenSource, cancelled in DisposeAsync — not System.Threading.Timer"
|
|
- "Component implements IAsyncDisposable and cancels the polling token in DisposeAsync to prevent resource leaks"
|
|
timeout: 600
|