| name | backend-feature |
| description | Scaffolds backend features including new domain entities, new properties on existing entities, and new business operations. Use when creating a new domain entity, extending an existing entity with new properties, or adding new business features/commands. |
| allowed-tools | Read, Glob, Grep, Write, Edit, Bash(dotnet:*, ls:*, mkdir:*) |
Backend Feature Scaffolding
This skill handles three scenarios:
- New Entity - Create a complete vertical slice for a new domain entity
- New Property - Add properties to an existing entity
- New Feature - Add business operations (commands/queries) to an existing entity
Scenario 1: New Entity
For a new entity named [EntityName] (e.g., Customer, Order, Product), this skill generates:
Domain/
└── [EntityName]s/
├── [EntityName].cs # Rich domain entity
├── DomainEvents/
│ ├── [EntityName]Created.cs
│ ├── [EntityName]Updated.cs
│ └── [EntityName]Deleted.cs
├── Dtos/
│ ├── [EntityName]Dto.cs
│ ├── [EntityName]ForCreationDto.cs
│ ├── [EntityName]ForUpdateDto.cs
│ └── [EntityName]ParametersDto.cs
├── Features/
│ ├── Add[EntityName].cs
│ ├── Update[EntityName].cs
│ ├── Delete[EntityName].cs
│ ├── Get[EntityName].cs
│ └── Get[EntityName]List.cs
├── Mappings/
│ └── [EntityName]Mapper.cs
└── Models/
├── [EntityName]ForCreation.cs
└── [EntityName]ForUpdate.cs
Databases/
└── EntityConfigurations/
└── [EntityName]Configuration.cs # EF Core entity configuration
Controllers/
└── v1/
└── [EntityName]sController.cs
Scenario 2: New Property on Existing Entity
When adding properties to an existing entity, update these files:
| File | Changes |
|---|
[EntityName].cs | Add property with private setter |
[EntityName]ForCreation.cs | Add property if set at creation |
[EntityName]ForUpdate.cs | Add property if updatable |
[EntityName]ForCreationDto.cs | Add property if set at creation |
[EntityName]ForUpdateDto.cs | Add property if updatable |
[EntityName]Dto.cs | Add property for response |
[EntityName]Mapper.cs | Add custom mapping if value object |
[EntityName]Configuration.cs | Configure property constraints, value objects |
Scenario 3: New Feature on Existing Entity
When adding a business operation to an existing entity:
| Component | Files to Create/Modify |
|---|
| Domain method | [EntityName].cs - Add behavior method |
| Domain event | DomainEvents/[EntityName][Action].cs - New event |
| Feature | Features/[Action][EntityName].cs - New command/query |
| Controller | [EntityName]sController.cs - Add endpoint |
| DTOs (if needed) | Dtos/[Action][EntityName]Dto.cs - Request/response |
Usage Examples
New Entity
Create a backend feature for managing Products with name, price, and category
New Property on Existing Entity
Add an email property to the Customer entity
Add a status property with Draft, Active, and Archived states to the Product entity
New Feature on Existing Entity
Add a Submit feature to the Order entity that changes status and validates requirements
Add a GetOrdersByCustomer query that returns orders for a specific customer
Process: New Entity
-
Gather Requirements
- Entity name (PascalCase, singular:
Customer, Order, Product)
- Properties and their types
- Any special business rules or value objects needed
-
Generate Domain Entity
- Create rich domain entity following DDD principles
- Private setters, factory methods, encapsulated behavior
- Value objects for complex concepts
- See:
.claude/rules/backend/working-with-domain-entities.md
-
Generate Domain Events
- Created, Updated, Deleted events
- Additional business-specific events as needed
- See:
.claude/rules/backend/domain-events.md
-
Generate DTOs and Models
- Read DTO for responses
- Creation/Update DTOs for requests
- Parameters DTO for list queries
- Internal models for domain method contracts
- See:
.claude/rules/backend/dtos-and-mappings.md
-
Generate Mapperly Mapper
- Entity to DTO mappings
- DTO to internal model mappings
- IQueryable projection support
- See:
.claude/rules/backend/dtos-and-mappings.md
-
Generate CQRS Features
- Add, Update, Delete commands
- Get single and Get list queries
- MediatR handlers with proper patterns
- See:
.claude/rules/backend/features-and-cqrs.md
-
Generate Controller
- Thin controller delegating to MediatR
- Proper API versioning
- OpenAPI documentation
- See:
.claude/rules/backend/controllers.md
-
Generate Entity Configuration
- Create
IEntityTypeConfiguration<T> class
- Configure property constraints and indexes
- Configure value object mappings with
OwnsOne
- See:
.claude/rules/backend/entity-configurations.md
-
Update Infrastructure
- Add DbSet to AppDbContext
- Ensure
ApplyConfigurationsFromAssembly is called in OnModelCreating
Process: New Property
-
Read Existing Entity
- Understand current entity structure and patterns
- Identify if property is a simple type or value object
-
Add Property to Domain Entity
public string PhoneNumber { get; private set; }
public EmailAddress Email { get; private set; } = default!;
-
Update Factory Method (if set at creation)
public static Customer Create(CustomerForCreation forCreation)
{
var entity = new Customer
{
PhoneNumber = forCreation.PhoneNumber,
};
}
-
Update Update Method (if updatable)
public Customer Update(CustomerForUpdate forUpdate)
{
PhoneNumber = forUpdate.PhoneNumber;
}
-
Update Internal Models
- Add to
[EntityName]ForCreation.cs if set at creation
- Add to
[EntityName]ForUpdate.cs if updatable
-
Update DTOs
- Add to
[EntityName]Dto.cs for responses
- Add to
[EntityName]ForCreationDto.cs if set at creation
- Add to
[EntityName]ForUpdateDto.cs if updatable
-
Update Mapper (for value objects)
private static string? MapEmail(EmailAddress? email) => email?.Value;
-
Update Entity Configuration
builder.Property(e => e.PhoneNumber).HasMaxLength(20);
builder.OwnsOne(e => e.Email, email =>
{
email.Property(e => e.Value).HasColumnName("email").HasMaxLength(320);
});
-
Create Migration
dotnet ef migrations add Add[PropertyName]To[EntityName]
Process: New Feature
-
Read Existing Entity
- Understand current entity structure
- Identify what state changes are needed
- Determine guard conditions
-
Add Domain Method to Entity
public Order Submit()
{
GuardIfNotDraft("Cannot submit");
Status = OrderStatus.Submitted();
QueueDomainEvent(new OrderSubmitted
{
OrderId = Id,
SubmittedAt = DateTimeOffset.UtcNow
});
return this;
}
-
Create Domain Event (if needed)
public sealed record OrderSubmitted : IDomainEvent
{
public required Guid OrderId { get; init; }
public required DateTimeOffset SubmittedAt { get; init; }
}
-
Create Feature (Command or Query)
public static class SubmitOrder
{
public sealed record Command(Guid Id) : IRequest<OrderDto>;
public sealed class Handler(AppDbContext dbContext) : IRequestHandler<Command, OrderDto>
{
public async Task<OrderDto> Handle(Command request, CancellationToken ct)
{
var order = await dbContext.Orders.GetById(request.Id, ct);
order.Submit();
await dbContext.SaveChangesAsync(ct);
return order.ToOrderDto();
}
}
}
-
Add Endpoint to Controller
[Authorize]
[HttpPost("{id:guid}/submit", Name = "SubmitOrder")]
[ProducesResponseType(typeof(OrderDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OrderDto>> SubmitOrder(Guid id)
{
var command = new SubmitOrder.Command(id);
var result = await mediator.Send(command);
return Ok(result);
}
-
Create Additional DTOs (if needed)
- Request DTO if the action needs input parameters
- Custom response DTO if different from standard entity DTO
Important Guidelines
Domain Entity Design
- Use private setters for all properties
- Create static factory method
Create() for entity creation
- Use
Update() method for modifications
- Implement guard methods for business rules
- Use value objects for complex domain concepts
- Queue domain events on state changes
Property Naming
- Entity properties: PascalCase (
FirstName, Email)
- DTO properties: PascalCase with
{ get; init; }
- Route parameters: camelCase in URLs, PascalCase in code
Value Objects to Consider
EmailAddress - validated email
PhoneNumber - formatted phone
Money - currency with amount
Address - street, city, state, zip
- Status enums with SmartEnum pattern
Common Patterns
Status with Behavior:
public class OrderStatus : ValueObject
{
private OrderStatusEnum _status;
public bool IsFinalState() => _status.IsFinalState();
public bool CanBeCancelled() => !IsFinalState();
public static OrderStatus Draft() => new("Draft");
public static OrderStatus Submitted() => new("Submitted");
}
Encapsulated Collections:
private readonly List<LineItem> _lineItems = [];
public IReadOnlyCollection<LineItem> LineItems => _lineItems.AsReadOnly();
public LineItem AddLineItem(Product product, int quantity)
{
var item = LineItem.Create(product, quantity);
_lineItems.Add(item);
return item;
}
Checklists
New Entity Checklist
New Property Checklist
New Feature Checklist
Reference Files
The following rules provide detailed patterns:
.claude/rules/backend/working-with-domain-entities.md - Rich domain entities
.claude/rules/backend/features-and-cqrs.md - CQRS with MediatR
.claude/rules/backend/dtos-and-mappings.md - DTOs and Mapperly
.claude/rules/backend/controllers.md - API controllers
.claude/rules/backend/domain-events.md - Domain events
.claude/rules/backend/entity-configurations.md - EF Core entity configurations