Instruction file imported from attrectomma/SimpleCADDDSample (
.github/instructions/scaffolding.instructions.md). Copyright stays with the author.
Scaffolding a New Project
This instruction is for one-time project scaffolding or adding a complete new aggregate across all layers. For the full reference with every file template, see scaffolding.md at the repository root.
New Project Setup
Scaffold a single-project ASP.NET Core Web API with:
- EF Core + PostgreSQL
- Clean Architecture by folder boundaries (Domain → Data → Services → Endpoints)
- DDD tactical patterns (strongly typed IDs, value objects, sealed class entities)
- FluentValidation at endpoint boundary
- GlobalExceptionHandler for domain exceptions → ProblemDetails
- OpenAPI + Scalar (root
/redirects to/scalar/v1) - Docker Compose with PostgreSQL
- Integration tests with Testcontainers
Program.cs Template
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
// IUnitOfWork resolves the already-scoped ApplicationDbContext.
// Do NOT use AddScoped<IUnitOfWork, ApplicationDbContext>() — that creates a second instance.
builder.Services.AddScoped<IUnitOfWork>(sp =>
sp.GetRequiredService<ApplicationDbContext>());
builder.Services.AddScoped<IItemQueries, DbContextItemQueries>();
builder.Services.AddValidatorsFromAssemblyContaining<Program>();
builder.Services.AddProblemDetails();
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
builder.Services.AddOpenApi();
var app = builder.Build();
app.UseExceptionHandler();
app.MapOpenApi();
app.MapScalarApiReference();
app.MapGet("/", () => Results.Redirect("/scalar/v1")).ExcludeFromDescription();
app.UseHttpsRedirection();
// Map endpoints
app.MapCreateItemEndpoint();
app.MapGetItemByIdEndpoint();
app.Run();
public partial class Program { }
Adding a New Aggregate (Full Checklist)
Domain/{Aggregate}/{AggregateId}.cs—readonly record structwrappingGuidDomain/{Aggregate}/{ValueObjects}.cs— value objects for propertiesDomain/{Aggregate}/{Aggregate}.cs—sealed classwithstatic Create(...)Data/{Aggregate}/{AggregateConfiguration}.cs—IEntityTypeConfigurationwithHasConversionData/{Aggregate}/ApplicationDbContext{Aggregate}.cs— partial implementingIRepositoryData/ApplicationDbContext.cs— add: IRepository<Agg, AggId>+ApplyConfigurationData/{Aggregate}/I{Aggregate}Queries.cs— read-side interface with DTOsData/{Aggregate}/DbContext{Aggregate}Queries.cs— query implementationEndpoints/{Aggregate}/— endpoint files (Create, GetById, List, etc.)Program.cs— wire queries + map endpoints- EF migration
- Integration tests in
tests/.../Endpoints/{Aggregate}/
Adding a Cross-Aggregate Service
Services/{Feature}/I{Feature}Service.cs— interfaceServices/{Feature}/{Feature}Service.cs— implementationEndpoints/{Feature}/{Action}Endpoint.cs— calls serviceProgram.cs— wire service
Adding a Child Entity to an Existing Aggregate
Domain/{Aggregate}/{ChildId}.cs— strongly typed IDDomain/{Aggregate}/{Child}.cs—internalconstructor + factory- Modify aggregate root — backing list +
Add/Removemethods Data/{Aggregate}/{AggregateConfiguration}.cs— addOwnsManyData/{Aggregate}/ApplicationDbContext{Aggregate}.cs— add.Include()- EF migration
- Query interface — add child DTO + query method
- Query implementation
- New endpoint files for add / remove / list children
- Wire endpoints in
Program.cs - Integration tests