NOTIFICATIONS PLUGIN - nself-org/nchat GitHub Wiki
Plugin Name: notifications
Version: 1.0.0
Category: Communication
Status: Production Ready
Priority: CRITICAL
The Notifications Plugin provides multi-channel notification delivery for Ι³Chat. It handles email, push notifications, SMS, and in-app notifications with templating, preferences, and delivery tracking.
- β Email Notifications - SMTP, SendGrid, Mailgun support
- β Push Notifications - FCM (Android), APNS (iOS)
- β SMS Notifications - Twilio integration
- β In-App Notifications - Real-time notification center
- β Templating System - Customizable templates
- β User Preferences - Per-user notification settings
- β Delivery Tracking - Status and delivery confirmation
- β Batching - Bulk notification sending
- β Scheduling - Delayed notification delivery
- β Email Digests - Daily/weekly summary emails
- β Notification Categories - Mentions, messages, threads, etc.
- β Priority Levels - Low, normal, high, critical
- β Retry Logic - Automatic retry on failure
- β Rate Limiting - Prevent notification spam
- β Analytics - Delivery rates and engagement tracking
- β Localization - Multi-language support
- β Rich Notifications - Images, actions, sounds
- Docker running
- nself CLI v0.9.8+
- Mailpit (dev) or SMTP server (prod)
cd /Users/admin/Sites/nself-nchat/backend
nself plugin install notificationsAdd to backend/.env.plugins:
# Notifications Plugin
NOTIFICATIONS_ENABLED=true
NOTIFICATIONS_PORT=3102
NOTIFICATIONS_ROUTE=notifications.${BASE_DOMAIN:-localhost}
NOTIFICATIONS_MEMORY=128M
# Email Provider (Development)
NOTIFICATIONS_EMAIL_PROVIDER=mailpit
NOTIFICATIONS_SMTP_HOST=mailpit
NOTIFICATIONS_SMTP_PORT=1025
NOTIFICATIONS_SMTP_SECURE=false
[email protected]
NOTIFICATIONS_FROM_NAME=nself Chat
# Email Provider (Production)
# NOTIFICATIONS_EMAIL_PROVIDER=sendgrid
# NOTIFICATIONS_SENDGRID_API_KEY=${SENDGRID_API_KEY}
# Or SMTP:
# NOTIFICATIONS_EMAIL_PROVIDER=smtp
# NOTIFICATIONS_SMTP_HOST=smtp.example.com
# NOTIFICATIONS_SMTP_PORT=587
# NOTIFICATIONS_SMTP_SECURE=true
# NOTIFICATIONS_SMTP_USER=${SMTP_USER}
# NOTIFICATIONS_SMTP_PASSWORD=${SMTP_PASSWORD}
# Push Notifications
NOTIFICATIONS_PUSH_ENABLED=true
NOTIFICATIONS_FCM_SERVER_KEY=${FCM_SERVER_KEY}
NOTIFICATIONS_APNS_KEY_ID=${APNS_KEY_ID}
NOTIFICATIONS_APNS_TEAM_ID=${APNS_TEAM_ID}
NOTIFICATIONS_APNS_BUNDLE_ID=com.nchat.app
# SMS (Twilio)
NOTIFICATIONS_SMS_ENABLED=false
NOTIFICATIONS_TWILIO_ACCOUNT_SID=${TWILIO_ACCOUNT_SID}
NOTIFICATIONS_TWILIO_AUTH_TOKEN=${TWILIO_AUTH_TOKEN}
NOTIFICATIONS_TWILIO_FROM_NUMBER=${TWILIO_FROM_NUMBER}
# Templates
NOTIFICATIONS_TEMPLATES_DIR=/app/templates
NOTIFICATIONS_DEFAULT_TEMPLATE=default
# Delivery
NOTIFICATIONS_RETRY_ATTEMPTS=3
NOTIFICATIONS_RETRY_DELAY=5000
NOTIFICATIONS_BATCH_SIZE=100
NOTIFICATIONS_RATE_LIMIT=1000
# Database (for preferences and history)
NOTIFICATIONS_DATABASE_URL=${DATABASE_URL}nself restartGET /healthResponse:
{
"status": "healthy",
"service": "notifications",
"version": "1.0.0",
"uptime": 86400,
"channels": {
"email": { "enabled": true, "provider": "mailpit" },
"push": { "enabled": true },
"sms": { "enabled": false }
},
"providers": {
"email": { "status": "connected" },
"fcm": { "status": "connected" }
}
}POST /send
Content-Type: application/json
{
"userId": "user-123",
"channel": "email",
"to": {
"email": "[email protected]"
},
"content": {
"subject": "New message from Alice",
"body": "Alice sent you a message: Hello!"
},
"category": "message",
"priority": "normal"
}Response:
{
"success": true,
"notification_id": "notif-abc123",
"message": "Notification queued",
"estimated_delivery": "2026-02-03T12:00:05Z"
}POST /send-bulk
Content-Type: application/json
{
"notifications": [
{
"userId": "user-1",
"channel": "email",
"to": { "email": "[email protected]" },
"content": { "subject": "Hello", "body": "World" }
},
{
"userId": "user-2",
"channel": "push",
"to": { "push_token": "fcm-token" },
"content": { "title": "Hello", "body": "World" }
}
]
}GET /notifications/:notificationIdResponse:
{
"id": "notif-abc123",
"status": "delivered",
"channel": "email",
"userId": "user-123",
"sentAt": "2026-02-03T12:00:05Z",
"deliveredAt": "2026-02-03T12:00:07Z",
"openedAt": null,
"clickedAt": null
}GET /preferences/:userIdResponse:
{
"userId": "user-123",
"channels": {
"email": true,
"push": true,
"sms": false
},
"categories": {
"mentions": { "email": true, "push": true },
"messages": { "email": false, "push": true },
"threads": { "email": true, "push": false }
},
"digest": {
"enabled": true,
"frequency": "daily",
"time": "09:00"
},
"quiet_hours": {
"enabled": true,
"start": "22:00",
"end": "08:00"
}
}POST /preferences/:userId
Content-Type: application/json
{
"channels": {
"email": true,
"push": false
},
"categories": {
"mentions": { "email": true, "push": true }
}
}GET /history/:userId?category=mention&limit=20&offset=0Response:
{
"notifications": [
{
"id": "notif-1",
"category": "mention",
"channel": "email",
"status": "delivered",
"sentAt": "2026-02-03T12:00:00Z"
}
],
"total": 42,
"limit": 20,
"offset": 0
}{
"channel": "email",
"to": {
"email": "[email protected]",
"name": "John Doe" // optional
},
"content": {
"subject": "Subject line",
"body": "Plain text body",
"html": "<p>HTML body</p>", // optional
"template": "mention", // optional
"variables": {
"actorName": "Alice",
"channelName": "general"
}
},
"attachments": [ // optional
{
"filename": "document.pdf",
"content": "base64-encoded-content",
"contentType": "application/pdf"
}
]
}{
"channel": "push",
"to": {
"push_token": "fcm-token-or-apns-token",
"platform": "android" // or "ios"
},
"content": {
"title": "New message",
"body": "You have a new message from Alice",
"icon": "https://example.com/icon.png", // optional
"image": "https://example.com/image.png", // optional
"sound": "default", // optional
"badge": 5, // optional (iOS)
"data": { // optional custom data
"channelId": "channel-123",
"messageId": "msg-456"
},
"actions": [ // optional
{
"action": "reply",
"title": "Reply"
},
{
"action": "mark_read",
"title": "Mark as Read"
}
]
}
}{
"channel": "sms",
"to": {
"phone_number": "+12345678901"
},
"content": {
"body": "You have a new message from Alice in #general"
}
}{
"channel": "in-app",
"to": {
"userId": "user-123"
},
"content": {
"title": "New message",
"body": "Alice sent you a message",
"icon": "message",
"color": "blue",
"action_url": "/chat/channel-123"
}
}# .env.local
NEXT_PUBLIC_NOTIFICATIONS_URL=http://notifications.localhost:3102
NEXT_PUBLIC_NOTIFICATIONS_ENABLED=trueimport { useNotificationPreferences } from '@/hooks/use-notification-preferences'
function NotificationSettings() {
const {
preferences,
updatePreferences,
loading
} = useNotificationPreferences()
const handleToggleEmail = async () => {
await updatePreferences({
channels: {
...preferences.channels,
email: !preferences.channels.email
}
})
}
return (
<div>
<label>
<input
type="checkbox"
checked={preferences.channels.email}
onChange={handleToggleEmail}
disabled={loading}
/>
Email notifications
</label>
</div>
)
}import { NotificationService } from '@/services/notifications'
const notificationService = new NotificationService()
// Send notification
await notificationService.sendNotification({
userId: 'user-123',
channel: 'email',
to: { email: '[email protected]' },
content: {
subject: 'New message',
body: 'You have a new message',
},
})
// Get preferences
const prefs = await notificationService.getPreferences('user-123')
// Update preferences
await notificationService.updatePreferences('user-123', {
channels: { email: false, push: true },
})templates/
βββ email/
β βββ mention.html
β βββ message.html
β βββ thread-reply.html
β βββ digest.html
βββ push/
β βββ mention.json
β βββ message.json
βββ sms/
βββ mention.txt
<!-- templates/email/mention.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{{subject}}</title>
</head>
<body>
<h1>{{actorName}} mentioned you in #{{channelName}}</h1>
<p>{{messagePreview}}</p>
<a href="{{actionUrl}}">View message</a>
</body>
</html>Available variables in templates:
-
{{actorName}}- User who triggered the notification -
{{channelName}}- Channel name -
{{messagePreview}}- Message content preview -
{{actionUrl}}- Link to relevant content -
{{appName}}- Application name -
{{timestamp}}- Notification timestamp
// Automatically process chat events
const events = [
'message.mention',
'message.reply',
'message.reaction',
'channel.invite',
'thread.reply',
]
await notificationService.processChatEvent({
type: 'message.mention',
timestamp: new Date().toISOString(),
actor: {
id: 'user-1',
name: 'Alice',
},
target: {
user_id: 'user-2',
user_email: '[email protected]',
user_push_token: 'fcm-token',
},
data: {
channel_id: 'channel-123',
channel_name: 'general',
message_preview: 'Hey @bob, check this out!',
action_url: 'https://nchat.app/channel-123',
},
})curl http://notifications.localhost:3102/healthcurl -X POST http://notifications.localhost:3102/send \
-H "Content-Type: application/json" \
-d '{
"userId": "test-user",
"channel": "email",
"to": { "email": "[email protected]" },
"content": {
"subject": "Test Email",
"body": "This is a test"
}
}'open http://mailpit.localhost:8025- Notifications Sent: Total count by channel
- Delivery Rate: Percentage successfully delivered
- Open Rate: Email open tracking (if enabled)
- Click Rate: Link click tracking
- Failure Rate: Failed deliveries
- Latency: Time from trigger to delivery
Access metrics at: /metrics
nself logs notifications --follow- Check SMTP configuration
- Verify Mailpit is running (dev)
- Check logs:
nself logs notifications - Test SMTP connection:
telnet smtp.example.com 587
- Verify FCM/APNS credentials
- Check device token is valid
- Test with Firebase Console / APNS tester
- Review notification payload format
- Check provider status
- Review rate limits
- Validate email addresses/tokens
- Check retry configuration
- User Preferences: Always respect user notification preferences
- Rate Limiting: Prevent notification fatigue
- Batching: Use digest emails for high-volume notifications
- Templates: Use templating for consistency
- Tracking: Monitor delivery and engagement metrics
- Testing: Test with Mailpit before production deployment
- Fallback: Have multiple channels configured
- Quiet Hours: Respect user quiet hours settings
- Validate all recipient addresses
- Sanitize user-provided content
- Use HTTPS for action URLs
- Secure webhook endpoints
- Rate limit to prevent abuse
- Encrypt sensitive data in database
- Initial release
- Email, push, SMS, in-app channels
- Template system
- User preferences
- Delivery tracking
- Event integration
- Documentation: https://nself.org/docs/plugins/notifications
- Issues: https://github.com/nself-org/plugins/issues