Appearance
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
Meta-package (recommended)
bash
dotnet add package GrydNotificationsThis includes Core, Application, Infrastructure (MailKit + EF Core + Scriban), and API layers.
Individual packages
bash
dotnet add package GrydNotifications.Corebash
dotnet add package GrydNotifications.Core
dotnet add package GrydNotifications.Application
dotnet add package GrydNotifications.Infrastructure
dotnet add package GrydNotifications.APIbash
dotnet add package GrydNotifications
dotnet add package GrydNotifications.Scheduling2. 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
Via MediatR (recommended for services)
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
- Configuration — All options explained in detail
- Channels — Email, Push, In-App deep dive
- Templates — Scriban template syntax, locale fallback
- In-App & SignalR — Real-time notifications setup
- API Reference — Full endpoint documentation
- Advanced — Retry, scheduling, observability, testing