Skip to content

Getting Started ​

This guide walks you through setting up GrydNotifications in your .NET application, from installation to sending your first notification.

Prerequisites ​

  • .NET 10.0 or later
  • PostgreSQL (for notification persistence and template storage)
  • An existing Gryd.IO project (or use the gryd-api template)
  • Only for e-mail attachments: GrydFiles (AddGrydFiles, with object storage and an antivirus engine) and the gryd.notification-attachment profile. A host that never sends an attachment — in-app only, or e-mail without files — does not register it; see Email with Attachments.

1. Installation ​

bash
dotnet add package GrydNotifications

This includes Core, Application, Infrastructure (MailKit + EF Core + Scriban), and API layers.

Individual packages ​

bash
dotnet add package GrydNotifications.Core
bash
dotnet add package GrydNotifications.Core
dotnet add package GrydNotifications.Application
dotnet add package GrydNotifications.Infrastructure
dotnet add package GrydNotifications.API
bash
dotnet add package GrydNotifications
dotnet add package GrydNotifications.Scheduling

2. Configure Services ​

Register GrydNotifications in your Program.cs:

csharp
using GrydNotifications;

var builder = WebApplication.CreateBuilder(args);

// Option A: Full registration with meta-package
builder.Services.AddGrydNotifications(options =>
{
    // PostgreSQL storage
    options.UsePostgreSqlStorage(
        builder.Configuration.GetConnectionString("Notifications")!);

    // Email via SMTP (MailKit)
    options.Email.DefaultFrom = "noreply@myapp.com";
    options.Email.DefaultFromName = "My App";
    options.Email.SmtpHost = "smtp.myapp.com";
    options.Email.SmtpPort = 587;
    options.Email.SmtpUseSsl = true;
    options.Email.SmtpUsername = "apikey";
    options.Email.SmtpPassword = builder.Configuration["Smtp:Password"]!;

    // In-App (real-time via SignalR)
    options.InApp.Enabled = true;
    options.InApp.EnableSignalR = true;

    // Push (FCM - optional)
    options.Push.Enabled = false; // Enable when Firebase is configured
});

// Option B: Register layers individually
builder.Services.AddGrydNotificationsApplication();
builder.Services.AddGrydNotificationsInfrastructure(new GrydNotificationsOptions { /* ... */ });
builder.Services.AddGrydNotificationsApi();

// Health checks (optional)
builder.Services.AddGrydNotificationsHealthChecks();

var app = builder.Build();

// Configure middleware pipeline
app.UseGrydNotifications(); // Maps SignalR hub if InApp.Enabled

// Apply migrations on startup (Development only)
if (app.Environment.IsDevelopment())
    await app.ApplyGrydNotificationsMigrationsAsync();

app.MapControllers();
app.MapHealthChecks("/health");
app.Run();

3. Add Configuration ​

Add the following to your appsettings.json:

json
{
  "ConnectionStrings": {
    "Notifications": "Host=localhost;Port=5432;Database=gryd_notifications;Username=postgres;Password=postgres"
  }
}

For a production-ready setup, configure all options via appsettings:

json
{
  "ConnectionStrings": {
    "Notifications": "Host=db.myapp.com;Database=gryd_notifications;Username=app;Password=secret;Ssl Mode=Require"
  },
  "GrydNotifications": {
    "EnableTemplates": true,
    "EnableQueue": true,
    "PersistNotifications": true,
    "NotificationRetentionDays": 90,
    "Email": {
      "DefaultFrom": "noreply@myapp.com",
      "DefaultFromName": "My App",
      "SmtpHost": "smtp.sendgrid.net",
      "SmtpPort": 587,
      "SmtpUseSsl": true,
      "SmtpUsername": "apikey",
      "SmtpPassword": "SG.xxxxx",
      "MaxAttachmentSizeMb": 10,
      "MaxRecipientsPerEmail": 50
    },
    "Push": {
      "Enabled": true,
      "DefaultTimeToLive": "24:00:00",
      "AutoRemoveInvalidTokens": true
    },
    "InApp": {
      "Enabled": true,
      "RetentionDays": 90,
      "MaxUnreadPerUser": 200,
      "EnableSignalR": true,
      "HubPath": "/hubs/notifications"
    },
    "Retry": {
      "MaxRetries": 3,
      "BackoffType": "Exponential",
      "BaseDelay": "00:00:05",
      "MaxDelay": "00:05:00",
      "UseJitter": true
    },
    "Queue": {
      "BatchSize": 10,
      "PollingInterval": "00:00:05",
      "MaxConcurrency": 4
    }
  }
}

4. Send Your First Notification ​

csharp
using GrydNotifications.Application.Features.Notifications.Commands;
using GrydNotifications.Application.Features.Email.Commands;
using GrydNotifications.Core.DTOs;
using GrydNotifications.Core.Enums;
using MediatR;

public class OrderService
{
    private readonly IMediator _mediator;

    public OrderService(IMediator mediator) => _mediator = mediator;

    public async Task OnOrderCreatedAsync(Order order, CancellationToken ct)
    {
        // Option 1: Unified pipeline (auto-resolves channel)
        var result = await _mediator.Send(new SendNotificationCommand
        {
            Channel = NotificationChannel.Email,
            Recipients = [new RecipientDto("user@example.com", "John Doe")],
            Subject = "Order Confirmed",
            HtmlBody = $"<h1>Order #{order.Id}</h1><p>Thank you, {order.CustomerName}!</p>"
        }, ct);

        if (!result.IsSuccess)
            _logger.LogWarning("Notification failed: {Error}", result.ErrorMessage);

        // Option 2: Direct email shortcut
        await _mediator.Send(new SendEmailCommand
        {
            To = ["user@example.com"],
            Cc = ["admin@myapp.com"],
            Subject = "New Order",
            HtmlBody = "<p>A new order was placed.</p>"
        }, ct);
    }
}

Via REST API ​

http
POST /api/v1/notifications/send
Content-Type: application/json

{
  "channel": "Email",
  "recipients": [
    { "address": "user@example.com", "displayName": "John Doe" }
  ],
  "subject": "Order Confirmed",
  "htmlBody": "<h1>Your order has been confirmed!</h1>"
}

Response: 200 OK

json
{
  "notificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "Sent",
  "statusDisplay": "Sent"
}

5. Using Templates ​

Create a template via API:

http
POST /api/v1/notification-templates
Content-Type: application/json

{
  "slug": "order-confirmation",
  "name": "Order Confirmation Email",
  "subjectTemplate": "Order #{{order_id}} Confirmed",
  "htmlBodyTemplate": "<h1>Hi {{customer_name}},</h1><p>Your order #{{order_id}} for {{total | math.format \"C2\"}} has been confirmed.</p>",
  "locale": "en-US"
}

Then send using the template:

csharp
await _mediator.Send(new SendNotificationCommand
{
    Channel = NotificationChannel.Email,
    Recipients = [new RecipientDto("user@example.com")],
    TemplateSlug = "order-confirmation",
    TemplateData = new Dictionary<string, object>
    {
        ["order_id"] = "ORD-12345",
        ["customer_name"] = "John",
        ["total"] = 199.99m
    }
}, ct);

Next Steps ​

Released under the MIT License.