DotnetForge 2.7.0
dotnet tool install --global DotnetForge --version 2.7.0
dotnet new tool-manifest
dotnet tool install --local DotnetForge --version 2.7.0
#tool dotnet:?package=DotnetForge&version=2.7.0
nuke :add-package DotnetForge --version 2.7.0
DotnetForge
Production-ready .NET 10 project templates. One NuGet package, three templates.
Quick Start
# Install the CLI tool (recommended)
dotnet tool install -g DotnetForge
# Interactive wizard — prompts for everything
dotnet forge new
# Specify your app name, prompts for remaining options
dotnet forge new MyApp
# Fully non-interactive
dotnet forge new MyApp --template forge-aspire --auth keycloak --include-react-email
# Build and run
cd MyApp
dotnet run --project src/MyApp.AppHost
The CLI auto-installs DotnetForge.Templates on first run if missing. To update:
dotnet tool update -g DotnetForge
Templates
| Template | Command | What you get |
|---|---|---|
| Forge API | dotnet forge new MyApp -t forge-api |
Standalone Minimal API with OpenTelemetry, health checks, resilience |
| Forge Aspire | dotnet forge new MyApp -t forge-aspire |
API + .NET Aspire orchestration + Azure deployment |
| Forge Full-Stack | dotnet forge new MyApp -t forge-fullstack |
API + Aspire + React frontend (Vite/Bun) + Docker deployment |
| Forge Email (item) | dotnet new forge-email -n PasswordReset |
Scaffold a new email action + model + React Email template |
CLI Flags
| Flag | Default | Description |
|---|---|---|
[name] |
(prompted) | Project name (PascalCase). Auto-generates lowercase variants for config. |
-t, --template |
(prompted) | Template short name: forge-api, forge-aspire, forge-fullstack |
-o, --output |
current dir | Output directory |
--auth-provider / --auth |
(prompted) | Identity provider: keycloak or entra |
--entra-tenant-id |
common |
Microsoft Entra ID tenant ID (only when --auth entra) |
--entra-client-id |
YOUR_CLIENT_ID |
Microsoft Entra ID application (client) ID (only when --auth entra) |
--entra-domain |
yourtenant.onmicrosoft.com |
Microsoft Entra ID tenant domain (only when --auth entra) |
--include-react-email |
false |
Include React Email template system (Bun + MailKit + Scriban) |
When a flag is omitted, the CLI prompts interactively. In non-interactive terminals (CI/pipes), template and name are required.
Manual Install (without CLI)
You can also install templates directly and use dotnet new:
dotnet new install DotnetForge.Templates
dotnet new forge-aspire -n MyApp
dotnet new forge-aspire -n MyApp --auth-provider entra
dotnet new forge-api -n MyApp --auth entra --entra-tenant-id abc123 --entra-client-id def456
# Add a new email action to an existing project
dotnet new forge-email -n PasswordReset
What's Included
API (forge-api / forge-aspire / forge-fullstack)
- .NET 10 Minimal APIs with feature-slice architecture
- Keycloak or Microsoft Entra ID authentication + role-based authorization
- PostgreSQL with EF Core, migrations, Ulid primary keys
- FusionCache L1 memory + L2 Redis with backplane
- JSON:API compliant responses via JsonApiKit (cursor + offset pagination)
- MediaKit file storage (Local, S3, SeaweedFS, RustFS, Azure Blob/Azurite) with image conversions
- Scalar API docs with OAuth2 Authorization Code flow
- Rate limiting (Global, PublicRead, Authenticated, AdminWrite policies)
- FluentValidation + ErrorOr result pattern
- Domain events via EF Core interceptors
- xUnit v3 unit tests + k6 performance tests
- ArchUnitNET architecture tests (dependency direction, naming, endpoint conventions)
Aspire Orchestration (forge-aspire / forge-fullstack)
- PostgreSQL, Redis containers with data volumes (Keycloak container when using Keycloak auth)
- DbGate web-based database management (persistent, for Postgres and Redis)
- Configurable storage — S3-compatible (RustFS, SeaweedFS) or Azure Blob (Azurite emulator)
- Enterprise publisher for deployment documentation
- Aspire Dashboard with seed data command
- Azure Container Apps deployment via
azd up - Feature/integration tests with
Aspire.Hosting.Testing
React Frontend (forge-fullstack only)
- React 19 + TypeScript + Vite + Bun (auto-installed via
WithBunPackageInstallation()) - TanStack Router + Query
- Radix UI + Tailwind CSS 4
- oidc-spa OIDC integration (Keycloak or Entra ID)
- i18n via i18next
- Orval API client generation from OpenAPI
- Docker multi-stage build with nginx
Setting up Microsoft Entra ID
When using --auth-provider entra, you need an Azure App Registration:
- Create App Registration in Azure Portal → Microsoft Entra ID → App registrations
- Add App Roles (e.g.,
admin,author,reader) under App roles → Create app role - Configure API Permissions → Expose an API → Add a scope (e.g.,
api://<client-id>/access_as_user) - For the React frontend (forge-fullstack): Create a second App Registration (SPA type) with redirect URI
http://localhost:5173 - Update
appsettings.jsonwith your Tenant ID, Client ID, and Domain
The Entra parameters are optional at project creation — you can leave the defaults and configure appsettings.json later:
# Minimal — configure in appsettings.json after project creation
dotnet new forge-api -n MyApp --auth entra
# Or provide values upfront
dotnet new forge-api -n MyApp --auth entra \
--entra-tenant-id your-tenant-id \
--entra-client-id your-client-id \
--entra-domain yourtenant.onmicrosoft.com
Architecture
MyApp/
├── src/
│ ├── MyApp.Api/ # Minimal API
│ │ ├── Data/ # Repositories + cached decorators
│ │ ├── Entities/ # Domain entities (Book, Author, Category)
│ │ ├── Features/ # Feature slices (Admin, Public, Dev)
│ │ ├── Infrastructure/ # Auth, caching, validation, etc.
│ │ ├── Migrations/ # EF Core migrations
│ │ └── Services/ # Cross-cutting services
│ ├── MyApp.AppHost/ # Aspire orchestrator (aspire/fullstack)
│ ├── MyApp.AppHost.Extensions/ # Enterprise publisher
│ ├── MyApp.ServiceDefaults/ # Shared OTel + health + resilience
│ ├── MyApp.Web/ # React frontend (fullstack)
│ └── MyApp.KeycloakTheme/ # Keycloakify theme (fullstack, Keycloak only)
├── tests/
│ ├── MyApp.Api.ArchitectureTests/ # ArchUnitNET architecture rules
│ ├── MyApp.Api.UnitTests/ # xUnit v3 + NSubstitute
│ ├── MyApp.Api.FeatureTests/ # Aspire integration tests (aspire/fullstack)
│ └── MyApp.PerformanceTests/ # k6 load tests
├── MyApp.slnx # Solution file
├── docker-compose.api.yml # Production API deployment
└── docker-compose.api.build.yml # Local API build
Architecture Tests
Every scaffolded project includes automated architecture tests powered by ArchUnitNET that enforce the feature-slice conventions and prevent architectural drift.
Enforced Rules
Endpoint Conventions (EndpointArchitectureTests)
IEndpointimplementations must reside in theFeaturesnamespace- Endpoint classes must not be abstract
- Endpoint classes must be sealed
Dependency Direction (DependencyArchitectureTests)
Entitiesmust not depend onFeatures,Infrastructure, orDataInfrastructuremust not depend onFeaturesDatamust not depend onFeatures- No cross-feature slice dependencies (e.g.,
Features.Admin.Booksmust not referenceFeatures.Admin.Authors)
Naming Conventions (NamingConventionTests)
- Interfaces start with
I - Validators end with
Validatorand reside inFeatures - Repository interfaces reside in
Data - Cached decorators reside in
Data.Cached - Entity classes in
Entitiesinherit fromBaseEntity - No public fields in entities
Configuration
Rules are enabled by default. To disable enforcement (tests skip instead of fail), edit tests/MyApp.Api.ArchitectureTests/appsettings.Testing.json:
{
"ArchitectureTests": {
"EnforceRules": false
}
}
When disabled, all tests are skipped during dotnet test but remain available for manual verification.
Deployment Options
Azure (Aspire + Full-Stack)
azd init
azd up
Docker Compose (all templates)
docker compose -f docker-compose.api.build.yml up -d
GitHub Actions
- deploy-azure.yml — Azure Container Apps via
azd(aspire/fullstack) - deploy-docker.yml — Multi-arch Docker build + webhook deploy (fullstack)
Sample Domain
The template includes a Books Management sample domain with:
- Book — title, ISBN, description, cover image, gallery
- Author — name, biography, avatar
- Category — name, description, icon
This gives you working CRUD endpoints, relationships, media uploads, caching, and search — all wired up and ready to extend. See SAMPLE_DOMAIN.md for details.
Development (Template Authors)
Repository Structure
dotnet-forge/
├── shared/ # Common files across all templates (edit here)
├── overrides/ # Template-specific file variants (edit here)
│ ├── forge-api/
│ ├── forge-aspire/
│ └── forge-fullstack/
├── template-configs/ # .template.config per template
├── templates/ # BUILD OUTPUT (git-ignored)
├── src/
│ └── DotnetForge.Cli/ # Interactive CLI tool (dotnet forge)
├── build.ps1 # Assembles templates from shared + overrides
└── DotnetForge.Templates.csproj
Build & Test
# Assemble templates
./build.ps1
# Install locally
dotnet new install ./templates/forge-api
dotnet new install ./templates/forge-aspire
dotnet new install ./templates/forge-fullstack
# Test
dotnet new forge-aspire -n TestApp
cd TestApp && dotnet build
# Package
dotnet pack DotnetForge.Templates.csproj
# Build CLI tool
dotnet build src/DotnetForge.Cli/
dotnet pack src/DotnetForge.Cli/DotnetForge.Cli.csproj --output ./artifacts
dotnet tool install --global --add-source ./artifacts DotnetForge
Uninstall
# CLI tool
dotnet tool uninstall -g DotnetForge
# Templates only
dotnet new uninstall DotnetForge.Templates
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.