Production-ready dotnet new templates for building .NET 10 services on the
Trellis framework — Domain-Driven Design + Railway-Oriented
Programming, with authorization, observability, tests, optional API versioning, and AI coding guidance wired in
from the first commit. Scaffold a service, press run, and start building.
| I want to build... | Template | dotnet new id |
NuGet |
|---|---|---|---|
| A single ASP.NET Core service | ASP.NET service | trellis-asp |
Trellis.Asp.Templates |
| A multi-service platform (gateway + services, .NET Aspire) | Microservices | trellis-microservices |
Trellis.Microservices.Templates |
Start with trellis-asp when you are building one service. Reach for trellis-microservices
when you need multiple services behind a gateway with asynchronous, cross-service messaging.
- .NET 10 SDK
- Microservices template only: Docker or Podman running (Aspire runs SQL Server and the Service Bus emulator as containers)
dotnet new install Trellis.Asp.Templates
dotnet new trellis-asp -n MyService
cd MyService
dotnet run --project Api/srcOpen the Scalar API reference at the URL printed on startup, or fire the ready-made requests in
Api/src/api.http. No containers or external database are needed to run the sample, and the generated
solution builds and its tests pass out of the box (dotnet test). You get a working Todo service —
delete it and build your own.
dotnet new install Trellis.Microservices.Templates
dotnet new trellis-microservices -n MyPlatform
cd MyPlatform
dotnet run --project AppHost/srcThis boots the .NET Aspire dashboard (http://localhost:15151) and brings up a Gateway
(YARP reverse proxy + internal-JWT minting) in front of two reference services — Members and
Projects. Open AppHost/src/*.http for click-to-run scenarios that walk the authorization outcomes
and the cross-service eventing flow (invite a member, then watch them appear in another service's team
list). The generated README.md is a full guided tour.
Both short names remain unchanged. APIs are unversioned by default; --api-versioning selects
the versioned sample instead of installing a separate template. Choices affect generated code,
dependencies, tests, and deployment assets, not just runtime configuration.
| Option | Choices | ASP default | Microservices default |
|---|---|---|---|
--api-versioning |
true, false |
false |
false |
--database |
sqlite (ASP only), postgres, sqlserver |
sqlite |
sqlserver |
--auth |
jwt, entra |
jwt |
jwt |
--telemetry-exporters |
otlp, azure-monitor, both |
otlp |
otlp |
--deployment |
none, container, azure |
none |
none |
--author-name |
Project author | Your Name |
Your Name |
--root-namespace |
Root C# namespace | Derived from -n |
Derived from -n |
--skip-restore |
Skip post-generation restore | false |
false |
dotnet new trellis-asp -n Billing --database postgres --api-versioning --auth entra --deployment container
dotnet new trellis-microservices -n Platform --database postgres --telemetry-exporters bothAzure selects App Service for ASP and Container Apps for microservices. It requires an explicit
--database postgres or --database sqlserver; ASP's SQLite/Azure combination fails restore, build,
and deployment preflight rather than silently changing the provider. --author-name avoids the
.NET CLI's reserved --author filter.
Authentication uses an external OIDC issuer or Entra ID, not a built-in user database. Development actors work only in Development. Production requires identity configuration, durable Cosmos idempotency, and, for the gateway, persistent private-key material. Aspire, messaging, tenancy, integration-event schema versions, and internal-JWT contract versions are independent of HTTP API versioning.
Both templates scaffold a clean, layered service (Domain -> Application -> Acl -> Api, each with its
own src/ and tests/) built around Trellis's Result<T> / Maybe<T> and always-valid value objects —
plus these cross-cutting capabilities, already wired and tested:
- Unversioned APIs, or date-based API versioning when selected
- Actor-based authorization — permission gates and per-resource/ownership checks
- RFC 9457 ProblemDetails error responses using Trellis's standard
code/kindenvelope - RFC 9110 conditional requests — strong ETags,
If-Match(412 / 428),If-None-Match-> 304 - RFC 8288 cursor (keyset) pagination with
Linkheaders - RFC 7240
Prefer: return=minimalon writes - Idempotent writes (
Idempotency-Key) — in-memory in Development, durable Cosmos storage required outside Development - Value-object validation — malformed scalars are rejected as 422 at the boundary, and commands are always-valid via
TryCreate - OpenAPI document + Scalar UI
- OpenTelemetry traces, metrics, and structured logs (including Service Level Indicators), with configuration-aware OTLP/Azure Monitor exporters
- Health checks
- EF Core with Trellis conventions (value-object mapping, timestamps, ETag/concurrency interceptors)
- Mediator pipeline — authorization and transactional unit-of-work behaviors
- Trellis composition APIs —
AddTrellismodules and the canonical ProblemDetails middleware
The microservices template adds the distributed pieces: a YARP gateway with internal-JWT minting and a JWKS endpoint, multi-tenant ABAC isolation, and a transactional outbox -> Azure Service Bus -> inbox flow for effectively-once, cross-service messaging.
Every generated project ships its architectural rules and coding conventions in AGENTS.md, the
canonical instructions for coding agents that support this format. .github/copilot-instructions.md
is a thin compatibility pointer to the same file.
Version-aligned API references live under .agentdocs/, installed by the pinned Trellis.AgentDocs
local tool. Managed pointers route agents to .agentdocs/README.md for required and on-demand references.
AgentDocs maintains only the marked pointer blocks in instruction files; curated rules live outside them.
After generating a project, initialize its Git root and refresh the recorded restore graph from there:
git init
dotnet tool restore
dotnet restore
dotnet tool run agentdocs sync
dotnet tool run agentdocs check --strictRepeat restore, sync, and check after package upgrades, and commit .config/dotnet-tools.json, the
managed pointers, .agentdocs/policy.json, and .agentdocs/ with the package update. Core approval
covers framework guidance; microservices, ResourceNaming, and SLI publishers are approved separately.
AgentDocs is optional for building and running the application.
- Trellis framework docs: https://xavierjohn.github.io/Trellis/
- This repo's docs site: https://xavierjohn.github.io/Trellis.Templates/
- Framework:
xavierjohn/Trellis—Result<T>,Maybe<T>, value objects, DDD primitives, ASP.NET / EF Core / Mediator integration - Microservices packages:
xavierjohn/Trellis.Microservices— YARP gateway integration + consumer-side actor provider for multi-tenant ABAC - Resource naming:
xavierjohn/Trellis.ResourceNaming— deterministic, CAF-aligned Azure resource names and endpoints; consumed by both templates as a published package
The two templates live in one repository so a single capability-parity contract keeps them from
drifting apart: a developer who picks either template should get the same guardrails.
shared/capability-parity-manifest.yaml is the source of truth
for the required cross-cutting capabilities. CI runs shared/contract-tests/
against generated option profiles and fails the build if a required capability is missing or regressed —
drift is caught by CI, not by human discipline. (A separate workflow instantiates each template with
dotnet new and builds the generated solution end to end.)
asp/ trellis-asp ASP.NET single-service template
microservices/ trellis-microservices Aspire multi-service template
shared/
capability-parity-manifest.yaml required capabilities (source of truth)
contract-tests/ runner that asserts each template implements the manifest
conventions/ cross-template conventions (e.g. Azure resource naming)
Run the contract check locally against a generated project. Its .trellis-template.json records the
selected options:
dotnet run --project shared/contract-tests -- shared/capability-parity-manifest.yaml microservices C:\Temp\MyPlatformMIT.