Appearance
GrydNotifications Module
GrydNotifications is a multi-channel notification module for .NET applications. It provides a unified pipeline for sending Email, Push (FCM), and In-App (SignalR) notifications with Scriban templates, retry policies, dead letter queue, scheduling, multi-tenancy, and observability — all following Clean Architecture.
✨ Features
| Feature | Description |
|---|---|
| 📧 Email (SMTP + SendGrid) | MailKit-based SMTP with SendGrid as alternative provider |
| 🔔 Push Notifications | Firebase Cloud Messaging (FCM) with device token management |
| 🔔 In-App Notifications | Real-time delivery via SignalR with read/unread, categories, and expiration |
| 📝 Scriban Templates | Database-stored templates with locale and tenant fallback, variable detection |
| 🔁 Retry + Dead Letter | Configurable per-channel retry with exponential backoff and jitter |
| ⏰ Scheduling | Schedule notifications for future delivery, with cancel support |
| 🏢 Multi-Tenancy | Automatic tenant isolation across all channels and templates |
| 📊 Observability | OpenTelemetry metrics, activity tracing, and health checks |
| 🔌 Provider-Agnostic | Swap email/push providers without changing application code |
| ✅ 465 Tests | Comprehensive test coverage across all 5 layers |
📦 Packages
GrydNotifications is modular — use only what you need:
📦 GrydNotifications # Meta-package (includes all)
├── GrydNotifications.Core # Abstractions, entities, DTOs, enums
├── GrydNotifications.Application # CQRS handlers, validators, MediatR
├── GrydNotifications.Infrastructure # EF Core, MailKit, Scriban, SignalR sender
├── GrydNotifications.Scheduling # GrydJobs integration (optional)
└── GrydNotifications.API # REST controllers, SignalR hub, health checks🚀 Quick Start
1. Install the meta-package
bash
dotnet add package GrydNotifications2. Register services
csharp
builder.Services.AddGrydNotifications(options =>
{
options.UsePostgreSqlStorage(
builder.Configuration.GetConnectionString("Notifications")!);
// Email (SMTP via MailKit)
options.Email.DefaultFrom = "noreply@myapp.com";
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 (SignalR)
options.InApp.Enabled = true;
options.InApp.EnableSignalR = true;
});
// Optional: health checks
builder.Services.AddGrydNotificationsHealthChecks();3. Configure middleware
csharp
app.UseGrydNotifications(); // Maps SignalR hub at /hubs/notifications
// Apply migrations (Development only)
if (app.Environment.IsDevelopment())
await app.ApplyGrydNotificationsMigrationsAsync();4. Send your first notification
csharp
public class OrderService
{
private readonly IMediator _mediator;
public OrderService(IMediator mediator) => _mediator = mediator;
public async Task PlaceOrderAsync(Order order, CancellationToken ct)
{
// Send via unified pipeline
await _mediator.Send(new SendNotificationCommand
{
Channel = NotificationChannel.Email,
Recipients = [new RecipientDto { Address = order.Email }],
Subject = "Order Confirmed",
HtmlBody = $"<h1>Order #{order.Id} confirmed!</h1>"
}, ct);
// Or send directly via the email shortcut
await _mediator.Send(new SendEmailCommand
{
To = [order.Email],
Subject = "Order Confirmed",
HtmlBody = $"<h1>Order #{order.Id} confirmed!</h1>"
}, ct);
}
}5. Use templates
csharp
// Send using a Scriban template stored in the database
await _mediator.Send(new SendNotificationCommand
{
Channel = NotificationChannel.Email,
Recipients = [new RecipientDto { Address = "user@example.com" }],
TemplateSlug = "order-confirmation",
TemplateData = new Dictionary<string, object>
{
["order_id"] = order.Id,
["customer_name"] = order.CustomerName,
["total"] = order.Total
}
}, ct);🏗️ Architecture
┌─────────────────────────────────────────────────────────────────┐
│ GrydNotifications.API │
│ NotificationsController | TemplatesController | UserNotifs │
│ NotificationHub (SignalR) | HealthCheck │
├─────────────────────────────────────────────────────────────────┤
│ GrydNotifications.Application │
│ Commands → Handlers → INotificationSender/ITemplateRenderer │
│ Queries → Handlers → INotificationRepository/ITemplateStore │
│ Validators (FluentValidation) | MediatR Pipeline │
├─────────────────────────────────────────────────────────────────┤
│ GrydNotifications.Infrastructure │
│ MailKit SMTP │ SendGrid │ FCM │ SignalR InApp │ Scriban Engine │
│ EF Core (PostgreSQL) │ Queue (Channel<T>) │ Polly Retry │
├─────────────────────────────────────────────────────────────────┤
│ GrydNotifications.Core │
│ Entities │ Abstractions │ DTOs │ Enums │ Configuration │
└─────────────────────────────────────────────────────────────────┘📖 Documentation
- Getting Started — Installation, setup, and first notification
- Configuration — All options explained
- Channels — Email, Push, In-App deep dive
- Templates — Scriban templates with locale/tenant fallback
- In-App & SignalR — Real-time notifications, drawer, read tracking
- API Reference — All REST endpoints documented
- Advanced — Retry, scheduling, observability, testing, multi-tenancy