skills/team/dotnet-vertical-slice/SKILL.md
Scaffold vertical slice architecture with CQRS + FreeMediator, including optional Telerik Blazor UI generation. Use when creating feature-based .NET projects with command/query separation and pipeline behaviors. Do NOT use when the project uses layer-based (N-tier) architecture — this skill enforces feature folder structure and will conflict with existing layer conventions.
npx skillsauth add michaelalber/ai-toolkit dotnet-vertical-sliceInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
"The whole idea is that the abstraction we use to reason about the system should be the feature, not the layer." -- Jimmy Bogard
This skill scaffolds and maintains vertical slice architecture in .NET projects using FreeMediator for CQRS and pipeline behaviors. Every feature is a self-contained unit. Layers are an implementation detail inside the slice, not a project-level organizing principle.
Non-Negotiable Constraints:
| # | Principle | Description | Priority |
|---|-----------|-------------|----------|
| 1 | Feature Isolation | Feature folder is self-contained. No imports between feature folders. Shared code lives in Common/ or Infrastructure/. | Critical |
| 2 | Handler Autonomy | Each handler owns its dependencies and logic. Duplication between handlers is acceptable and preferred over coupling. | Critical |
| 3 | Minimal Abstractions | Introduce abstractions only when three or more features demonstrate an identical, stable pattern. | High |
| 4 | Pipeline Composition | Cross-cutting concerns are composed via FreeMediator pipeline behaviors, not handler inheritance. | Critical |
| 5 | CQRS Boundary | Commands return at most an identifier or status. Queries return data and must not mutate state. | Critical |
| 6 | Request/Response Immutability | Request and response types are C# records — immutable value objects. | High |
| 7 | Explicit Dependencies | Handlers declare dependencies via constructor injection. No service locator or static helpers. | High |
| 8 | Validator Co-Location | FluentValidation validator lives in the same feature folder as its request and handler. | High |
| 9 | Endpoint Thinness | Endpoints only deserialize, mediate, and serialize. No business logic. | High |
| 10 | Test Proximity | Tests mirror the feature folder structure and test handler, validator, and endpoint as a unit. | Medium |
| Query | When to Call |
|-------|--------------|
| search_knowledge("vertical slice architecture CQRS feature folder .NET") | At session start |
| search_knowledge("FreeMediator IRequest handler pipeline behavior .NET") | When scaffolding handlers or pipeline behaviors |
| search_knowledge("FluentValidation IValidator async rule .NET") | When scaffolding validators |
| search_knowledge("ASP.NET Core Minimal API TypedResults endpoint group") | When scaffolding endpoints |
| search_knowledge("EF Core DbContext dependency injection scoped lifetime") | When scaffolding DbContext |
| search_knowledge("C# record immutable request response DTO") | When defining request/response types |
Search before scaffolding each new component type. Cite the source path in generated code comments.
Scaffold proceeds in phases: SCAFFOLD (create folder and stub files) → COMMAND or QUERY (implement handler) → PIPELINE (wire behaviors) → VALIDATE (run tests, verify isolation). Use a notification (INotification) when an event must fan out to multiple handlers. When a feature both reads and writes, split it: extract the write as a command and the read as a separate query. Pipeline behaviors (validation, logging, transactions, caching) belong in Infrastructure/Behaviors/ and are registered once in DI — they must never contain feature-specific conditional logic.
CreateOrder, not OrderService)Program.csFeatures/ directory exists in the project<vslice-state>
step: [SCAFFOLD | COMMAND | QUERY | NOTIFICATION | PIPELINE | VALIDATE]
feature: [description]
pattern: [command | query | notification]
folder_path: [path to feature folder]
last_action: [what was just done]
next_action: [what should happen next]
blockers: [any issues]
</vslice-state>
Example:
<vslice-state>
step: SCAFFOLD
feature: CreateOrder - creates a new order from a cart
pattern: command
folder_path: src/MyApp/Features/Orders/CreateOrder/
last_action: Created feature folder structure
next_action: Define CreateOrderCommand record and CreateOrderResponse record
blockers: none
</vslice-state>
## Vertical Slice Session: [Feature Name]
**Pattern**: [Command | Query | Notification] | **Folder**: `Features/[Domain]/[FeatureName]/`
**Files created**: Request, Response, Handler, Validator, Endpoint
**State**: [current vslice-state block]
**Next**: [action]
Never create shared base handlers. Each handler is a standalone class implementing IRequestHandler<TRequest, TResponse>. If two handlers look similar, that duplication is intentional — shared abstractions between handlers re-introduce the horizontal layering that vertical slices eliminate.
One feature per folder. A feature folder contains exactly one request type, one handler, one validator (if applicable), one endpoint, and one response type. Two handlers in one folder means split it.
No cross-feature imports. Handlers must not import types from another feature folder or dispatch to another feature's handler. Use domain events (INotification) or shared infrastructure services for inter-feature communication.
Pipeline behaviors are infrastructure. A behavior with conditional logic per feature type is a design error. Use marker interfaces on the request type (e.g., ICachedQuery) to vary behavior without adding feature knowledge to the behavior class. Behaviors live in Infrastructure/Behaviors/, never inside a feature folder.
When the project uses Telerik UI for Blazor, generate Blazor pages alongside the backend slice. Pages live in the feature folder under Pages/ and dispatch commands/queries via FreeMediator. Only generate when the project has Telerik Blazor dependencies.
Extended feature folder structure:
Features/{FeatureName}/
├── Commands/Create{Entity}/, Update{Entity}/, Delete{Entity}/
├── Queries/Get{Entity}ById/, Get{Entity}List/
├── DTOs/{Entity}Dto.cs, {Entity}ListDto.cs
├── Pages/{Entity}List.razor, {Entity}Edit.razor
├── Mapping/{Entity}MappingConfig.cs (Mapster)
└── Tests/
| Anti-Pattern | Why It's Wrong | Correct Approach |
|--------------|----------------|------------------|
| Generic CRUD handler | Couples all features; base class changes ripple everywhere. | Each handler is standalone. Accept duplication. |
| Shared response types | Forces features to conform to one shape; blocks independent evolution. | Each feature defines its own response record. |
| Fat endpoint with business logic | Logic in HTTP layer can't be unit-tested without HTTP infrastructure. | Endpoints only deserialize, mediate, serialize. |
| Handler calling another handler | Hidden runtime coupling; breaks feature isolation. | Use INotification events or shared infrastructure services. |
| Organizing by technical layer | Developers touch multiple folders for one feature. | Organize by feature; each folder contains all layers for that slice. |
| Validation in the handler | Mixes cross-cutting logic with business logic; not reusable. | FluentValidation validator + pipeline validation behavior. |
| Pipeline behaviors in feature folders | Behaviors are shared infrastructure, not feature-specific. | Behaviors live in Infrastructure/Behaviors/. |
InvalidOperationException — No handler registered for [RequestType]
IRequestHandler<TRequest, TResponse>Handler executes with invalid data, no ValidationException thrown
ValidationBehavior<,> is registered as a pipeline behaviorAbstractValidator<TRequest>services.AddValidatorsFromAssemblyContaining<Program>()A feature folder has more than 6–8 files; handler has 200+ lines
Common/Feature A imports from Feature B, Feature B imports from Feature A
Common/Models/ or the domain layerTransaction commits before validation; logging misses exceptions
next() and does not swallow exceptionsef-migration-manager — When a slice requires schema changes, plan the migration alongside the feature. Define the entity first, then create the migration.tdd — Each slice is an ideal TDD unit. Write a failing handler test (RED), implement minimally (GREEN), refactor. Handler isolation makes testing straightforward without mocking half the application.tdd-agent — For autonomous vertical slice development: scaffold the folder, write handler tests RED, implement GREEN, refactor.development
Interviews the user relentlessly about a plan, decision, or idea — one question at a time, each with a recommended answer. Shared engine behind "grill-me" and "grill-with-docs". Use on any "grill" trigger phrase or to stress-test thinking. Do NOT use to build the plan; it ends at shared understanding, not implementation.
testing
Runs a relentless interview to sharpen a plan or design, capturing the decisions as ADRs and a glossary along the way. Use when the user wants to be grilled AND wants the session to leave durable domain documentation behind. Do NOT use for a throwaway stress-test with no artifacts; use grill-me instead.
tools
OWASP-based security review of Vue/TypeScript front-ends. Detects framework (Vite/Vue CLI/Nuxt), entry points, and data flows; scans the OWASP Top 10 (2025) mapped to Vue client-side risks (raw-HTML XSS via v-html, URL/protocol injection, bundled secrets, insecure token storage, dependency CVEs, missing CSP, open redirects, router guard bypass); emits an exec summary plus graded findings. Use to audit Vue for vulnerabilities. Not for architecture grading (vue-architecture-checklist).
tools
Analyzes legacy Vue codebases and produces actionable modernization plans. Primary migration paths include Options API to Composition API, Vue 2 to Vue 3, Vue CLI to Vite, JavaScript to TypeScript, Vue Test Utils/Karma/Mocha to Vitest + Vue Testing Library, legacy Vuex to Pinia, and removed-in-Vue-3 pattern cleanup (filters, event bus, `$listeners`). Does NOT perform the migration — assesses, quantifies risk, and plans.