A production-ready foundation for building maintainable full stack applications with .NET, Angular, React and Next.js.
Use the .NET backend with either Angular or React/Next.js. The frontends are independent and should not be mixed within the same product.
- Clean Architecture backend with layered projects and clear boundaries
- CQRS with MediatR (Commands and Queries per feature)
- FluentValidation in handlers (
ValidateAndThrowAsync) - EF Core and FluentMigrator (InMemory for dev, SQL Server for production-style setups)
- Structured logging with Serilog
- External API integration with Refit
- Angular enterprise SPA option (ng-zorro, signals, Vitest)
- React / Next.js SaaS and SSR option (Ant Design, TanStack Query, App Router)
- Automated tests across backend and both frontends
- Docker support per application
- Independent frontends — choose one stack per product
| Scenario | Recommendation |
|---|---|
| Enterprise admin, traditional SPA, Angular team | frontend-angular/ — Angular 21 + ng-zorro |
| New SaaS, SSR, SEO, App Router, React ecosystem | frontend-react/ — React 19 + Next.js 16 + Ant Design |
| Same backend, different products | Use one frontend per product — do not mix Angular and React patterns in the same app |
Both frontends consume the same REST API and share UI route conventions (/products, /products/new, /products/:id/edit), but they are separate codebases. Pick the stack that fits your team and product; you normally choose one frontend when starting a new product.
flowchart LR
Angular[Angular SPA] --> API[ASP.NET Core API]
React[React / Next.js] --> API
API --> Application[Application / CQRS]
Application --> Domain[Domain]
Application --> Infrastructure[Infrastructure]
Infrastructure --> Database[(SQL Server)]
Infrastructure --> External[External APIs]
In development, the API can use an InMemory database instead of SQL Server (see Configuration).
Controller → MediatR → Handler → Repository/Service → Database or external API| Layer | Responsibility |
|---|---|
| Domain | Entities, repository and service interfaces |
| Application | Commands/Queries, handlers, validators (Features/) |
| Infrastructure | EF Core, repositories, HTTP integrations |
| Interface | Controllers, Program, middlewares, Swagger |
| CrossCutting | DTOs, options, helpers |
| Migration | FluentMigrator (SQL schema) |
| Tests | Mirror Application/Features/ |
Details: backend-dotnet/README.md.
| Tool | Minimum version | Notes |
|---|---|---|
| .NET SDK | 10.0.301+ | Pinned in backend-dotnet/global.json |
| Node.js | 24+ | See .nvmrc in each frontend folder |
| npm | 8+ (included with Node) | Use npm ci when package-lock.json is present |
| Docker | optional | Per-application Dockerfiles |
cd backend-dotnet
dotnet restore backend-dotnet.sln
dotnet run --project CleanStack.Interface- Swagger: https://localhost:5001/swagger
- HTTP API: http://localhost:5000
cd frontend-angular
npm ci
npm startcd frontend-react
npm ci
cp .env.example .env.local
npm run devApp: http://localhost:3000 — use another port if Angular is already running (npm run dev -- -p 3001).
Run the backend in parallel. Both frontends target
http://localhost:5000for the API in development.
CleanStack can be used as a GitHub repository template.
- Click Use this template on GitHub (enable Template repository under repository settings first).
- Create a new repository from the template.
- Choose either
frontend-angularorfrontend-reactfor your product. - Remove the unused frontend if it will not be maintained.
- Update application names, environment variables and connection settings.
- Review the roadmap before using the foundation in production.
clean-stack/
backend-dotnet/ → .NET 10 API (Clean Architecture + CQRS)
frontend-angular/ → Angular 21 SPA (ng-zorro)
frontend-react/ → React 19 + Next.js 16 (Ant Design)
docs/images/ → screenshots
.github/ → CI workflows, issue/PR templates
README.md
CONTRIBUTING.md
SECURITY.md
CODE_OF_CONDUCT.md
CHANGELOG.md
LICENSE| Project | Stack highlights |
|---|---|
backend-dotnet/ |
ASP.NET Core, EF Core, MediatR, FluentValidation, FluentMigrator, Refit, Serilog |
frontend-angular/ |
ng-zorro-antd, RxJS, Vitest |
frontend-react/ |
Ant Design, TanStack Query, Axios, React Hook Form, Zod, Vitest |
Run these before opening a pull request for the affected area:
# Backend
cd backend-dotnet
dotnet restore backend-dotnet.sln
dotnet build backend-dotnet.sln --configuration Release
dotnet test backend-dotnet.sln --configuration Release
# Angular
cd frontend-angular
npm ci
npm run build
npm test
# React
cd frontend-react
npm ci
npm run lint
npm run test
npm run build| Variable / key | Description |
|---|---|
ConnectionStrings__Default |
SQL Server connection string |
Database:Provider |
InMemory (dev default) or SqlServer |
ExternalProductApi__BaseUrl |
External API URL (e.g. FakeStore) |
| File | Key |
|---|---|
src/environments/environment.development.ts |
apiBaseUrl (http://localhost:5000) |
Copy .env.example to .env.local:
| Variable | Description |
|---|---|
NEXT_PUBLIC_API_BASE_URL |
API base URL (e.g. http://localhost:5000) |
NEXT_PUBLIC_APP_NAME |
App display name and SEO tags |
NEXT_PUBLIC_SITE_URL |
Public site URL (metadata, sitemap, Open Graph) |
Build images from each project directory:
| Service | Dockerfile |
|---|---|
| API | backend-dotnet/CleanStack.Interface/Dockerfile |
| Migration | backend-dotnet/CleanStack.Migration/Dockerfile |
| Angular | frontend-angular/Dockerfile |
| React | frontend-react/Dockerfile |
# API (from backend-dotnet/)
docker build -t cleanstack-api:latest -f CleanStack.Interface/Dockerfile .
# Angular (from frontend-angular/)
docker build -t cleanstack-angular:latest .
# React (from frontend-react/)
docker build -t cleanstack-react:latest .A root docker-compose.yml is planned once SQL Server, migrations and services can start together without code changes (see Roadmap).
- Real JWT authentication in the backend (
/api/auth/login) - Route guard / middleware in
frontend-react
- Align API contracts between Angular and React (
Product.Idlong vs string) - Decouple Domain from CrossCutting / Refit (dependency inversion)
- Global
401interceptor in React when real auth exists
- Document minimum Node version in per-frontend
.nvmrcfiles - Root
docker-compose.ymlwith SQL Server, migrations and profile-based frontends
- Migration Docker: copy
appsettings.jsonin Release and support environment variables
Complementary skills in maurao-skills:
npx skills add luismpenholato/maurao-skills --skill dotnet-backend-clean-architecture
npx skills add luismpenholato/maurao-skills --skill angular-frontend-clean-architecture
npx skills add luismpenholato/maurao-skills --skill react-nextjs-antd-clean-architectureSee CONTRIBUTING.md for setup, conventions, and the pull request workflow.
For structural changes, open an architecture discussion before large refactors.
Report vulnerabilities privately — do not open public issues. See SECURITY.md.
- Issues for bugs and feature requests
- GitHub Sponsors to support ongoing maintenance
This project is licensed under the MIT License.
| Document | Description |
|---|---|
| Contributing | How to contribute, standards, and PR workflow |
| Security | Responsible vulnerability reporting |
| Code of Conduct | Community standards |
| Changelog | Notable changes |
| License | MIT License |


