Skip to content

CLI Templates ​

Gryd.IO provides CLI templates for dotnet new to quickly scaffold new projects with the correct structure and dependencies.

Installation ​

From NuGet (Production) ​

Install all Gryd.IO templates from NuGet:

bash
dotnet new install Gryd.IO.Templates

From Local Packages (Development) ​

If you're developing or testing locally, install from the local-packages folder:

bash
# Navigate to the Gryd.IO repository
cd /path/to/Gryd.IO

# Install each template individually
dotnet new install ./templates/gryd-api
dotnet new install ./templates/gryd-minimal
dotnet new install ./templates/gryd-module

Verify Installation ​

List all installed Gryd templates:

bash
dotnet new list gryd

Expected output:

Template Name    Short Name     Language  Tags
--------------   -----------    --------  ----
Gryd API         gryd-api       [C#]      Web/API/Gryd
Gryd Minimal     gryd-minimal   [C#]      Web/API/Gryd
Gryd Module      gryd-module    [C#]      Library/Gryd/Module

Available Templates ​

TemplateShort NameDescription
Gryd APIgryd-apiComplete API with Auth + Crud modules
Gryd Minimalgryd-minimalMinimal API with Core packages only
Gryd Modulegryd-moduleClean Architecture module structure

gryd-api ​

Complete API template with optional GrydAuth and GrydCrud integration, Docker support, and database configuration.

Usage ​

bash
# Create with defaults (Auth + Crud + PostgreSQL + Docker)
dotnet new gryd-api -n MyApiProject

# Create without authentication
dotnet new gryd-api -n MyApiProject --IncludeAuth false

# Create with SQL Server instead of PostgreSQL
dotnet new gryd-api -n MyApiProject --UsePostgres false --UseSqlServer true

# Create without Docker support
dotnet new gryd-api -n MyApiProject --IncludeDocker false

Parameters ​

ParameterTypeDefaultDescription
--IncludeAuthbooltrueInclude GrydAuth for authentication/authorization
--IncludeCrudbooltrueInclude GrydCrud for CRUD operations
--UsePostgresbooltrueConfigure PostgreSQL as database
--UseSqlServerboolfalseConfigure SQL Server as database
--IncludeDockerbooltrueInclude Dockerfile and docker-compose.yml
--IncludeJobsboolfalseInclude GrydJobs for background jobs
--IncludeReportsboolfalseInclude GrydReports. Brings GrydFiles, GrydJobs and the ClamAV scanner registration with it
--IncludeNotificationsboolfalseInclude GrydNotifications. Brings GrydFiles, GrydJobs and the ClamAV scanner registration with it

Reports and Notifications keep their files in GrydFiles (generated reports, e-mail attachments), so either flag also registers the object storage, AddGrydFiles with the ClamAV engine and GrydJobs, which runs the file checks. The GrydFiles section of appsettings.json declares the gryd.report and gryd.notification-attachment profiles the two modules require. GrydReports cannot run without GrydFiles; GrydNotifications needs it only for e-mail attachments, so a product that sends none can remove the GrydFiles registration and its section (see Email with Attachments).

Generated Structure ​

MyApiProject/
├── MyApiProject.csproj          # Project with Gryd packages
├── Program.cs                    # Startup with DI configuration
├── appsettings.json             # Production configuration
├── appsettings.Development.json # Development configuration
├── README.md                    # Project documentation
├── Controllers/
│   └── ProductsController.cs    # Example CRUD controller
├── Data/
│   └── AppDbContext.cs          # EF Core DbContext
├── Domain/
│   └── Product.cs               # Example entity
├── DTOs/
│   └── ProductDtos.cs           # DTOs for Product entity
├── Dockerfile                   # (if IncludeDocker=true)
├── docker-compose.yml           # (if IncludeDocker=true)
└── .dockerignore                # (if IncludeDocker=true)

Program.cs Example ​

csharp
var builder = WebApplication.CreateBuilder(args);

// Add Gryd Core
builder.Services.AddGrydCore();
builder.Services.AddDbContext<AppDbContext>(options => 
    options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));

// Add GrydAuth (if IncludeAuth=true)
builder.Services.AddGrydAuth(builder.Configuration);

// Add GrydCrud (if IncludeCrud=true)
builder.Services.AddGrydCrud();
builder.Services.AddCrudFor<Product, ProductDto, CreateProductDto, UpdateProductDto>();

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthentication();  // if IncludeAuth=true
app.UseGrydAuth();        // if IncludeAuth=true
app.UseAuthorization();
app.MapControllers();

app.Run();

gryd-minimal ​

Minimal API template with only Gryd.Core packages. Perfect for microservices or simple APIs that don't need full CRUD or authentication features.

Usage ​

bash
# Create with defaults (PostgreSQL)
dotnet new gryd-minimal -n MyMinimalApi

# Create with SQL Server
dotnet new gryd-minimal -n MyMinimalApi --UsePostgres false --UseSqlServer true

Parameters ​

ParameterTypeDefaultDescription
--UsePostgresbooltrueConfigure PostgreSQL as database
--UseSqlServerboolfalseConfigure SQL Server as database

Generated Structure ​

MyMinimalApi/
├── MyMinimalApi.csproj           # Project with Gryd.Core packages
├── Program.cs                     # Minimal startup configuration
├── appsettings.json              # Production configuration
├── appsettings.Development.json  # Development configuration
├── README.md                     # Project documentation
├── Controllers/
│   └── HelloController.cs        # Example controller
└── Data/
    └── AppDbContext.cs           # EF Core DbContext

Program.cs Example ​

csharp
var builder = WebApplication.CreateBuilder(args);

// Add Gryd Core
builder.Services.AddGrydCore();

// Add Database
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

gryd-module ​

Clean Architecture module template. Creates a complete module structure following Domain-Driven Design principles, ready to be integrated into a host application.

Usage ​

bash
# Create with defaults (ModuleName=MyModule, with Tests and API)
dotnet new gryd-module -n Catalog

# Create with custom module name
dotnet new gryd-module -n Catalog --ModuleName Products

# Create without tests
dotnet new gryd-module -n Catalog --IncludeTests false

# Create without API layer (library only)
dotnet new gryd-module -n Catalog --IncludeApi false

Parameters ​

ParameterTypeDefaultDescription
--ModuleNamestringMyModuleName of the module (used in namespaces)
--IncludeTestsbooltrueInclude test project with xUnit
--IncludeApibooltrueInclude API layer with controllers
--IncludeReports / --IncludeNotificationsboolfalseAs in gryd-api: either one also brings GrydFiles, GrydJobs and the ClamAV scanner registration

Generated Structure ​

Catalog/
├── Catalog.sln                          # Solution file
├── README.md                            # Module documentation
│
├── src/
│   ├── Catalog.Domain/                  # Domain Layer
│   │   ├── Catalog.Domain.csproj
│   │   ├── GlobalUsings.cs
│   │   ├── CatalogDomainAssemblyMarker.cs
│   │   └── Entities/
│   │       └── SampleEntity.cs          # Example aggregate root
│   │
│   ├── Catalog.Application/             # Application Layer
│   │   ├── Catalog.Application.csproj
│   │   ├── GlobalUsings.cs
│   │   ├── CatalogApplicationAssemblyMarker.cs
│   │   ├── DTOs/
│   │   │   └── SampleEntityDtos.cs      # DTOs for CRUD operations
│   │   └── Features/
│   │       └── SampleEntities/
│   │           ├── Commands/
│   │           │   └── SampleEntityCommands.cs  # Create, Update, Delete
│   │           ├── Queries/
│   │           │   └── SampleEntityQueries.cs   # GetById, GetPaged
│   │           └── Validators/
│   │               └── SampleEntityValidators.cs
│   │
│   ├── Catalog.Infrastructure/          # Infrastructure Layer
│   │   ├── Catalog.Infrastructure.csproj
│   │   ├── GlobalUsings.cs
│   │   ├── CatalogInfrastructureAssemblyMarker.cs
│   │   └── CatalogServiceCollectionExtensions.cs
│   │
│   └── Catalog.API/                     # API Layer (if IncludeApi=true)
│       ├── Catalog.API.csproj
│       ├── GlobalUsings.cs
│       ├── CatalogApiServiceCollectionExtensions.cs
│       └── Controllers/
│           └── SampleEntitiesController.cs
│
└── tests/                               # (if IncludeTests=true)
    └── Catalog.Tests/
        ├── Catalog.Tests.csproj
        ├── GlobalUsings.cs
        └── Domain/
            └── SampleEntityTests.cs     # Unit tests for domain

Layer Details ​

Domain Layer ​

Contains entities, value objects, and domain events. No external dependencies.

csharp
// Entities/SampleEntity.cs
public class SampleEntity : AggregateRoot
{
    public string Name { get; private set; } = string.Empty;
    public string? Description { get; private set; }
    public bool IsActive { get; private set; } = true;

    public static SampleEntity Create(string name, string? description = null)
    {
        Guard.NotNullOrWhiteSpace(name, nameof(name));
        
        var entity = new SampleEntity
        {
            Id = Guid.NewGuid(),
            Name = name,
            Description = description,
            IsActive = true
        };
        
        return entity;
    }

    public void Update(string name, string? description)
    {
        Guard.NotNullOrWhiteSpace(name, nameof(name));
        Name = name;
        Description = description;
    }

    public void Activate() => IsActive = true;
    public void Deactivate() => IsActive = false;
}

Application Layer ​

Contains DTOs, CQRS commands/queries, and validators.

csharp
// Features/SampleEntities/Commands/SampleEntityCommands.cs
public record CreateSampleEntityCommand(string Name, string? Description) 
    : ICommand<Result<SampleEntityDto>>;

public record UpdateSampleEntityCommand(Guid Id, string Name, string? Description) 
    : ICommand<Result<SampleEntityDto>>;

public record DeleteSampleEntityCommand(Guid Id) 
    : ICommand<Result>;

Infrastructure Layer ​

Contains service registration and external integrations.

csharp
// CatalogServiceCollectionExtensions.cs
public static class CatalogServiceCollectionExtensions
{
    public static IServiceCollection AddCatalog(this IServiceCollection services, IConfiguration configuration)
    {
        services.AddCatalogApplication();
        services.AddCatalogInfrastructure(configuration);
        return services;
    }
}

API Layer ​

Contains controllers that use MediatR to dispatch commands/queries.

csharp
// Controllers/SampleEntitiesController.cs
[ApiController]
[Route("api/[controller]")]
public class SampleEntitiesController : GrydBaseController
{
    private readonly ISender _sender;

    [HttpGet]
    public async Task<IActionResult> GetAll([FromQuery] int page = 1, [FromQuery] int pageSize = 10)
    {
        var query = new GetSampleEntitiesQuery(page, pageSize);
        var result = await _sender.Send(query);
        return FromResult(result);
    }

    [HttpPost]
    public async Task<IActionResult> Create([FromBody] CreateSampleEntityDto dto)
    {
        var command = new CreateSampleEntityCommand(dto.Name, dto.Description);
        var result = await _sender.Send(command);
        return FromResult(result);
    }
}

Integration with Host Application ​

  1. Add project references to your host:
xml
<ProjectReference Include="path/to/Catalog.API/Catalog.API.csproj" />
<ProjectReference Include="path/to/Catalog.Infrastructure/Catalog.Infrastructure.csproj" />
  1. Register services in Program.cs:
csharp
// Add the module
builder.Services.AddCatalog(builder.Configuration);

// Add controllers from the module
builder.Services.AddControllers()
    .AddCatalogControllers();
  1. Configure the database context to include module entities:
csharp
public class AppDbContext : DbContext
{
    public DbSet<SampleEntity> SampleEntities => Set<SampleEntity>();
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfigurationsFromAssembly(
            typeof(CatalogInfrastructureAssemblyMarker).Assembly);
    }
}

Uninstalling Templates ​

To remove installed templates:

bash
dotnet new uninstall Gryd.IO.Templates

Or for locally installed:

bash
dotnet new uninstall ./templates/gryd-api
dotnet new uninstall ./templates/gryd-minimal
dotnet new uninstall ./templates/gryd-module

List Installed Templates ​

bash
dotnet new list gryd

Output:

Template Name    Short Name     Language  Tags
--------------   -----------    --------  ----
Gryd API         gryd-api       [C#]      Web/API/Gryd
Gryd Minimal     gryd-minimal   [C#]      Web/API/Gryd
Gryd Module      gryd-module    [C#]      Library/Gryd/Module

Database Setup ​

Prerequisites ​

Projects created with gryd-api or gryd-module (with --IncludeAuth true) require:

  • PostgreSQL (default) or SQL Server
  • Redis (for caching and token management)

v5 security configuration (required)

GrydAuth v5 signs tokens with an asymmetric key and validates configuration at boot, so a new project will not start until you provide:

  • JwtSettings:Algorithm (RS256/ES256), JwtSettings:ActiveKeyId and JwtSettings:PrivateKeyPem (from a secret manager — never commit the key);
  • JwtSettings:ExpirationMinutes between 1 and 15 (default 10);
  • GrydAuth:Cors:AllowedOrigins (CORS is deny-by-default outside Development).

See the v4 → v5 migration guide for key generation and full configuration.

Step 1: Start Infrastructure with Docker Compose ​

Each template includes a docker-compose.yml that starts the required databases:

bash
# Navigate to your project folder
cd MyProject

# Start PostgreSQL and Redis containers
docker-compose up -d

TIP

The docker-compose only starts the database services. Run your API locally with dotnet run for development.

Step 2: GrydAuth Migrations (Automatic in Development) ​

In Development environment, GrydAuth migrations are applied automatically when the application starts. Just run your application and the database schema will be created.

bash
# Navigate to your API project folder
cd src/MyProject.API

# Run the application (migrations are applied automatically)
dotnet run

Automatic Migrations

The template includes await app.ApplyGrydAuthMigrationsAsync() in the startup code, which automatically applies pending migrations when running in Development environment.

Production Environment

For production deployments, consider using a CI/CD pipeline or running migrations manually before deployment.

Step 3: Verify Database ​

After applying migrations, your database should have the following tables:

  • Users - User accounts
  • Roles - Role definitions
  • Permissions - Permission definitions
  • UserRoles - User-Role associations
  • RolePermissions - Role-Permission associations
  • UserPermissions - Direct user permissions
  • UserTenants - Multi-tenancy user associations
  • UserAppIds - Multi-app user registrations
  • RefreshTokens - JWT refresh tokens
  • FailedLoginAttempts - Brute-force protection
  • __EFMigrationsHistory - EF Core migrations tracking

Default Admin User ​

After applying migrations, a default admin user is seeded:

FieldValue
Emailadmin@gryd.io
PasswordAdmin@123
RoleAdmin

Security Warning

Change the default admin password immediately in production environments!

Step 3: Update Admin User AppId (Required) ​

After the first run, you must update the admin user's AppId to match the one generated in your appsettings.Development.json.

  1. Find the AppId in your appsettings.Development.json:
json
"JwtSettings": {
  "AppId": "MyProject-dev-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
  1. Update the UserAppIds table in your database:
sql
-- Replace with your actual AppId from appsettings.Development.json
UPDATE public."UserAppIds"
SET "AppId" = 'MyProject-dev-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
WHERE "UserId" = '11111111-1111-1111-1111-111111111111';

Important

Without this update, login will fail with the error: Invalid application ID. The AppId in the token request must match the one registered for the user.


Quick Start Examples ​

Example 1: Create a Complete API Project ​

bash
# 1. Install templates
dotnet new install Gryd.IO.Templates

# 2. Create project with Auth + Crud
dotnet new gryd-api -n MyStore --IncludeAuth true --IncludeCrud true

# 3. Navigate to project
cd MyStore

# 4. Start databases
docker-compose up -d

# 5. Run the application (migrations are applied automatically)
cd src/MyStore.API
dotnet run

# 6. Update admin AppId (first run only)
# Get AppId from appsettings.Development.json and update UserAppIds table:
# UPDATE public."UserAppIds" SET "AppId" = 'your-appid' WHERE "UserId" = '11111111-1111-1111-1111-111111111111';

# 7. Access Swagger UI
# Open: http://localhost:5000/swagger

Example 2: Create a Module and Add to Existing Project ​

bash
# 1. Create a new module
dotnet new gryd-module -n Inventory --IncludeAuth true

# 2. Add module references to your host project
# (add to your .csproj)

# 3. Register in Program.cs:
# builder.Services.AddInventoryServices(builder.Configuration);

# 4. Start databases
docker-compose up -d

# 5. Run the application (migrations are applied automatically)
dotnet run

# 6. Update admin AppId in database (see Database Setup section)

Example 3: Create a Minimal API (No Auth) ​

bash
# 1. Create minimal project
dotnet new gryd-minimal -n MyMicroservice

# 2. Navigate to project
cd MyMicroservice

# 3. Run (no migrations needed - no GrydAuth)
dotnet run

Troubleshooting ​

Database does not exist ​

If you see database "xxx" does not exist:

bash
# Remove volumes and recreate
docker-compose down -v
docker-compose up -d

Invalid application ID ​

If login fails with Invalid application ID, update the admin user's AppId:

sql
UPDATE public."UserAppIds"
SET "AppId" = 'your-appid-from-appsettings'
WHERE "UserId" = '11111111-1111-1111-1111-111111111111';

NuGet cache issues ​

If packages are not updating:

bash
# Clear NuGet cache
dotnet nuget locals all --clear

# Restore packages
dotnet restore --force

Port already in use ​

If port 5000 is in use (common on macOS with AirPlay):

  1. Find the process: lsof -i :5000
  2. Kill it: kill -9 <PID>
  3. Or disable AirPlay Receiver in System Settings

Released under the MIT License.