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)

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.