DotnetForge.Templates
2.17.0
dotnet new install DotnetForge.Templates::2.17.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
# Browser-based UI — visual form with all options
dotnet forge new --ui
# 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 (auto-detects AppHost or API project)
cd MyApp
dotnet forge watch
# Or run explicitly
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) |
--ui |
false |
Open browser-based project configuration form |
When a flag is omitted, the CLI prompts interactively. In non-interactive terminals (CI/pipes), template and name are required.
Browser UI (--ui)
Run dotnet forge new --ui to open a browser-based project configuration wizard instead of terminal prompts. The wizard walks you through five steps: Template → Platform → Project Details → Configure → Review & Create.
Features
- Multi-step wizard with animated transitions between steps
- Dark / Light / System themes — defaults to dark mode with a warm industrial-forge aesthetic. Light mode uses a warm parchment palette. Toggle with the theme button in the header or
Ctrl+D. - Platform-independent auth — choosing a platform (Self-Hosted, Azure) sets a sensible default auth provider, but you can switch between Keycloak and Entra ID on the Configure step regardless of platform
- Conditional sections — AppHost storage and Docker options appear only when the selected template supports them
- Real-time validation — PascalCase project name enforcement with live preview of generated project names
Keyboard Shortcuts
The entire wizard is fully keyboard-navigable — no mouse required.
| Key | Action |
|---|---|
← → ↑ ↓ |
Navigate between cards and options |
Enter / Space |
Select focused item |
Tab / Shift+Tab |
Move between form fields |
1–5 |
Jump directly to a wizard step |
Esc |
Go back to previous step |
Ctrl+D |
Toggle theme (Dark → Light → System) |
? |
Show keyboard shortcuts overlay |
Development (UI only)
For hot-reload UI development:
# Terminal 1: Start the API server
dotnet run --project src/DotnetForge.Cli/ -- new --ui
# Terminal 2: Start Vite dev server with HMR
cd src/DotnetForge.Cli/ui && npm run dev
# Open http://localhost:5299
To skip the UI build during C#-only development, pass -p:BuildUi=false to dotnet build.
Watch Command
Auto-detect and run a project with dotnet watch:
# Auto-detect project type (Aspire AppHost → API fallback)
dotnet forge watch
# Search a specific directory
dotnet forge watch ./src
# Explicit project path (skip detection)
dotnet forge watch --project src/MyApp.AppHost/MyApp.AppHost.csproj
# Force target type
dotnet forge watch --target aspire
dotnet forge watch --target api
| Flag | Description |
|---|---|
[directory] |
Directory to search (defaults to current directory) |
-p, --project |
Explicit .csproj path (skips auto-detection) |
-t, --target |
Force target type: aspire or api |
Detection priority: Aspire AppHost projects are detected first (by IsAspireHost, Aspire.Hosting, or Aspire.AppHost.Sdk markers in .csproj). If none found, falls back to API projects matching *.Api.csproj. When multiple projects are found, an interactive prompt lets you pick one.
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 Azure App Registration(s).
API App Registration
- Create App Registration in Azure Portal > Microsoft Entra ID > App registrations
- Platform type: Web (no redirect URI needed for the API)
- Under Authentication > Implicit grant: leave both checkboxes unchecked (uses PKCE)
- Expose an API > Add a scope:
- Application ID URI:
api://<client-id>(auto-generated) - Scope name:
access_as_user - Who can consent: Admins and users
- Application ID URI:
- App Roles > Create app role:
- Display name:
Admin, Value:admin, Allowed member types: Users/Groups - Repeat for other roles as needed (
author,reader)
- Display name:
- Assign roles to users: Go to Enterprise Applications > your app > Users and groups > Add user/group > select role
- Update
appsettings.jsonwith your Tenant ID, Client ID, and Domain
SPA App Registration (forge-fullstack only)
- Create a second App Registration for the Web app:
- Platform type: Single-page application (SPA)
- Redirect URIs:
http://localhost:5173(add production URL later) - Implicit grant: leave both checkboxes unchecked (uses PKCE)
- API Permissions on the SPA app:
- Add a permission > My APIs > select the API app > Delegated permissions > select
access_as_user
- Add a permission > My APIs > select the API app > Delegated permissions > select
- Update
.envwith SPA Client ID, API Client ID, and Authority URL
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
}
}
Alternatively, override via environment variable (useful in CI):
ArchitectureTests__EnforceRules=false dotnet test
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
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.17.0 | 188 | 3/23/2026 |
| 2.15.0 | 188 | 3/16/2026 |
| 2.10.2 | 187 | 3/12/2026 |
| 2.10.0 | 187 | 3/12/2026 |
| 2.9.0 | 184 | 3/12/2026 |
| 2.7.1 | 183 | 3/7/2026 |
| 2.7.0 | 188 | 3/6/2026 |
| 2.6.2 | 178 | 3/5/2026 |
| 2.6.1 | 180 | 3/5/2026 |
| 2.6.0 | 184 | 3/5/2026 |
| 2.5.1 | 180 | 3/5/2026 |
| 2.1.0 | 193 | 3/3/2026 |
| 2.0.4 | 184 | 3/3/2026 |
| 2.0.3 | 188 | 3/2/2026 |
| 1.2.0 | 199 | 3/2/2026 |
| 1.1.0 | 211 | 3/1/2026 |
| 1.0.0 | 194 | 2/28/2026 |