LFZ.Templates
1.0.0
dotnet new install LFZ.Templates@1.0.0
LFZ.Templates
A .NET 8 starter template for Lagos Free Zone services. Generates a five-project solution wired with Clean Architecture, CQRS, MediatR, FluentValidation, EF Core 8 (SQL Server), and a Blazor WebAssembly PWA frontend — installable from the dotnet CLI and discoverable in the Visual Studio "New Project" dialog.
LFZ = Lagos Free Zone. This package is the canonical scaffold used by Lagos Free Zone engineering for new line-of-business services and internal tools, so every new app starts from the same architectural baseline.
What you get
Running the template scaffolds a complete solution with five projects following the onion / Clean Architecture dependency rule:
| Project | Responsibility |
|---|---|
<Name>.Domain |
Entities, value objects, domain events. Pure C#, no framework dependencies. |
<Name>.Application |
CQRS commands, queries, handlers, validators, MediatR pipeline behaviors. |
<Name>.Infrastructure |
EF Core ApplicationDbContext, entity configurations, external I/O. |
<Name>.API |
ASP.NET Core Web API. Controllers, Swagger, exception-handling middleware. |
<Name>.UI |
Blazor WebAssembly PWA. Calls the API over HTTP. |
Solution file is <Name>.UI.slnx (SLNX format). All projects target net8.0.
Wired and ready
- MediatR 14.1.0 with a pipeline of
UnhandledExceptionBehavior→ValidationBehavior→LoggingBehavioraround every handler. - FluentValidation 12.1.1 auto-discovered from the Application assembly; failures become HTTP 400
ValidationProblemDetailsvia API middleware. - EF Core 8.0.11 / SqlServer.
ApplicationDbContextimplements anIApplicationDbContextabstraction so Application code never depends on a concreteDbContext. - Swashbuckle 6.6.2 Swagger UI in Development.
- Exception → HTTP mapping via
ExceptionHandlingMiddleware:ValidationException→ 400,NotFoundException→ 404, anything else → 500 (logged). - Blazor WASM PWA with a registered
HttpClient, default layout, and nav. - Agent guide (
CLAUDE.md) shipped alongside the solution describing layer conventions, the feature-addition recipe, and anti-patterns — renamed automatically to reference your project name.
Architecture at a glance
+----------+ +-----------------+ +-------------------+
| Domain | <---- | Application | <---- | Infrastructure |
+----------+ +-----------------+ +-------------------+
^ ^
| |
+----+----+ |
| API | <--------------------+
+---------+
^
| HTTP only
|
+-------+
| UI | (Blazor WASM PWA)
+-------+
Dependencies point inward. The UI talks to the API over HTTP — no project reference.
Install
From any console:
dotnet new install LFZ.Templates
Or from a local .nupkg (development / internal feed):
dotnet new install ./LFZ.Templates.1.0.0.nupkg
Visual Studio 2022 (17.x) auto-discovers dotnet new templates — restart VS once after install and the template appears in File → New → Project, filterable under C# / Web / Cloud.
Use
From the CLI
dotnet new lfz-clean -n CustomerPortal -o ./CustomerPortal
cd CustomerPortal
dotnet build CustomerPortal.UI.slnx
The -n value is substituted for LFZ throughout the scaffold — file names, folder names, namespaces, project references, and the contents of CLAUDE.md are all rewritten. So dotnet new lfz-clean -n CustomerPortal produces:
CustomerPortal/
CustomerPortal.UI.slnx
CLAUDE.md
CustomerPortal.Domain/
CustomerPortal.Application/
CustomerPortal.Infrastructure/
CustomerPortal.API/
CustomerPortal.UI/
From Visual Studio
- File → New → Project
- Search for LFZ Clean Architecture Solution
- Set the Project name (this is the value used to rename
LFZeverywhere) - Create
The "Project name" you type flows into the same sourceName substitution as the CLI's -n flag.
After scaffolding
Set the connection string. Edit
<Name>.API/appsettings.json→ConnectionStrings:DefaultConnection. Default points at LocalDB with a database name derived from your project name. For non-local secrets, use User Secrets or environment variables rather than committing credentials.Create the database. From the solution root:
dotnet ef migrations add InitialCreate --project <Name>.Infrastructure --startup-project <Name>.API dotnet ef database update --project <Name>.Infrastructure --startup-project <Name>.APIRun the API.
dotnet run --project <Name>.APISwagger is served at
/swaggerin Development.Run the UI.
dotnet run --project <Name>.UIUpdate
<Name>.UI/Program.csso theHttpClientBaseAddresspoints at the API URL — by default it uses the WASM host's base address.
Adding a feature (vertical slice)
The template ships with a documented recipe in CLAUDE.md. Summary for a "Customer" feature:
- Domain →
<Name>.Domain/Customers/Customer.csinheritingBaseEntity. - Application interface → add
DbSet<Customer> Customers { get; }toIApplicationDbContext. - Infrastructure → add
DbSet<Customer>toApplicationDbContext; add aCustomerConfiguration : IEntityTypeConfiguration<Customer>underPersistence/Configurations/. - Migration →
dotnet ef migrations add AddCustomer ... && dotnet ef database update ... - Application handlers under
<Name>.Application/Features/Customers/:Commands/CreateCustomer/-- command, handler, validatorQueries/GetCustomerById/-- query, handler, DTO
- API →
<Name>.API/Controllers/CustomersController.csinjectingIMediator. - UI (optional) → Blazor page calling
api/customers.
Validators are picked up automatically. Application handlers never return EF entities to callers — use DTOs.
What stays unchanged in the template
- Inward-only dependency rule (Domain has zero project references).
- Pipeline behavior order (
UnhandledException→Validation→Logging). - API controllers stay thin (HTTP →
IMediator.Send→ result). Business rules live in handlers. - Persistence is accessed only through
IApplicationDbContextfrom Application code.
Anti-patterns explicitly called out in CLAUDE.md include: referencing EF Core from Domain, returning entities from controllers, injecting handlers directly instead of IMediator, catching ValidationException/NotFoundException in handlers, and bypassing FluentValidation with manual checks.
Known gaps
The scaffold includes wiring points that are intentionally left for the consumer to complete:
IAuditableEntityexists; noSaveChangesinterceptor populatesCreatedAt/CreatedByyet.IDomainEventcollection exists onBaseEntity; no dispatcher publishes events viaIMediator.Publishyet.- No authentication / authorization scheme is configured (
UseAuthorization()is called, but no auth pipeline). - No CORS policy between the WASM UI and API.
- Template scaffolding (
WeatherForecastController,WeatherForecast.cs,Weather.razor) is shipped as a working sample — remove when real features land. - No test projects in the solution.
Uninstall
dotnet new uninstall LFZ.Templates
To list every installed template package: dotnet new uninstall (no args).
Template parameters
| Parameter | Description | Default |
|---|---|---|
-n, --name |
Project name. Substitutes LFZ throughout the scaffold. |
(required) |
-o, --output |
Output directory. | ./ |
Versioning
1.0.0-- Initial release. .NET 8, Clean Architecture, CQRS, MediatR 14.x, Blazor WASM.
Maintainer
Lagos Free Zone Engineering.
-
net8.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 |
|---|---|---|
| 1.0.0 | 282 | 5/25/2026 |