Skip to content

iPazooki/CleanArchitecture

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

50 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

GitHub GitHub contributors .NET Aspire CI

🧱 Clean Architecture

A production-ready .NET 10 + Next.js 16 Clean Architecture template, orchestrated by .NET Aspire and ready to deploy to Azure with azd. It ships with a Minimal API, an admin dashboard, dual authentication providers, and PostgreSQL β€” all wired up out of the box.


✨ Highlights

  • 🎯 Clean Architecture β€” strict layer boundaries enforced by architecture tests
  • ⚑ .NET 10 Minimal API β€” versioned endpoints, output caching, Result<T> pattern
  • 🧩 CQRS via the Mediator source generator (no MediatR runtime cost)
  • 🌐 Next.js 16 Admin Panel β€” App Router BFF with i18n (en / fa / ar + RTL)
  • πŸ” Pluggable Authentication β€” switch between Keycloak and Microsoft Entra ID via config
  • πŸ“œ Scalar API Reference β€” interactive OpenAPI UI with implicit OAuth flow (no client secret needed)
  • πŸ› οΈ Orval-generated API client β€” typed React hooks regenerated from the OpenAPI spec
  • 🐘 PostgreSQL via EF Core 10 with auto-applied migrations
  • ☁️ .NET Aspire β€” orchestrates all services locally and provisions Azure infrastructure
  • πŸ§ͺ Robust Testing β€” Domain unit tests, architecture tests, and Aspire-based integration tests
  • πŸ›‘οΈ Polly β€” retries, circuit breakers, fallbacks for outbound calls

πŸ—οΈ Architecture

Domain ← Application ← Infrastructure / Infrastructure.Persistence ← Presentation
Layer Responsibility
Domain Entities, Value Objects, Specifications, Domain Events
Application CQRS commands/queries, validators, Result<T>
Infrastructure External integrations (email, etc.) with Polly resilience
Infrastructure.Persistence EF Core DbContext, Postgres, migrations, interceptors
Presentation/API Minimal API, versioned at /api/v1/..., Scalar UI
Presentation/admin Next.js admin dashboard (BFF + NextAuth.js)
Aspire AppHost Orchestrates the full stack and Azure deployment

βœ… Prerequisites


πŸš€ Quick Start

# 1. Clone
git clone https://github.com/iPazooki/CleanArchitecture.git
cd CleanArchitecture

# 2. Restore .NET dependencies
dotnet restore

# 3. Install admin panel dependencies
cd CleanArchitecture.Presentation/admin && pnpm install && cd ../..

# 4. Run the full stack with Aspire
dotnet run --project CleanArchitecture.Aspire/CleanArchitecture.AppHost/CleanArchitecture.AppHost.csproj

Aspire will spin up everything you need:

Service What it does
πŸ”΅ API .NET Minimal API
🟣 Admin Next.js dashboard
🐘 Postgres + PgAdmin Database & UI
πŸ”‘ Keycloak Local identity provider (realm auto-imported)

The Aspire dashboard prints the URLs for every resource (API, Scalar UI, admin, Keycloak, PgAdmin).


πŸ” Authentication

The app supports two providers and switches between them via configuration.

Environment Default Provider Why
πŸ› οΈ Development Keycloak Runs as a local container, realm auto-imported, no cloud setup needed
☁️ Production Microsoft Entra ID Managed identity, no secrets to rotate for the API

Switching providers

In CleanArchitecture.Aspire/CleanArchitecture.AppHost/appsettings.*.json:

{
  "UseKeycloak": true   // false β†’ Entra
}

The AppHost wires the right environment variables (Authentication__Provider, issuer URLs, audiences, NextAuth client config) into the API and admin projects automatically.

πŸ“˜ Scalar uses the OAuth 2.0 implicit flow, so no client secret is needed for the API reference UI. Just sign in from the Scalar page.


πŸ“œ API Reference (Scalar)

Once running, open the Scalar UI from the Aspire dashboard's API resource. It renders the OpenAPI spec at /openapi/v1.json and lets you authenticate and call endpoints interactively.


πŸ–₯️ Admin Panel

The admin dashboard lives in CleanArchitecture.Presentation/admin (Next.js 16, App Router, Tailwind, NextAuth.js, TanStack Query).

cd CleanArchitecture.Presentation/admin
pnpm dev        # dev server (Aspire normally runs this for you)
pnpm build      # production build
pnpm lint       # ESLint with --max-warnings=0
pnpm generate   # regenerate the typed API client from the live OpenAPI spec

πŸ€– Orval β€” generated API client

The React Query hooks and TypeScript DTOs under src/lib/api/ are generated by Orval from the API's OpenAPI document. Never edit them by hand. After changing an endpoint or DTO, run:

pnpm generate

(Make sure the API is running on http://localhost:5049 so Orval can fetch the spec.)


πŸ—„οΈ Database

  • Engine: PostgreSQL
  • ORM: EF Core 10 (Npgsql.EntityFrameworkCore.PostgreSQL)
  • Migrations: live in CleanArchitecture.Infrastructure.Persistence
  • Auto-apply: the dedicated CleanArchitecture.DbMigrator project runs migrations at startup before the API boots

Add a migration

dotnet ef migrations add <MigrationName> \
  --project CleanArchitecture.Infrastructure.Persistence \
  --startup-project CleanArchitecture.Presentation/API

πŸ’‘ An ApplicationDbContextFactory provides a design-time connection string so EF tools work without Aspire running.


☁️ Deploy to Azure with azd

The Aspire AppHost provisions everything for you:

  • 🚒 Azure Container Apps β€” API, admin, (optionally Keycloak)
  • 🐘 Azure Database for PostgreSQL Flexible Server
  • πŸ”’ Azure Key Vault β€” all secrets stored here automatically
  • πŸ“Š Azure Application Insights

Deploy

azd up

Parameters requested by azd

azd only prompts for values it cannot derive automatically. Public URLs (adminPublicUrl, apiPublicUrl, authPublicUrl) are derived from Container Apps endpoints β€” you don't need to enter them.

Always required

nextAuthSecret

When using Microsoft Entra ID (default for production)

EntraAPIInstance
EntraAPIPrimaryDomain
EntraAPIClientId
EntraAPIAudienceId
EntraTenantId
EntraAdminClientId
EntraAdminClientSecret
EntraAdminScope
EntraAdminOpenIdURL

When using Keycloak (UseKeycloak = true)

keycloakClientId
keycloakClientSecret
keycloakRealm
keycloakAdminUsername
keycloakAdminPassword
keycloakDbUsername
keycloakDbPassword

πŸ” All secret parameters (*Secret, *Password, nextAuthSecret) are written to Azure Key Vault automatically β€” they never live in plain text in your container apps.


πŸ§ͺ Testing

dotnet test --configuration Release
  • 🧬 Domain unit tests β€” Tests/Domain.UnitTests
  • πŸ›οΈ Architecture tests β€” enforce layer dependencies
  • πŸ”„ Integration tests β€” use DistributedApplicationTestingBuilder against a real Aspire fixture

The Testing environment uses an ephemeral Postgres and a TestAuthHandler that grants all roles, so no Keycloak or Entra setup is required.


🀝 Contributing

Pull requests are welcome! For major changes, please open an issue first to discuss what you'd like to change.

⭐ If you find this template useful, please star the repo β€” it really helps!


πŸ“„ License

MIT β€” use it freely as a foundation for your own projects.

About

Clean Architecture with Minimal API

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Contributors