Skip to content

Notifications

The Notifications module provides interfaces for sending notifications through pluggable delivery channels and persisting in-app notification state.

Quick Start

using Deepstaging.Effects;
using Deepstaging.Notifications;

[EffectsModule(typeof(INotificationChannel))]
[EffectsModule(typeof(INotificationStore))]
public sealed partial class NotificationEffects;

[Runtime]
[Uses(typeof(NotificationEffects))]
public sealed partial class AppRuntime;

Interfaces

INotificationChannel

Sends notifications through delivery channels (email, push, SMS, WebSocket).

Method Returns Description
SendAsync(notification) Task Send a single notification
SendManyAsync(notifications) Task Send a batch

INotificationStore

Persists and queries in-app notifications with read/unread state.

Method Returns Description
SaveAsync(notification) Task Persist a notification
GetAsync(recipientId, unreadOnly?, offset?, limit?) Task<IReadOnlyList<StoredNotification>> Query by recipient
MarkReadAsync(notificationId) Task Mark as read
MarkAllReadAsync(recipientId) Task Mark all read
GetUnreadCountAsync(recipientId) Task<int> Count unread

Usage

from _ in NotificationEffects.NotificationChannel.SendAsync<AppRuntime>(
    new Notification(
        Type: "order.confirmed",
        Title: "Order Confirmed",
        Body: $"Your order {orderId} has been confirmed.",
        RecipientId: userId))
select unit;

Templating

Use Scriban templates for notification title and body content. This keeps notification copy consistent and easy to update without changing handler code.

{{- # Templates/Notifications/OrderShipped.scriban-txt -}}
Your order #{{ order_id }} has shipped! Estimated delivery: {{ delivery_date | date.to_string "%B %d" }}.
var body = Template.RenderText("Notifications/OrderShipped",
    new { OrderId = order.Id, DeliveryDate = order.EstimatedDelivery });

from _ in NotificationEffects.NotificationChannel.SendAsync<AppRuntime>(
    new Notification(
        Type: "order.shipped",
        Title: "Order Shipped",
        Body: body,
        RecipientId: userId))
select unit;

For syntax reference and best practices, see Scriban Templating.

Dispatch integration

Notifications compose naturally with dispatch handlers — send notifications as a side effect after command execution.