novu
Multi-channel notification infrastructure and workflows
$ npx docs2skills add novu-notificationsNovu
Multi-channel notification infrastructure and workflows
What this skill does
Novu provides a complete notification infrastructure that unifies email, SMS, push notifications, and in-app messaging into a single platform. It eliminates the complexity of managing multiple notification providers by offering workflow orchestration, template management, subscriber handling, and delivery tracking through a unified API.
Developers use Novu to build scalable notification systems without vendor lock-in, reduce integration complexity across multiple channels, and maintain consistent messaging experiences. It solves the problem of notification sprawl by providing a centralized hub for all notification logic, from simple transactional emails to complex multi-step notification workflows with conditions, delays, and channel fallbacks.
Prerequisites
- Node.js 16+ or Python 3.7+ (for server-side SDKs)
- Novu account with API key from dashboard.novu.co
- Provider credentials (SendGrid, Twilio, Firebase, etc.) for channels you'll use
- React 16.8+ (for in-app notification components)
Quick start
npm install @novu/node @novu/notification-center-react
// Server-side: Trigger notification
import { Novu } from '@novu/node';
const novu = new Novu(process.env.NOVU_API_KEY);
await novu.trigger('welcome-email', {
to: {
subscriberId: 'user-123',
email: 'john@example.com',
},
payload: {
firstName: 'John',
organizationName: 'Acme Corp'
}
});
// Client-side: In-app notifications
import { NovuProvider, NotificationBell } from '@novu/notification-center-react';
function App() {
return (
<NovuProvider subscriberId="user-123" applicationIdentifier="APP_ID">
<NotificationBell />
</NovuProvider>
);
}
Core concepts
Workflows: Multi-step notification sequences with conditions, delays, and channel routing. Define once in dashboard or code, trigger from anywhere.
Subscribers: Recipients with unique IDs and channel preferences. Automatically managed with upsert behavior.
Templates: Reusable content with variable substitution. Support Handlebars syntax and conditional logic.
Providers: Channel integrations (SendGrid, Twilio, Firebase). Novu handles provider failover and routing.
Triggers: Events that start workflows. Include payload data for template personalization.
Channels: Email, SMS, push, in-app, chat. Each with provider-specific configurations.
Key API surface
// Triggering notifications
await novu.trigger(templateId, { to, payload, overrides })
await novu.bulkTrigger([{ templateId, to, payload }])
// Subscriber management
await novu.subscribers.identify(subscriberId, data)
await novu.subscribers.update(subscriberId, updates)
await novu.subscribers.setCredentials(subscriberId, providerId, credentials)
await novu.subscribers.updatePreferences(subscriberId, templateId, preferences)
// Message management
await novu.messages.list({ subscriberId, channel })
await novu.messages.markAs(messageId, { seen: true, read: true })
await novu.messages.remove(messageId)
// Event tracking
await novu.events.trigger(name, { subscriberId, payload })
await novu.events.cancel(transactionId)
// Workflow management
await novu.workflows.create(workflowData)
await novu.workflows.update(workflowId, updates)
Common patterns
User onboarding sequence:
await novu.trigger('user-onboarding', {
to: { subscriberId: userId, email: userEmail },
payload: {
userName: user.name,
activationUrl: `${baseUrl}/activate/${token}`
}
});
Order status updates with fallback:
await novu.trigger('order-shipped', {
to: { subscriberId: customerId },
payload: {
orderNumber: order.id,
trackingUrl: order.trackingUrl,
estimatedDelivery: order.estimatedDelivery
},
overrides: {
sms: {
to: customer.phoneNumber
}
}
});
Bulk notifications:
const triggers = users.map(user => ({
name: 'weekly-digest',
to: { subscriberId: user.id, email: user.email },
payload: {
digestContent: user.weeklyDigest,
unsubscribeUrl: `${baseUrl}/unsubscribe/${user.token}`
}
}));
await novu.bulkTrigger(triggers);
Real-time in-app notifications:
import { useSocket, useNotifications } from '@novu/notification-center-react';
function NotificationsList() {
const { notifications, markAsRead } = useNotifications();
return (
<div>
{notifications.map(notification => (
<div key={notification._id} onClick={() => markAsRead(notification._id)}>
{notification.content}
</div>
))}
</div>
);
}
Configuration
Environment variables:
NOVU_API_KEY=your_api_key_here
NOVU_APPLICATION_IDENTIFIER=your_app_id # For client-side
Provider setup (in dashboard or API):
await novu.integrations.create({
providerId: 'sendgrid',
channel: 'email',
credentials: {
apiKey: process.env.SENDGRID_API_KEY,
from: { email: 'noreply@company.com', name: 'Company Name' }
}
});
Subscriber preferences:
await novu.subscribers.updatePreferences(subscriberId, templateId, {
enabled: true,
channels: {
email: true,
sms: false,
in_app: true
}
});
Best practices
- Use semantic workflow names that describe business events, not technical actions
- Always include unsubscribe mechanisms in email workflows
- Set up provider fallbacks for critical notifications
- Batch trigger calls when sending to multiple users simultaneously
- Use subscriber preferences to respect user communication choices
- Include correlation IDs in payloads for debugging and analytics
- Test workflows in development environment before production deployment
- Monitor delivery rates and failed notifications through dashboard
- Use workflow delays judiciously to avoid overwhelming users
- Implement proper error handling for trigger failures
Gotchas and common mistakes
subscriberId must be consistent: Once set, always use the same subscriberId for a user across all triggers. Changing it creates a new subscriber.
Payload nesting limits: Template variables support up to 3 levels of nesting. Deeper objects get flattened or ignored.
Provider rate limits: Novu doesn't automatically handle provider rate limits. Configure delays in workflows for high-volume sends.
Workflow caching: Changes to workflows in dashboard take up to 2 minutes to propagate. Use workflow override during development.
Client-side security: Never use server API key in frontend code. Use applicationIdentifier for client-side components.
Duplicate triggers: Calling trigger multiple times with same transactionId only sends once. Use unique transactionId for each send.
Template compilation errors: Invalid Handlebars syntax fails silently. Test templates with sample data before production.
Channel prerequisites: In-app notifications require subscriber to be online. Use fallback channels for critical messages.
Bulk trigger limits: Maximum 100 events per bulkTrigger call. Batch larger lists into multiple calls.
Provider credentials: Wrong provider credentials cause silent failures. Check integration status in dashboard.
Timezone handling: All dates in workflows use UTC. Convert user timezones in payload data, not workflow configuration.
Message retention: Messages older than 30 days are automatically deleted. Export important delivery data regularly.