Compiler-enforced guardrails for .NET.
Trellis is an opinionated .NET service framework with compiler and analyzer guardrails that make generated code more predictable. It turns typed errors, validated value objects, and composable application pipelines into structure the compiler can enforce — so a whole class of common mistakes fails at build time, whether the code is written by a human or an AI assistant.
📺 Watch the series: youtube.com/@trellisdev — Railway-Oriented Programming, Domain-Driven Design, and more.
Without Trellis
if (string.IsNullOrWhiteSpace(request.Email))
return Results.BadRequest(new { code = "email.required", detail = "Email is required." });
if (!request.Email.Contains('@'))
return Results.BadRequest(new { code = "email.invalid", detail = "Email is invalid." });
return Results.Ok(new User(request.Email.Trim().ToLowerInvariant()));With Trellis
using Trellis.Asp;
using Trellis.Primitives;
return EmailAddress.TryCreate(request.Email)
.Map(email => new User(email))
.ToHttpResponse();- Compiler-enforced guardrails — Roslyn analyzers and types so a whole class of illegal states won't compile; humans and AI stay on the happy path.
Result<T>andMaybe<T>pipelines that make failures explicit — no exceptions for control flow.- Strongly typed value objects that eliminate primitive obsession.
- DDD building blocks:
Aggregate,Entity,ValueObject,Specification, and domain & integration events. - Reliable, crash-safe event delivery via a transactional outbox — events persist atomically with state and relay after commit.
- ASP.NET Core, EF Core, Mediator, HttpClient, FluentValidation, and state-machine integrations.
- AOT-friendly, allocation-conscious APIs built for modern .NET.
AOT: per-package APIs are trim- and AOT-safe;
Trellis.ServiceDefaultsexposes both AOT-safe per-type overloads and assembly-scanning overloads (annotated so the AOT analyzer flags the choice).Trellis.EntityFrameworkCorefollows EF Core's own AOT policy. See the docs for details.
Trellis requires the .NET SDK 10.0.300 or later (Roslyn 5.6+).
Trellis.Core, Trellis.Asp, and Trellis.EntityFrameworkCore ship source generators, and Trellis.Analyzers ships analyzers, all compiled against Roslyn 5.6. On an older SDK the compiler reports CS9057 and skips them — the generated members simply never appear, which surfaces as confusing "missing member" build errors rather than an obvious version complaint.
Add the library:
dotnet add package Trellis.Coreusing Trellis;
var result = Result.Ok("ada@example.com")
.Ensure(email => email.Contains('@'),
Error.InvalidInput.ForField("email", ValidationCodes.StringEmail, "Email is invalid."))
.Map(email => email.Trim().ToLowerInvariant());Or scaffold a full production-ready service — Clean Architecture, API versioning, EF Core, OpenAPI, and tests — with the trellis-asp template:
dotnet new trellis-asp -n MyServiceStart with Trellis.Core; add only the integrations your application uses. Trellis.ServiceDefaults is the opinionated composition root for web services.
| Package | Use it for |
|---|---|
| Trellis.Core | Result<T>, Maybe<T>, typed errors, DDD building blocks, pagination, and source-generated value-object bases |
| Trellis.Primitives | Ready-to-use value objects such as EmailAddress, Money, and Url |
| Trellis.Analyzers | Compile-time guidance for Result, Maybe, EF Core, and value-object usage |
| Package | Use it for |
|---|---|
| Trellis.Asp | Result-to-HTTP mapping, Problem Details, scalar validation, idempotency middleware, and actor providers |
| Trellis.Asp.ApiVersioning | Destination-aware versioned Location and pagination URLs |
| Trellis.Authorization | Actors, permissions, attributes, and resource-authorization contracts |
| Trellis.FluentValidation | Standalone FluentValidation-to-Result conversion |
| Trellis.Mediator | Result-aware validation, authorization, tracing, logging, and transaction behaviors for Mediator |
| Trellis.Mediator.FluentValidation | FluentValidation inside the Trellis Mediator validation stage |
| Trellis.ServiceDefaults | Canonically ordered composition of Trellis web-service modules |
| Trellis.StateMachine | Stateless transitions that return Result<TState> |
| Package | Use it for |
|---|---|
| Trellis.Http.Abstractions | Shared HTTP faults, ETags, preconditions, retry values, and write outcomes |
| Trellis.Http | HttpClient calls that stay inside Result and Maybe pipelines |
| Trellis.Persistence.Abstractions | Store-neutral unit-of-work, inbox-store, and checkpoint contracts |
| Trellis.EntityFrameworkCore | EF Core conventions, converters, Maybe queries, pagination, and safe persistence |
| Trellis.EntityFrameworkCore.Outbox | Crash-safe transactional domain and integration-event delivery |
| Trellis.EntityFrameworkCore.Inbox | Idempotent integration-event consumption within an EF Core unit of work |
| Trellis.Asp.Idempotency.Cosmos | Distributed Cosmos DB store for the ASP idempotency middleware |
| Trellis.Messaging.AzureServiceBus | Azure Service Bus transport between the transactional outbox and inbox |
| Package | Use it for |
|---|---|
| Trellis.Testing | FluentAssertions extensions, fake repositories, and test actor providers |
| Trellis.Testing.AspNetCore | WebApplicationFactory, dependency replacement, fake time, and .http replay helpers |
| Trellis.Testing.Idempotency | Executable conformance tests for custom IIdempotencyStore implementations |
| Trellis.Testing.Worker | Deterministic integration testing for BackgroundService workers |
Typical overhead is measured in single-digit to low double-digit nanoseconds—tiny next to a database call or HTTP request. Benchmarks
- 📺 YouTube — @trellisdev: the Trellis video series covering Railway-Oriented Programming, Domain-Driven Design, and more.
- Full documentation
- Getting started
- With vs without Trellis
- API reference
- Training lab + AI consistency benchmark — hand an AI model Trellis, a template, and a spec; let it ship a service in one shot; score against 66 criteria across 6 quality levels.
The Trellis family extends the core framework into multi-service topologies, ready-to-scaffold templates, and operational telemetry. All packages live on nuget.org; all repos share the same MIT license, branch-protected main, and analyzer gates.
xavierjohn/Trellis.Microservices— microservice trust-boundary packages: YARP gateway that mints internal-network JWTs + consumer-side actor provider enforcing a strict claim contract that defends multi-tenant ABAC. ShipsTrellis.Microservices.Abstractions,Trellis.Microservices.AspNetCore,Trellis.Yarp.xavierjohn/Trellis.Microservices.Template—dotnet new trellis-microservicestemplate scaffolding a multi-tenant Project Tracker (YARP gateway + Projects + Members + Aspire AppHost) that demonstrates resource auth, the HideExistence pattern, and the deny-overrides-allow JWT contract.xavierjohn/Trellis.AspTemplate—dotnet new trellis-asptemplate scaffolding a production-ready single-service ASP.NET application with Clean Architecture layout (API + Application + Domain + ACL), API versioning, EF Core, OpenAPI, and test infrastructure.xavierjohn/Trellis.ServiceLevelIndicators— latency SLI metrics library for emitting operation-duration histograms viaSystem.Diagnostics.Metrics+ OpenTelemetry, with rich dimensions (CustomerResourceId,LocationId,Operation,Outcome) and ASP.NET Core + API-versioning integrations.xavierjohn/trellis-training— training lab + AI consistency benchmark: give an AI model Trellis, a template, and a business spec; let it ship a service in one shot; score against 66 criteria across 6 quality levels.
Contributions are welcome. For major changes, please open an issue first and run dotnet test before sending a PR.
