A production-ready, enterprise-grade ASP.NET Core 9 template implementing Clean Architecture with CQRS pattern. Create professional applications in 30 seconds with complete authentication, 2FA, and modern development practices.
# 1. Install template (one-time setup)
dotnet new install Sinan.AspNetCore.CleanArchitecture.CQRS.Template
# 2. Create your project (automatic renaming!)
dotnet new clean-cqrs-template -n MyAwesomeProject
cd MyAwesomeProject
# 3. Run immediately!
dotnet run --project src/MyAwesomeProject.APIThat's it! You now have:
- β
MyAwesomeProject.APIwith full auth system - β
MyAwesomeProject.Applicationwith CQRS commands/queries - β JWT authentication + 2FA ready
- β Email confirmation system
- β PostgreSQL database with seeded data
- β Docker support
- β Clean Architecture + CQRS pattern
MyAwesomeProject/
βββ src/
β βββ MyAwesomeProject.API/ # π Web API with auth endpoints
β βββ MyAwesomeProject.Application/ # π― CQRS commands & queries
β βββ MyAwesomeProject.Domain/ # ποΈ Domain entities
β βββ MyAwesomeProject.Infrastructure/ # π§ External services (email, etc.)
β βββ MyAwesomeProject.Persistence/ # πΎ Database context & migrations
βββ tests/
βββ MyAwesomeProject.Application.Tests/
βββ MyAwesomeProject.Infrastructure.Tests/
POST /api/Auth/register # β
User registration with email confirmation
POST /api/Auth/login # β
Login with JWT tokens
POST /api/Auth/enable-2fa # β
Google Authenticator 2FA
POST /api/Auth/complete-2fa-login # β
Complete 2FA login
POST /api/Auth/refresh-token # β
JWT refresh tokens
POST /api/Auth/forgot-password # β
Password reset via email
POST /api/Auth/confirm-email # β
Email confirmation- π JWT Authentication with refresh token rotation
- π‘οΈ Two-Factor Authentication (Google Authenticator)
- π§ Real SMTP Email Service (MailKit)
- ποΈ Clean Architecture (proper dependency flow)
- π― CQRS Pattern (MediatR implementation)
- πΎ PostgreSQL with Entity Framework Core
- π³ Docker ready with multi-stage builds
- π Serilog structured logging
- β FluentValidation for all requests
- π Swagger/OpenAPI documentation
- π§ͺ Unit tests structure ready
dotnet new install Sinan.AspNetCore.CleanArchitecture.CQRS.Template
dotnet new clean-cqrs-template -n YourProjectName# Clone and install locally
git clone https://github.com/sinanfen/aspnetcore-clean-cqrs-template.git
cd aspnetcore-clean-cqrs-template
dotnet new install ./
# Create your project
dotnet new clean-cqrs-template -n YourProjectNameUpdate src/YourProject.API/appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Database=YourProjectDB;Username=postgres;Password=yourpassword"
}
}{
"EmailSettings": {
"SmtpServer": "smtp.gmail.com",
"SmtpPort": 587,
"SmtpUsername": "[email protected]",
"SmtpPassword": "%YOUR_EMAIL_PASSWORD%"
}
}# Set your email app password
export YOUR_EMAIL_PASSWORD="your-gmail-app-password"
# Windows: $env:YOUR_EMAIL_PASSWORD = "your-gmail-app-password"# Install EF tools (if needed)
dotnet tool install --global dotnet-ef
# Apply migrations and seed data
dotnet ef database update --project src/YourProject.Persistence --startup-project src/YourProject.API# Development
dotnet run --project src/YourProject.API
# With Docker
docker-compose up -d
# Access your API
# Swagger: https://localhost:7176/swagger
# Health Check: https://localhost:7176/health# 1. Register a new user
curl -X POST "https://localhost:7176/api/Auth/register" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "SecurePass123!",
"firstName": "John",
"lastName": "Doe"
}'
# 2. Check email for confirmation link and confirm
# 3. Login
curl -X POST "https://localhost:7176/api/Auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "SecurePass123!"
}'
# 4. Enable 2FA (returns QR code)
curl -X POST "https://localhost:7176/api/Auth/enable-2fa" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# 5. Complete 2FA login
curl -X POST "https://localhost:7176/api/Auth/complete-2fa-login" \
-H "Content-Type: application/json" \
-d '{"twoFactorCode": "123456"}'π API Layer (Controllers, Middleware)
β depends on
π― Application Layer (CQRS, Business Logic)
β depends on
ποΈ Domain Layer (Entities, Business Rules)
β depended by
π§ Infrastructure Layer (Email, External APIs)
β depended by
πΎ Persistence Layer (Database, Repositories)
Commands/
βββ RegisterUser/
β βββ RegisterUserCommand.cs
β βββ RegisterUserCommandHandler.cs
β βββ RegisterUserCommandValidator.cs
βββ Enable2FA/
βββ Enable2FACommand.cs
βββ Enable2FACommandHandler.cs
βββ Enable2FACommandValidator.cs
Queries/
βββ LoginUser/
βββ LoginUserQuery.cs
βββ LoginUserQueryHandler.cs
βββ LoginUserQueryValidator.cs
// src/YourProject.Domain/Entities/Product.cs
public class Product : BaseEntity
{
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public string Description { get; set; } = string.Empty;
}// src/YourProject.Application/Features/Products/Commands/CreateProduct/
public record CreateProductCommand(string Name, decimal Price, string Description)
: IRequest<Result<Guid>>;
public class CreateProductCommandHandler : IRequestHandler<CreateProductCommand, Result<Guid>>
{
private readonly IApplicationDbContext _context;
public CreateProductCommandHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<Result<Guid>> Handle(CreateProductCommand request, CancellationToken cancellationToken)
{
var product = new Product
{
Name = request.Name,
Price = request.Price,
Description = request.Description
};
_context.Products.Add(product);
await _context.SaveChangesAsync(cancellationToken);
return Result<Guid>.Success(product.Id);
}
}
public class CreateProductCommandValidator : AbstractValidator<CreateProductCommand>
{
public CreateProductCommandValidator()
{
RuleFor(x => x.Name).NotEmpty().MaximumLength(100);
RuleFor(x => x.Price).GreaterThan(0);
}
}// src/YourProject.API/Controllers/ProductController.cs
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class ProductController : ControllerBase
{
private readonly IMediator _mediator;
public ProductController(IMediator mediator)
{
_mediator = mediator;
}
[HttpPost]
public async Task<IActionResult> CreateProduct(CreateProductCommand command)
{
var result = await _mediator.Send(command);
return result.IsSuccess ? Ok(result) : BadRequest(result);
}
}dotnet ef migrations add AddProductEntity --project src/YourProject.Persistence
dotnet ef database update --project src/YourProject.Persistence# Development with Docker Compose
docker-compose -f docker-compose.dev.yml up -d
# Production deployment
docker-compose up -d
# Build custom image
docker build -t yourproject-api .
docker run -p 8080:8080 yourproject-api# Run all tests
dotnet test
# Run with coverage
dotnet test --collect:"XPlat Code Coverage"
# Specific test project
dotnet test tests/YourProject.Application.Tests/- ASP.NET Core 9.0 - Latest .NET web framework
- Entity Framework Core 9.0 - Modern ORM
- PostgreSQL - Production database
- MediatR - CQRS implementation
- FluentValidation - Request validation
- AutoMapper - Object-to-object mapping
- ASP.NET Core Identity - User management
- JWT Bearer - Token authentication
- Google Authenticator - 2FA implementation
- MailKit - Professional email service
- Serilog - Structured logging
- Swashbuckle - OpenAPI/Swagger
- Docker - Containerization
- β JWT Authentication with RS256 signing
- β Refresh Token Rotation for security
- β Two-Factor Authentication (TOTP)
- β Email Confirmation required
- β Password Reset via secure tokens
- β Rate Limiting protection
- β CORS properly configured
- β Input Validation on all endpoints
- β SQL Injection protection
- β XSS Protection headers
- π 2-3 weeks to setup basic auth
- π Security vulnerabilities from scratch implementation
- π Reinventing the wheel for common patterns
- π Learning curve for Clean Architecture + CQRS
- βοΈ Complex configuration setup
- β‘ 30 seconds to production-ready app
- π Enterprise-grade security built-in
- ποΈ Proven architecture patterns
- π Well-documented and tested
- π Focus on business logic, not infrastructure
We welcome contributions! Please see our Contributing Guidelines.
# Fork the repo, then:
git clone https://github.com/yourusername/aspnetcore-clean-cqrs-template.git
cd aspnetcore-clean-cqrs-template
# Create feature branch
git checkout -b feature/amazing-feature
# Make changes and test
dotnet test
dotnet build
# Submit PR
git push origin feature/amazing-featureThis project is licensed under the MIT License - see the LICENSE file for details.
- Robert C. Martin - Clean Architecture principles
- Greg Young - CQRS pattern advocacy
- ASP.NET Core Team - Amazing framework
- Community Contributors - Feedback and improvements
If this template helps you build better applications, please:
- β Star this repository
- π¦ Share on Twitter
- π Consider sponsoring the project
- π Write a blog post about your experience
dotnet new install Sinan.AspNetCore.CleanArchitecture.CQRS.Template
dotnet new clean-cqrs-template -n MyNextBigProjectHappy coding! π