Every channel step in a Novu Workflow can now be managed as TypeScript in your codebase - email, SMS, push, chat, and in-app.
Author:
Adam Chmara
Each step now has two modes: Editor (visual) and Custom Code (developer-managed via code). Switch any step to Custom Code mode, and the dashboard shows a pre-filled CLI command.
Switch any step to Custom Code mode and the dashboard shows the publish command, pre-filled and ready to run.
Run it to scaffold a placeholder handler and deploy it:
Define a controlSchema in your code steps to expose editable fields in the Novu dashboard. Developers set the structure and defaults - non-technical teammates override copy without touching code.
Once published, controls defined in your handler appear as editable fields in the dashboard - no code change needed to update copy.
Mix Custom Code steps and Editor steps freely within the same Workflow.
Switch any step to Custom Code mode and copy the pre-filled command from the step editor to get started.
Give users control over what notifications they receive - at the topic level. Create subscribe/unsubscribe flows that fit the context. Set workflow preferences and use advanced conditional rules. All of this can be done with a customizable React component.
We've introduced Subscriptions, a new way to manage notification delivery at the topic level. Now with full context-awareness, giving subscribers precise control over what they receive and when.
States of <Subscription /> component
The new <Subscription /> React component makes it easy to add subscription features to your app. You can use it for a simple “follow” button on a resource or a complete preferences view.
Breakdown of the <Subscription /> component
Subscribe or unsubscribe to topics (e.g., projects, issues)
Enable or disable specific workflows within a topic
Support conditional delivery rules (e.g., owner-only, thresholds, filters)
Context-aware preferences: manage subscriptions differently across environments, tenants, or custom contexts using contextKeys
Multiple subscriptions per topic with different conditions
Fully customizable UI with theming, localization, and headless hooks
Works seamlessly with Inbox and existing workflow/global preferences
Previously, subscribers could only control notifications at the workflow or channel level.
Subscriptions now unlock:
Topic-level muting (e.g., turn off updates for project:43)
Context-scoped preferences: filter and match subscriptions by context, with behavior safely gated behind the feature flag
Advanced, structured preferences stored as JSON conditions
Contextual subscription management directly on entities like projects or tasks
Behind the scene, we've added robust support for contextKeys throughout the inbox and subscription modules. Sorted for consistency, validated across commands, and integrated into identifier logic for uniqueness.
This lays the groundwork for granular notification preferences in multi-context environments while maintaining backward compatibility when context features are disabled.
Removed the default custom font URL from block-based email content. Now, it uses system default fonts instead.
Subscriber preferences now support context-aware binding. You can set and retrieve preferences for specific contexts, such as tenants or environments. If there's no context-specific value, it will use the global preferences instead.
Pagination preferences now persist across sessions. When you change how many items show per page, it saves your choice. The next time you visit, your selection will be restored.
Webhook messages now include workflow and step identifiers. Each webhook payload now includes workflowId and stepId. This gives you better context for tracking and routing events.
You can now configure digest lookback windows directly in the workflow editor. When digest mode is on, you’ll find new options for how far back to look. You can pick from quick presets: immediately, 5 minutes, or 30 minutes. You can also enter a custom value.
Fixes (1)
Fixed the problem where duplicating a workflow didn't copy schema fields. This includes payloadSchema, validatePayload, and severity. These properties are now correctly preserved when workflows are duplicated.
Route notifications to Slack or Microsoft Teams channels and DMs using your app identity. One integration, simple OAuth per customer, and Novu handles the rest.
Notify Slack channels, Microsoft Teams, and users through DMs using your app identity.
The new chat integrations let you connect your Slack app or Microsoft Teams bot to Novu. You can then route notifications to the exact destinations your users choose.
Messages go where they’re needed. You can alert teams about server problems. You can update hiring managers on candidates. You can send operational alerts to specific channels.
Both integrations work the same way:
First, set up your app credentials in Novu.
Then, let users connect their workspaces via OAuth.
Finally, register endpoints for channels or users.
Novu handles token management. It routes messages and delivers them. All this happens across different customer tenants using a single integration.
Slack integration beta
The Slack chat integration bot is currently in beta. Contact [email protected] to enable it for your organization.
Multi-tenant by design
A single Slack app or Teams bot can serve all your customers. Each customer connects their own workspace through a one-time OAuth consent flow.
Novu keeps the connection for you. It sends messages on your app's behalf.
You won't need to manage tokens. Also, you won't have to set up separate integrations for each customer.
In Microsoft Teams, your customers grant admin consent only once. Then, Novu can send messages to any team or user with your app installed.
Users authorize their Slack workspace, so you can quickly route messages to channels or DMs.
Flexible delivery targets
Create Channel Endpoints to define exactly where notifications should land:
Channels: Post to `#alerts`, `#engineering`, or any channel where your app has access
Direct messages: Send personal notifications to individual users
Webhooks: Use Slack incoming webhooks or Teams Workflows. They allow easy channel-only delivery without needing a full bot setup.
When you trigger a Workflow, Novu matches the subscriber and context to the right endpoints and delivers messages through the appropriate workspace connection.
Novu cloud infrastructure is now available in five additional regions, enabling lower-latency delivery and improved data residency support for teams operating in these geographies.
Novu now supports deploying its cloud infrastructure in five new geographic regions: Australia (AU), Korea (KR), Japan (JP), Singapore (SG), and the United Kingdom (UK).
This expansion enables you to run Novu services closer to your users in these regions, resulting in improved performance and enhanced data residency compliance.
Novu now supports full multi-tenancy using Contexts, making it possible to isolate notifications, preferences, and credentials across tenants, workspaces, or applications within a single project.
All generated messages are tagged with the tenant:org-acme key.
You can later query or filter by this key using the API.
GET /v2/notifications?contextKey=tenant:org-acme
Within templates or layouts, context.tenant.data can be used for branding or logic:
{{context.tenant.data.name}} has a new billing update.
Supported use cases
Per-tenant isolation for notifications
Tenant-level credentials for chat integrations (e.g., Teams, Slack)
Dynamic content and branding driven by context data
Workspace or app-level scoping within shared environments
Real-world examples
A SaaS platform with multiple customer organizations sending workspace-specific updates.
An enterprise product using chat integrations where each workspace manages its own credentials.
An application separating preferences across multiple apps or environments under one Novu project.
Multi-tenancy in Novu introduces a consistent and reliable way to manage notification boundaries across tenants, workspaces, or applications, without duplicating workflows or environments.
Contexts make it simple to design systems where every notification and credential is tied to the right scope, predictable, queryable, and isolated by design.
Define tenant, app, or workspace context once, and Novu automatically scopes every notification, Inbox feed, preference, and delivery path to that context. No duplicated workflows, no custom filters, and no risk of cross-tenant leaks.
This feature is currently in beta. If you'd like to access Contexts, please email our support team at [email protected]
A Context in Novu is a structured object that describes the environment or scope to which a notification belongs. Instead of embedding metadata (like tenant ID or app name) into every trigger payload, you can now store it once and reference it everywhere.
When defining contexts, Novu supports multiple formats per key-value pair, allowing you to store and reference metadata relevant to your workflows and templates.
await novu.trigger('welcome-email', { to: 'user123', payload: { userName: 'John' }, context: { // Simple string format tenant: 'acme-corp', // Rich object format (ID only) app: { id: 'jira' }, // Rich object format (ID + data) region: { id: 'us-east', data: { name: 'US East', timezone: 'America/New_York', currency: 'USD' } } }});
As products mature, they typically shift from serving a single user group to supporting multiple groups.
Each organization, environment, or workspace has its own unique data, brand, and set of rules.
Most notification systems regard users as a single group with the same feeds, which leads teams to create weak filters and have duplicate subscribers across different tenants.
This is where <Inbox /> with Contexts excels for managing multi-tenancy. It offers built-in support directly at the notification layer, providing each tenant with a dedicated Inbox setup. This approach keeps your subscriber model and workflows intact without requiring any duplication.
Inbox Scoped by Context
When you render the Inbox, merely pass the same context:
The <Inbox /> knows precisely which messages to load, filtered by context.
Subscribers can switch between tenants or workspaces. Each one shows its own separate feed and settings.
Inbox A → tenant:org-acme
Inbox B → tenant:org-globex
Inbox C → tenant:org-novu
Each has its own unread counts, archived messages, and rules. They all use a single subscriber ID (user-123).
feat(dashboard,api-service, worker): include inbox unread count in the FCM and Expo messages available on the app badge
feat(worker): device token invalidation logic for FCM and Expo is now enabled, in active tokens will be removed and notified via the message.failed webhook
Fixes (4)
fix(api-service,application-generic): Passing null values when updating subscriber will now properly recognize and persist them
fix(api-service): translation keys escaping bug caused \"\ fields when used escaped fields in the i18n files
fix(js): notification count display for 99+ was properly fixed, where previously 100 was shown.