-Install the [Mintlify CLI](https://www.npmjs.com/package/mintlify) to preview the documentation changes locally. To install, use the following command
+
+
+
` if `author` is truthy. |
+| includeZero | `includeZero=true` treats the conditional as not empty, handling 0 differently. | `{{#if 0 includeZero=true}}
Does render
{{/if}}` | Renders `
Does render
` for 0. |
+| Sub-Expressions | Create custom logic helpers and use them in sub-expressions. | `{{#if (isdefined value1)}}true{{else}}false{{/if}}` | Renders `true` or `false` based on custom helper. |
+| unless | Inverse of if helper. Renders a block if the expression is falsy. | `{{#unless license}}
WARNING
{{/unless}}` | Renders warning if `license` is falsy. |
+| each | Iterate over a list. Use this to reference the iterated element. | `{{#each people}}
{{this}}
{{/each}}` | Renders list items. |
+| with | Change context for template parts. | `{{#with person}}{{firstname}} {{lastname}}{{/with}}` | Renders `firstname` and `lastname` from the context. |
+| Nested each | Access iteration variables in nested each blocks. | `{{#each array}}{{@index}}: {{this}}{{/each}}` | Renders index and item in each iteration. |
+| Nested with | Use with block parameters for clear code. | See above example with nested with and complex template. | Renders nested context values. |
+| | You can use else section to handle empty values. | `{{#with city}}...{{else}}No city found{{/with}}` | Handles empty context case. |
+
+# Novu-specific helpers
+
+| Handlebar Expression | Description |
+| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `{{dateFormat date 'EEEE, MMMM Do yyyy'}}` | You can format the date using the `dateFormat` function. Here, `date: '2020-01-01'` has been formatted into `Wednesday, January 1st 2020`. |
+| `{{lowercase key}}` | This helps you use the `lowercase` handlebar helper function and turns the value of the specified key to its lowercase value. So, for `message: 'hEllo WORLD'`, if we write `{{lowercase message}}`, we'll end up with `hello world`. |
+| `{{uppercase key}}` | This helps you use the `uppercase` handlebar helper function and turns the value of the specified key to its uppercase value. So, for `message: 'hello woRld'`, if we write `{{uppercase message}}`, we'll end up with `HELLO WORLD`. |
+| `{{titlecase key}}` | This helps you use the `titlecase` handlebar helper function and turns the value of the specified key to its titlecase value. So, for `message: 'hEllo wOrLD'`, if we write `{{titlecase message}}`, we'll end up with `Hello World`. |
+
+### groupBy
+
+`groupBy` helper is used to group the items in an array based on a property.
+
+
+
+```html
+{{#each (groupBy names "name")}}
+
+```
+
+
+
+### numberFormat
+
+`numberFormat` helper is used to format numbers with specified decimal length, thousands separator, and decimal separator.
+
+
+
+```html
+
{{numberFormat number decimalSep="," decimalLength="2" thousandsSep="|"}}
+```
+
+
+
+### pluralize
+
+The `pluralize` helper allows you to easily handle pluralization in your templates by providing different forms of a word depending on a variable value.
+
+### Basic Usage
+
+In its simplest form, the `pluralize` helper takes three arguments:
+
+```
+{{pluralize count singular plural}}
+```
+
+- `count`: The numeric value that determines whether the singular or plural form should be used.
+- `singular`: The singular form of the word.
+- `plural`: The plural form of the word.
+
+#### Example
+
+```
+{{pluralize dog_count "dog" "dogs"}}
+```
+
+In this example, if `dog_count` is equal to 1, it will render "1 dog," and if it's greater than 1, it will render "dogs."
+
+## Use Cases & Examples
+
+### Handling Event Count Display with Excluded Individuals
+
+In some cases, you may want to display the total count of certain events but exclude specific individuals who are already mentioned. For example, when using a phrase like "John and `{{step.total_count}}` people liked your photo," you may notice that the count is off by one because "John" is already mentioned.
+
+To account for such scenarios, you can utilize the following approach:
+
+```
+{{#each step.events}}
+ {{#if @first}}
+ {{this.name}}
+ {{else}}
+ {{#if @last}}
+ and {{@index}}
+ {{/if}}
+ {{/if}}
+{{/each}}
+followed you!
+```
+
+In this code, we iterate through the `step.events` array and conditionally display each name. If it's the first name in the list, it will be shown without "and." For subsequent names, we add "and" before the last name. This ensures that the count is not affected by names that are explicitly mentioned in the message.
+
+By using this code, you can achieve a more accurate representation of the event count in your messages, even when some users are individually mentioned in the message text.
+
+### Using array length as count
+
+Array length be used as total number of item. For example, if paylod have fruits property of type array then its length can be used as total number of fruits.
+
+
+
+```html
+Total number of fruits is {{fruits.length}}.
+```
+
+
+```json
+{
+ "fruits": [
+ {
+ "name": "Pine apple",
+ "price": "10$"
+ },
+ {
+ "name": "Apple",
+ "age": "8$"
+ },
+ {
+ "name": "Orange",
+ "age": "5$"
+ }
+ ]
+}
+```
+
+
+```html
+Total number of fruits is 3.
+```
+
+
+
+
+ {" "}
+ In a future release, we plan to replace handlebar helpers with an alternative solution.
+ Please note that custom handlebars in the editor itself are not currently supported.
+ If we are missing any handlebar helper that is blocking you to write template for
+ use case, feel free to reach out to us in [discord](https://discord.gg/novu?ref=docs-handlebar-helper)
+
diff --git a/content-creation-design/layouts.mdx b/content-creation-design/layouts.mdx
new file mode 100644
index 000000000..67c0ccbc3
--- /dev/null
+++ b/content-creation-design/layouts.mdx
@@ -0,0 +1,178 @@
+---
+title: "Layouts"
+description: "Explore how to create and manage layouts in Novu"
+icon: "table-layout"
+---
+
+### Email Layouts
+
+Novu allows the creation of layouts - a specific HTML design or structure to wrap content of email notifications. Layouts can be manipulated and assigned to new or existing workflows within the Novu platform, allowing users to create, manage, and assign these layouts to workflows, so they can be reused to structure the appearance of notifications sent through the platform.
+
+By default, Novu will create a default layout and assign it as the organization's default layout. At any time, you can choose any of your layouts as the default for your organization. All new email templates will be assigned the default layout unless assigned a different one through the email editor.
+
+#### Manage Layouts
+
+You can find and manage your organization's layouts in `Brand -> Layouts`
+
+
+
+#### Create and Edit Layouts
+
+You can create new or edit existing layouts through the layout editor.
+
+- You can create any html code to structure your layout.
+- Set a layout as default for your organization. Notice there could only be one default layout at a time.
+- Manage layout variables - set default values or required variables.
+
+
+
+ Layout content must include `{{{body}}}`, to indicate where the email editor content will be injected inside the layout.
+
+#### Assign layout to workflow
+
+To assign, choose a layout through the email editor. You can preview your layout combined with your email content through the `Preview` tab.
+
+
+
+#### Override layout on trigger
+
+To override your assigned layout during a trigger event, use the `layoutIdentifier` property.
+
+The layout specified will be used for all emails in the context of that trigger event.
+
+```ts
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+novu.trigger("workflow-identifier", {
+ to: {
+ subscriberId: "",
+ },
+ payload: {
+ attachments: [
+ {
+ file: fs.readFileSync(__dirname + "/data/test.jpeg"),
+ name: "test.jpeg",
+ mime: "image/jpg",
+ },
+ ],
+ },
+ overrides: {
+ layoutIdentifier: "your-layout-identifier",
+ },
+});
+```
+
+
+ {" "}
+ The override layout on trigger functionality is only available on v0.19.0.
+
+
+#### Using SDK
+
+Novu SDK supports all layout functionalities:
+
+#### Create a new layout
+
+A new layout can be created with name, description, content, variables and an `isDefault` flag. Here, content param is html content with custom variables.
+
+```tsx
+const name: string = "layout-name";
+const description: string =
+ "The description of the layout that will help other users to understand the goal it was created"; // Optional.
+const content: string = "";
+const variables: ITemplateVariable[] = []; // Optional. Will handle the placeholder variables inserted in the email layout (content).
+const isDefault: boolean = true; // Optional. All layouts are created as non default if not stated otherwise.
+
+const { _id: layoutId } = await novu.layouts.create({
+ name,
+ description,
+ content,
+ variables,
+ isDefault,
+});
+```
+
+```tsx
+interface ITemplateVariable {
+ type: TemplateVariableTypeEnum;
+ name: string;
+ required?: boolean;
+ defaultValue?: string | boolean;
+}
+
+enum TemplateVariableTypeEnum {
+ STRING = "String",
+ ARRAY = "Array",
+ BOOLEAN = "Boolean",
+}
+```
+
+#### Update existing layout
+
+When updating a layout, all properties are optional and the SDK will only update the ones passed.
+
+```tsx
+const layoutId: LayoutId = ""; // The unique identifier of the layout.
+
+const updatedLayout = await novu.layouts.update(layoutId, {
+ name,
+ description,
+ content,
+ variables,
+ isDefault,
+});
+```
+
+#### Set default layout
+
+When executing this, the existing default layout in the environment will be automatically set as non default and the chosen layout will be set as default. This action is non reversible.
+
+```tsx
+const layoutId: LayoutId = ""; // The unique identifier of the layout to be set as default.
+
+await novu.layouts.setDefault(layoutId);
+```
+
+#### Delete an existing layout
+
+Layouts can also be deleted. The condition to be able to delete a layout is that it is not a default layout and is not assigned in any existing workflow.
+
+```tsx
+const layoutId: LayoutId = ""; // The unique identifier of the layout to be deleted.
+
+await novu.layouts.delete(layoutId);
+```
+
+#### Get a layout
+
+Find a layout by layoutId
+
+```tsx
+const layoutId: LayoutId = ""; // The unique identifier of the layout to be found.
+
+const layout = await novu.layouts.get(layoutId);
+```
+
+#### List all layouts
+
+List paginated layouts
+
+```tsx
+const page: number = 0; // Pagination value of the page for the results. First page will be page = 0.
+const pageSize: number = 100; // Optional. Pagination value of the amount of layouts per page to return.
+const sortBy: string = "createdAt"; // Optional. Property to order the list of the layouts. So far only `createdAt` is supported.
+const orderBy: OrderDirectionEnum = -1; // Optional. Direction of the sorting by the property chosen in `sortBy`. Ascendent order is represented by 1 and descendent order is represented by -1.
+
+const layouts = await novu.layouts.list({
+ page,
+ pageSize,
+ sortBy,
+ orderBy,
+});
+```
+
+## API Reference Links
+
+- [Layout Methods](/api-reference/layouts/layout-creation/)
diff --git a/content-creation-design/notification-content-creation.mdx b/content-creation-design/notification-content-creation.mdx
new file mode 100644
index 000000000..8d7132e5d
--- /dev/null
+++ b/content-creation-design/notification-content-creation.mdx
@@ -0,0 +1,206 @@
+---
+title: "Content Creation"
+description: "Explore how to create notification content"
+icon: "pen"
+---
+
+To demonstrate the extensive range of possibilities, we've crafted a subscriber profile enriched with various attributes to highlight the flexibility of our system.
+
+```typescript
+const subscriber = {
+ subscriberId: "6427e97d0136cef86a315c46",
+ firstName: "John",
+ lastName: "Doe",
+ email: "john.doe@gmail.com",
+ phone: "+98712345677",
+ avatar:
+ "https://sm.ign.com/ign_nordic/cover/a/avatar-gen/avatar-generations_prsz.jpg",
+ locale: "en-US",
+ data: {
+ plan: "basic",
+ zipcode: 14925,
+ validVehicleLicense: true,
+ },
+};
+```
+
+Let's go over examples for each communication channel:
+
+## Email
+
+There are multiple ways to craft your email notification content for maximum impact.
+
+
+ Please remember that you have the option to preview the anticipated output of
+ your input using the editor. Simply switch from the editing mode to the
+ preview mode to see the results.
+
+
+### Regular Editor
+
+Example: Send a personalized welcome email to a user by leveraging their properties.
+
+**Input:**
+
+```html
+Hello {{subscriber.firstName}} {{subscriber.lastName}}! We are excited to
+welcome you to our {{subscriber.data.plan}} plan. Look forward to receiving
+daily updates from us on your phone number: {{subscriber.phone}}. {{#if
+subscriber.data.validVehicleLicense}} Why not consider renting a car to visit
+us? {{else}} We're delighted to offer you a train ticket to come see us. {{/if}}
+Should you require any assistance, don't hesitate to reach out. Best regards,
+Your friends at Novu.
+```
+
+
+
+**Output:**
+
+```html
+Hello John Doe! We are excited to welcome you to our basic plan. Look forward to
+receiving daily updates from us on your phone number: +98712345677. Why not
+consider renting a car to visit us? Should you require any assistance, don't
+hesitate to reach out. Best regards, Your friends at Novu.
+```
+
+
+
+### Custom Code Editor
+
+**Input:**
+
+
+ ```HTML
+
+
+
+
+ Welcome to Novu!
+
+
+
+
We are thrilled to have you on board with our {{subscriber.data.plan}} plan.
+
Get ready to receive daily updates on your phone: {{subscriber.phone}}.
+
{{#if subscriber.data.validVehicleLicense}}
+ We would like to offer you renting a car to visit us.
+ {{else}}
+ We would like to buy you a train ticket to visit us.
+ {{/if}}
+
If you need any assistance or have questions, feel free to reach out.
+ )}
+ />
+
+ );
+}
+```
+
+### Bring your own Popover
+
+`` can be mounted in your own popover component. For further
+customization, you can also use the `renderBell` and `renderNotification` render
+props. Below is an example of how to use `` with [Radix
+UI](https://www.radix-ui.com/).
+
+```tsx
+import React from 'react';
+import * as Popover from '@radix-ui/react-popover';
+import { BellIcon, Cross2Icon } from '@radix-ui/react-icons';
+import { Inbox, Bell, Notifications } from '@novu/react';
+import './styles.css';
+
+const PopoverDemo = () => (
+
+
+
+ (
+
+ {unreadCount}
+
+
+ )}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+export default PopoverDemo;
+```
diff --git a/inbox/react/components/inbox-content.mdx b/inbox/react/components/inbox-content.mdx
new file mode 100644
index 000000000..a0ea77b23
--- /dev/null
+++ b/inbox/react/components/inbox-content.mdx
@@ -0,0 +1,72 @@
+---
+title: ""
+---
+
+By default, `` renders the content of the `` popover. This component is meant to be used with a custom popover.
+
+```tsx
+import { Bell, Inbox, InboxContent } from '@novu/react';
+import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
+
+export default function CustomPopoverPage() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+}
+```
+
+## Behaviour
+
+The `` component can receive all the props that `` does, besides the configuration and bell specific ones.
+
+```tsx
+import { Bell, Inbox, InboxContent } from '@novu/react';
+import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
+
+export default function CustomPopoverPage() {
+ return (
+
+
+
+
+
+
+ {
+ // your logic to handle notification click
+ }}
+ onPrimaryActionClick={(notification) => {
+ // your logic to handle primary action click
+ }}
+ onSecondaryActionClick={(notification) => {
+ // your logic to handle secondary action click
+ }}
+ renderNotification={(notification) => (
+
+
{notification.subject}
+
{notification.body}
+
{notification.data.text}
+
+ )}
+ />
+
+
+
+ );
+}
+```
diff --git a/inbox/react/components/inbox.mdx b/inbox/react/components/inbox.mdx
new file mode 100644
index 000000000..386247811
--- /dev/null
+++ b/inbox/react/components/inbox.mdx
@@ -0,0 +1,245 @@
+---
+title: ''
+---
+
+By default, the `` renders a bell button, that opens a popover on click. The popover contains the notifications list and the user preferences.
+
+```tsx
+import { Inbox } from '@novu/react';
+
+function Novu() {
+ return (
+
+ );
+}
+```
+
+## Navigation
+
+The Inbox component uses the `routerPush` prop to make your notifications navigatable. We will automatically pass the `redirect.url` from your workflow definitions to the `routerPush` prop.
+
+To make the navigation work, you will need to specify the `routerPush` behaviour depending on your routing library.
+
+
+ ```tsx Next.js
+ import { Inbox } from '@novu/react';
+ import { useRouter } from 'next/navigation'
+
+ function Novu() {
+ const router = useRouter();
+
+ return (
+ router.push(path)}
+ />
+ );
+ }
+ ```
+
+ ```tsx Remix
+ import { Inbox } from '@novu/react';
+ import { useNavigate } from '@remix-run/react';
+
+ function Novu() {
+ const navigate = useNavigate();
+
+ return (
+ navigate(path)}
+ />
+ );
+ }
+ ```
+
+ ```tsx React Router
+ import { Inbox } from '@novu/react';
+ import { useNavigate } from 'react-router-dom';
+
+ function Novu() {
+ const navigate = useNavigate();
+
+ return (
+ navigate(path)}
+ />
+ );
+ }
+ ```
+
+ ```tsx Gatsby
+ import { Inbox } from '@novu/react';
+ import { navigate } from 'gatsby';
+
+ function Novu() {
+ return (
+ navigate(path)}
+ />
+ );
+ }
+ ```
+
+ ```tsx Create React App
+ import { Inbox } from '@novu/react';
+ import { useNavigate } from 'react-router-dom';
+
+ function Novu() {
+ const navigate = useNavigate();
+
+ return (
+ navigate(path)}
+ />
+ );
+ }
+ ```
+
+
+
+### Handle notification click
+
+In some cases, you might want to handle the notification click event without navigating. You can do so by passing a callback function to the `onNotificationClick` prop.
+
+This can be useful if you want to open a modal or a drawer instead of navigating to a page.
+
+```tsx
+import { Inbox } from '@novu/react';
+
+function Novu() {
+ return (
+ {
+ // your logic to handle notification click
+ }}
+ />
+ );
+}
+```
+
+### Handler action clicks
+
+For scenarios where you want to handle the action button click event without navigating, you can pass a callback function to the `onPrimaryActionClick` and `onSecondaryActionClick` props.
+
+In the callback function, an http request can be made or any other logic can be implemented. For common usecases such as accepting a friend request, a project invitation, etc...
+
+```tsx
+import { Inbox } from '@novu/react';
+
+function Novu() {
+ return (
+ {
+ // your logic to handle primary action click
+ }}
+ onSecondaryActionClick={(notification) => {
+ // your logic to handle secondary action click
+ }}
+ />
+ );
+}
+```
+
+## Controlled Popover state
+
+```tsx
+import { Inbox } from '@novu/react';
+
+function Novu() {
+ const [open, setOpen] = React.useState(false);
+
+ return (
+ <>
+
+
+ >
+ );
+}
+```
+
+## Custom Notification item
+
+Customize the notification item by passing a render function to the `renderNotification` prop.
+You can access the notification object and render the notification item as per your requirements.
+The `notification.data` property allows you acessing the custom information while rendering notification item.
+You can check how to pass it with the Novu Framework in-app step output [here](/framework/typescript/steps/inApp).
+
+```tsx
+import { Inbox } from '@novu/react';
+
+function Novu() {
+ return (
+ (
+
+ )}
+ />
+ );
+}
+```
+
+## Filter visible preferences
+
+You can customize the visible preferences by passing the `preferencesFilter` prop to the Inbox component, allowing you to display only relevant preferences to your users.
+The filtering works by matching the workflow [tags](/workflow/overview#tags) field with the specified filter `tags` value, showing workflows that contain at least one associated tag.
+Additionally, you can combine tags from different workflows to create a tailored preferences view.
+
+```tsx
+import { Inbox, Preferences } from '@novu/react';
+
+function Novu() {
+ return (
+
+ );
+}
+```
diff --git a/inbox/react/components/notifications.mdx b/inbox/react/components/notifications.mdx
new file mode 100644
index 000000000..b2642e508
--- /dev/null
+++ b/inbox/react/components/notifications.mdx
@@ -0,0 +1,47 @@
+---
+title: ''
+---
+
+The `Notifications` component is used to display the list of notifications.
+
+### Notifications as a list without the Bell and Popover
+
+```tsx
+import { Inbox, Notifications } from '@novu/react';
+
+function Novu() {
+ return (
+
+
+
+ );
+}
+```
+
+### Notifications as a list with custom Notification item
+
+```tsx
+import { Inbox, Notifications } from '@novu/react';
+
+function Novu() {
+ return (
+
+ (
+
+
{notification.subject}
+
{notification.body}
+
{notification.data.text}
+
+ )}
+ />
+
+ );
+}
+```
diff --git a/inbox/react/components/overview.mdx b/inbox/react/components/overview.mdx
new file mode 100644
index 000000000..465b548e1
--- /dev/null
+++ b/inbox/react/components/overview.mdx
@@ -0,0 +1,126 @@
+---
+title: 'Overview'
+---
+
+## Composition
+
+The Inbox is composed of the following sub-components that you can use to build your Inbox structure and layout:
+
+- [\](/inbox/react/components/inbox) - The Inbox wrapper, which is used to wrap the entire inbox UI and establish the session.
+- [\](/inbox/react/components/bell) - Used to display the bell icon and trigger the popover component when clicked.
+- [\](/inbox/react/components/notifications) - Displays the notifications list.
+- [\](/inbox/react/components/preferences) - Used to display the preferences modal.
+- [\](/inbox/react/components/inbox-content) - Usage with a custom popover.
+
+The internal UI and styles for those components can be modified using the [`appearance`](/inbox/react/styling#appearance-prop) prop.
+
+
+
+
+
+## Layouts
+
+The composition of the indivudal components can generate multiple different popular inbox layouts.
+
+### Inbox with Bell (Default)
+
+A trigger button usually located at the top right corner of the screen, which triggers the popover component when clicked.
+
+
+
+
+```tsx Defualt Bell
+import { Inbox } from '@novu/react';
+
+function Novu() {
+ return (
+
+ );
+}
+```
+
+```tsx Custom Bell
+import { Inbox, Bell } from '@novu/react';
+import { BellIcon } from './icons';
+
+function Novu() {
+ return (
+
+ (
+
+ {unreadCount}
+
+
+ )}
+ />
+
+ );
+}
+```
+
+
+### Side menu Inbox
+
+To render a side menu inbox, use the `` component as a direct child of the `` component, you can hide or show it based on any custom logic.
+
+```tsx
+import { Inbox, Notifications } from '@novu/react';
+
+function Novu() {
+ return (
+
+ {showSideMenu && (
+
+ )}
+
+ );
+}
+```
+
+### Full page Inbox
+
+Similiary to the side menu inbox, you can use the `` component as a direct child of the `` component, you can hide or show it based on any custom logic.
+
+```tsx
+import { Inbox, Notifications } from '@novu/react';
+
+function Novu() {
+ return (
+
+
+
+ );
+}
+```
+
+### Inbox with a custom popover
+
+```tsx
+import { Bell, Inbox, InboxContent } from '@novu/react';
+import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
+
+export default function CustomPopoverPage() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+}
+```
diff --git a/inbox/react/components/preferences.mdx b/inbox/react/components/preferences.mdx
new file mode 100644
index 000000000..e7c2c2667
--- /dev/null
+++ b/inbox/react/components/preferences.mdx
@@ -0,0 +1,46 @@
+---
+title: ""
+description: "Learn how to use and customize the Preferences component in React to manage notification settings."
+---
+
+By default, Novu will show the subscriber preferences cog icon on the Inbox component.
+
+Users can enable/disable any active channel in the workflow using subscriber preferences or they can update the preference globally for all workflows under the `Global Preferences`.
+
+
+
+### Preferences Component
+
+The `Preferences` component is used to display the subscriber preferences, use it when you want to render preference in another part of your application or a custom layout for the Inbox.
+
+```tsx
+import { Inbox, Preferences } from "@novu/react";
+
+function Novu() {
+ return (
+
+
+
+ );
+}
+```
+
+### Filtering preferences
+
+You can filter the preferences visible by the user by specifying the `preferenceFilter` on the `Inbox` component, learn more about it [here](/inbox/react/components/inbox#filter-visible-preferences)
+
+### Hide global preferences
+
+Global subscriber preferences are shown by default, it can hidden by using below code in global css file
+
+```css
+.nv-workflowContainer:first-child {
+ display: none;
+}
+```
diff --git a/inbox/react/get-started.mdx b/inbox/react/get-started.mdx
new file mode 100644
index 000000000..61d5bb540
--- /dev/null
+++ b/inbox/react/get-started.mdx
@@ -0,0 +1,161 @@
+---
+title: 'React Get Started'
+sidebarTitle: 'Quickstart'
+description: 'Learn how to add a Novu-Powered In-App Inbox to your React app'
+---
+
+Novu provides the `@novu/react` package that helps to add a fully functioning Inbox to your web application in minutes. Let's see how easily you can use it in your application.
+
+
+
+```bash
+npm install @novu/react
+```
+
+
+
+```tsx Next.js
+'use client';
+
+import { Inbox } from '@novu/react';
+import { useRouter } from 'next/navigation';
+
+function Novu() {
+ const router = useRouter();
+
+ return (
+ router.push(path)}
+ />
+ );
+}
+```
+```tsx Remix
+import { Inbox } from '@novu/react';
+import { useNavigate } from '@remix-run/react';
+
+function Novu() {
+ const navigate = useNavigate();
+
+ return (
+ navigate(path)}
+ />
+ );
+}
+```
+```tsx React Router
+import { Inbox } from '@novu/react';
+import { useNavigate } from 'react-router-dom';
+
+function Novu() {
+ const navigate = useNavigate();
+
+ return (
+ navigate(path)}
+ />
+ );
+}
+```
+```tsx Gatsby
+import { Inbox } from '@novu/react';
+import { navigate } from 'gatsby';
+
+function Novu() {
+ return (
+ navigate(path)}
+ />
+ );
+}
+```
+```tsx Create React App
+import { Inbox } from '@novu/react';
+import { useNavigate } from 'react-router-dom';
+
+function Novu() {
+ const navigate = useNavigate();
+
+ return (
+ navigate(path)}
+ />
+ );
+}
+```
+
+
+
+ You can find the `applicationIdentifier` in the Novu Dashboard under the [API keys page](https://dashboard-v2.novu.co/api-keys).
+ The `subscriberId` is the unique identifier of the user in your application, learn more about subscribers [here](/concepts/subscribers).
+
+
+ Novu uses the `routerPush` prop to make your notifications navigatable. We will automatically pass the `redirect.url` from your workflow definitions to the `routerPush` prop.
+
+
+ If you are using the European region in novu, you need to set the `backendUrl` and `socketUrl` props.
+ ```tsx
+
+ ```
+
+
+
+ Now that you have the inbox component added to your application, you can trigger an Inbox notification to see it in action.
+ To create your first workflow, follow our [quickstart guide](/getting-started/quickstart).
+
+
+
+
+
+
+
+## Next Steps
+
+
+
+ Learn how to customize the inbox with your own branding and design.
+
+
+ Learn more about the composable components of the inbox.
+
+
+
+## Frequently Asked Questions
+
+
+
+
+Possible reasons for the Inbox not loading properly:
+
+ - Invalid subscriberId
+ - Invalid applicationIdentifier
+ - Invalid subscriberHash (in case of active HMAC encryption)
+ - Invalid backendUrl (in case of self-hosted)
+ - Invalid socketUrl (in case of self-hosted)
+
+
+
+
+ Our Inbox is configures for all hosts. Please disable root level `withCredentials` config in axios or fetch http requests.
+
+
+
diff --git a/inbox/react/hooks/novu-provider.mdx b/inbox/react/hooks/novu-provider.mdx
new file mode 100644
index 000000000..fffe2d628
--- /dev/null
+++ b/inbox/react/hooks/novu-provider.mdx
@@ -0,0 +1,17 @@
+---
+title: 'NovuProvider'
+---
+
+import NovuProviderExample from '/snippets/inbox/react/novu-provider-example.mdx';
+import NovuParams from '/snippets/inbox/headless/api-reference/novu-params.mdx';
+
+The `NovuProvider` is the top-level component that provides the [Novu instance](/inbox/headless/api-reference#novu) to the rest of the hooks through the context.
+Usually, it's placed somewhere in the root of your application, which makes the hooks accessible throughout the application.
+
+## `NovuProvider` props
+
+
+
+## Example usage
+
+
diff --git a/inbox/react/hooks/overview.mdx b/inbox/react/hooks/overview.mdx
new file mode 100644
index 000000000..90372a4e8
--- /dev/null
+++ b/inbox/react/hooks/overview.mdx
@@ -0,0 +1,80 @@
+---
+title: 'Create Custom Inbox UI with React Hooks'
+sidebarTitle: 'Overview'
+---
+
+import UseNotificationsExample from '/snippets/inbox/react/use-notifications-example.mdx';
+import UseUnreadCountExample from '/snippets/inbox/react/use-unread-count-example.mdx';
+import NovuProviderExample from '/snippets/inbox/react/novu-provider-example.mdx';
+
+The `@novu/react` package offers an interface that enables you to build a custom notifications UI using React hooks that are powered by real-time data from the Novu services.
+
+These hooks are designed for use in both mobile and web applications, offering a flexible approach to building a custom notifications UI tailored to your application's requirements.
+
+### Getting Started
+
+Follow these steps to get started with building your custom inbox UI:
+
+
+
+ ```bash
+ npm install @novu/react
+ ```
+
+
+ To implement the [NovuProvider](/inbox/react/hooks/novu-provider) component, you need to place it in your application's code at the tree level where you want the hooks to be accessible. Here's how you can do it:
+
+
+ You can find the `applicationIdentifier` in the Novu Dashboard under the [API
+ keys page](https://dashboard-v2.novu.co/api-keys). The `subscriberId` is the
+ unique identifier of the user in your application, learn more about
+ subscribers [here](/concepts/subscribers).
+
+
+
+
+ For example, you can create a custom popover UI with a bell icon that shows the unread notifications count and a list of notifications.
+ ```tsx
+ const YourCustomInbox = () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+ };
+ ```
+
+ The `BellButton` component fetches the unread notifications count and renders the count value in the indicator.
+
+
+
+ The `NotificationsList` component retrieves and displays the notifications list with infinite scrolling functionality.
+
+
+
+ The `NotificationItem` component renders each notification item.
+
+ When any action is performed on the `notification` instance for example "read" button is clicked,
+ the SDK will optimistically update notification that will result in the `useNotifications` hook rerender, so yo don't need to refetch and manually update your UI.
+
+ ```tsx
+ const NotificationItem = ({ notification }) => {
+ return (
+
+ {notification.isRead && }
+
{notification.subject}
+
{notification.body}
+
+
+
+ );
+ };
+ ```
+
+
+
diff --git a/inbox/react/hooks/use-counts.mdx b/inbox/react/hooks/use-counts.mdx
new file mode 100644
index 000000000..96e36906d
--- /dev/null
+++ b/inbox/react/hooks/use-counts.mdx
@@ -0,0 +1,14 @@
+---
+title: 'useCounts'
+---
+
+import UseUnreadCountExample from '/snippets/inbox/react/use-unread-count-example.mdx';
+import UseCountsContent from '/snippets/hooks/use-counts-content.mdx';
+
+
+
+## Example usage
+
+The below example demonstrates how to use the `useCounts` hook to fetch the unread notifications count.
+
+
diff --git a/inbox/react/hooks/use-notifications.mdx b/inbox/react/hooks/use-notifications.mdx
new file mode 100644
index 000000000..d4037144c
--- /dev/null
+++ b/inbox/react/hooks/use-notifications.mdx
@@ -0,0 +1,12 @@
+---
+title: 'useNotifications'
+---
+
+import UseNotificationsExample from '/snippets/inbox/react/use-notifications-example.mdx';
+import UseNotificationsContent from '/snippets/hooks/use-notifications-content.mdx';
+
+
+
+## Example usage
+
+
diff --git a/inbox/react/hooks/use-novu.mdx b/inbox/react/hooks/use-novu.mdx
new file mode 100644
index 000000000..7ca54d41b
--- /dev/null
+++ b/inbox/react/hooks/use-novu.mdx
@@ -0,0 +1,30 @@
+---
+title: 'useNovu Hook for React'
+sidebarTitle: 'useNovu'
+---
+
+import UseNovuContent from '/snippets/hooks/use-novu-content.mdx';
+
+
+
+```tsx
+import { useNovu } from '@novu/react/hooks';
+
+const NotificationToast = () => {
+ const novu = useNovu();
+
+ useEffect(() => {
+ const listener = ({ result: notification }) => {
+ // Show a toast notification
+ };
+
+ novu.on('notifications.notification_received', listener);
+
+ return () => {
+ novu.off('notifications.notification_received', listener);
+ };
+ }, [novu]);
+
+ return null;
+};
+```
\ No newline at end of file
diff --git a/inbox/react/hooks/use-preferences.mdx b/inbox/react/hooks/use-preferences.mdx
new file mode 100644
index 000000000..7020661eb
--- /dev/null
+++ b/inbox/react/hooks/use-preferences.mdx
@@ -0,0 +1,26 @@
+---
+title: 'usePreferences Hook for React'
+sidebarTitle: 'usePreferences'
+---
+
+import UsePreferencesContent from '/snippets/hooks/use-preferences-content.mdx';
+
+
+
+## Example usage
+
+```tsx
+import { usePreferences } from '@novu/react/hooks';
+
+const PreferencesList = () => {
+ const { preferences, isLoading, error, refetch } = usePreferences();
+
+ return (
+ }>
+ {preferences?.map((preference) => {
+ return ;
+ })}
+
+ );
+};
+```
diff --git a/inbox/react/localization.mdx b/inbox/react/localization.mdx
new file mode 100644
index 000000000..64fa59050
--- /dev/null
+++ b/inbox/react/localization.mdx
@@ -0,0 +1,75 @@
+---
+title: 'Localizing the Inbox component'
+sidebarTitle: 'Localization'
+description: 'Learn how to localize the pre built Inbox component'
+---
+
+## Localization Prop
+
+The `localization` prop can be used to change the copywriting of the Inbox to a different language for your users or change the wording to suit your product. See the list of [available keys](https://github.com/novuhq/novu/blob/next/packages/js/src/ui/config/defaultLocalization.ts#L1), or use the fully typed TS auto complete to find the key you need.
+
+```tsx
+import { Inbox } from '@novu/react';
+
+function Novu() {
+ return (
+
+ `${notificationCount > 99 ? "99+" : notificationCount} new ${
+ notificationCount === 1 ? "notification" : "notifications"
+ }`,
+ "notification.actions.archive.tooltip": "Archive",
+ "notification.actions.unarchive.tooltip": "Unarchive",
+ "preferences.title": "Notification Preferences",
+ "preferences.global": "Global Preferences",
+ "preferences.workflow.disabled.notice":
+ "Contact admin to enable subscription management for this critical notification.",
+ "preferences.workflow.disabled.tooltip": "Contact admin to edit",
+ dynamic: {
+ // use the workflowId as a key to localize the workflow name
+ 'comment-on-post': 'Post comments',
+ },
+ locale: 'en-US',
+ }}
+ />
+ );
+}
+```
+
+### Specifying the workflow name using Framework
+
+In addition to specifying a workflow name in the `` component, you can also specify the workflow name in your Framework definition. The `name` property is optional, so if you don't specify it, the `workflowId` will be used as the name.
+
+```typescript
+import { workflow } from '@novu/framework';
+
+const weeklyCommentsWorkflow = workflow(
+ 'comment-on-post',
+ async ({ step }) => {
+ ...
+ });
+}, {
+ name: 'Post comments', // đ name is optional
+});
+```
+
+Now, your specified workflow name will be displayed in the `` component:
+
+
+
+
diff --git a/inbox/react/migration-guide.mdx b/inbox/react/migration-guide.mdx
new file mode 100644
index 000000000..b3c75cab1
--- /dev/null
+++ b/inbox/react/migration-guide.mdx
@@ -0,0 +1,881 @@
+---
+title: "Migration Guide"
+sidebarTitle: "Migration Guide"
+description: "This guide outlines the key differences between the `@novu/notification-center` package and the new `@novu/react` package. Follow the steps below to migrate your application to the latest version."
+---
+
+ [@novu/react](/inbox/react/get-started) Inbox react component and [@novu/js](/inbox/headless/get-started) headless package is compatible with [@novu/framework](/workflow/overview) based workflows only. With old UI based workflows, our old [@novu/notification-center](https://v0.x-docs.novu.co/notification-center/client/react/get-started) component should be used.
+
+
+The `@novu/react` package introduces a more flexible and customizable way to display notifications in your application. This guide outlines the key differences between the `@novu/notification-center` package and the new `@novu/react` package. Follow the steps below to migrate your application to the latest Inbox version.
+
+## Why you should upgrade to @novu/react
+
+- **Customization**: The `@novu/react` package provides more customization options for the appearance and behavior of the notification components.
+- **Flexibility**: The new package offers more flexibility in handling notifications and integrating with third-party libraries.
+- **Performance**: It is optimized for performance and provides a smoother user experience.
+- **Bundle Size**: The new package has a smaller bundle size and improved tree-shaking capabilities.
+- **Compatibility with the `@novu/framework`**: The `@novu/react` package is designed to work seamlessly with the `@novu/framework` package for creating and managing notifications.
+
+## Breaking Changes
+
+The `@novu/react` package introduces several breaking changes compared to the `@novu/notification-center` package. Here are the key differences:
+
+### Components
+
+- The `PopoverNotificationCenter` component has been replaced with the `Inbox` component.
+- The `NotificationCenter` component has been replaced with the `Notifications` component.
+- The `NotificationBell` component has been replaced with the `Bell` component.
+
+### Styling
+
+- The `styles` props is replaced by an enchanced and easy to use `appearance` prop to customize the appearance of the notification components. For more information on `appearance` customization visit [here](/inbox/react/styling).
+
+### Notification
+
+- Removal of `seen` , `lastSeenDate`, `content`, `templateIdentifier`, `payload`, `cta` properties from the Notification object.
+- We have introduced `archive` functionality to the Notification object.
+
+```diff
+type Notification = {
+- _id: string;
++ id: string;
+
+- content: string;
++ body: string;
+
+- cta: IMessageCTA;
++ redirect?: Redirect;
++ primaryAction?: Action;
++ secondaryAction?: Action;
+
+- channel: ChannelTypeEnum;
++ channelType: ChannelType;
+
+- payload: Record;
++ data?: Record;
+
+- subscriber: Subscriber;
++ to: Subscriber;
+
+- seen: boolean;
+- lastSeenDate: string;
+- templateIdentifier: string;
+
++ subject?: string;
++ isRead: boolean;
++ isArchived: boolean;
++ readAt?: string | null;
++ archivedAt?: string | null;
++ avatar?: string;
++ tags?: string[];
+
+createdAt: string;
+};
+
+
+type Subscriber = {
+ id: string;
+ firstName?: string;
+ lastName?: string;
+ avatar?: string;
+ subscriberId: string;
+};
+
+type Redirect = {
+ url: string;
+ target?: '_self' | '_blank' | '_parent' | '_top' | '_unfencedTop';
+};
+
+type Action = {
+ label: string;
+ isCompleted: boolean;
+ redirect?: Redirect;
+};
+```
+
+## Getting Started
+
+To begin migrating to `@novu/react`, install the package via npm:
+
+```bash
+npm install @novu/react
+```
+
+## Basic Usage
+
+- Old Implementation
+
+```tsx
+import {
+ NovuProvider,
+ PopoverNotificationCenter,
+ NotificationBell,
+} from "@novu/notification-center";
+
+function Novu() {
+ return (
+
+
+ {({ unseenCount }) => }
+
+
+ );
+}
+export default Novu;
+```
+
+- New Implementation with `@novu/react`
+
+```tsx
+import { Inbox } from "@novu/react";
+
+function Novu() {
+ return (
+
+ );
+}
+
+export default Novu;
+```
+
+## Notification Center without Bell Icon
+
+The @novu/react package introduces a flexible way to display notifications as a list without the default bell icon. Utilize the `Inbox` and `Notifications` components to achieve this functionality.
+
+- Old Implementation
+
+```tsx
+import { NovuProvider, NotificationCenter } from "@novu/notification-center";
+
+function Novu() {
+ return (
+
+
+
+ );
+}
+
+export default Novu;
+```
+
+- New Implementation with `@novu/react`
+
+```tsx
+import { Inbox, Notifications } from "@novu/react";
+
+function Novu() {
+ return (
+
+
+
+ );
+}
+
+export default Novu;
+```
+
+## Custom Bell Icon
+
+Customize the bell icon that triggers the notifications popover using the `renderBell` prop.
+
+- Old Implementation
+
+```tsx
+import {
+ NovuProvider,
+ PopoverNotificationCenter,
+} from "@novu/notification-center";
+import CustomBell from "./CustomBell"; // Your custom bell icon component
+
+function Novu() {
+ return (
+
+
+ {({ unseenCount }) => (
+
+ )}
+
+
+ );
+}
+
+export default Novu;
+```
+
+- New Implementation with `@novu/react`
+
+```tsx
+import { Inbox } from "@novu/react";
+import CustomBell from "./CustomBell"; // Your custom bell icon component
+
+function Novu() {
+ return (
+ }
+ />
+ );
+}
+
+export default Novu;
+```
+
+## Notification Actions
+
+Handle user interactions with notifications effectively using the action handlers provided by `@novu/react`.
+
+### onNotificationClick
+
+Trigger a callback function when a user clicks on a notification item.
+
+- Old Implementation
+
+```tsx
+import {
+ NovuProvider,
+ PopoverNotificationCenter,
+ NotificationBell,
+ IMessage,
+} from "@novu/notification-center";
+
+function Novu() {
+ function handleOnNotificationClick(message: IMessage) {
+ // your logic to handle the notification click
+ if (message?.cta?.data?.url) {
+ window.location.href = message.cta.data.url;
+ }
+ }
+
+ return (
+
+
+ {({ unseenCount }) => }
+
+
+ );
+}
+
+export default Novu;
+```
+
+- New Implementation with `@novu/react`
+
+```tsx
+import { Inbox } from "@novu/react";
+
+function Novu() {
+ const handleNotificationClick = (notification) => {
+ // Your custom logic here
+ console.log("Notification clicked:", notification);
+ };
+
+ return (
+
+ );
+}
+
+export default Novu;
+```
+
+### onPrimaryActionClick and onSecondaryActionClick
+
+Handle primary and secondary actions within a notification explicitly.
+
+- Old Implementation
+
+```tsx
+import {
+ NovuProvider,
+ PopoverNotificationCenter,
+ IMessage,
+ MessageActionStatusEnum,
+ useUpdateAction,
+ ButtonTypeEnum,
+ NotificationBell,
+} from "@novu/notification-center";
+
+function Novu() {
+ const CustomNotificationCenter = () => {
+ const { updateAction } = useUpdateAction();
+
+ const handleOnActionClick = async (
+ templateIdentifier: string,
+ btnType: ButtonTypeEnum,
+ notification: IMessage
+ ) => {
+ if (templateIdentifier === "friend-request") {
+ if (btnType === "primary") {
+ /** Call your API to accept the friend request here **/
+
+ /** And then update Novu that this action has been taken, so the user won't see the button again **/
+ updateAction({
+ messageId: notification._id,
+ actionButtonType: btnType,
+ status: MessageActionStatusEnum.DONE,
+ });
+ }
+ }
+ };
+
+ return (
+
+ {({ unseenCount }) => }
+
+ );
+ };
+
+ return (
+
+
+
+ );
+}
+
+export default Novu;
+```
+
+- New Implementation with `@novu/react`
+
+```tsx
+import { Inbox } from "@novu/react";
+
+function Novu() {
+ const handlePrimaryActionClick = (notification) => {
+ // Handle primary action
+ console.log("Primary action clicked:", notification);
+ };
+
+ const handleSecondaryActionClick = (notification) => {
+ // Handle secondary action
+ console.log("Secondary action clicked:", notification);
+ };
+
+ return (
+
+ );
+}
+
+export default Novu;
+```
+
+## Avatar Icons
+
+Customize the avatar displayed alongside notifications by specifying an avatar `URL` at the workflow definition level using `@novu/framework`.
+
+```ts
+import { workflow } from "@novu/framework";
+
+workflow("welcome-notification", async (step) => {
+ await step.inApp("inbox", async () => ({
+ subject: "Welcome to Our Service!",
+ body: "We are thrilled to have you onboard.",
+ avatar: "https://example.com/path-to-your-avatar-image.png",
+ }));
+});
+```
+
+## Popover Positioning
+
+For advanced positioning and styling of the notifications popover, integrate third-party popover libraries such as Radix UI.
+
+- Old Implementation
+
+```tsx
+import {
+ PopoverNotificationCenter,
+ NotificationBell,
+ NovuProvider,
+} from "@novu/notification-center";
+
+function Novu() {
+ return (
+
+
+ {({ unseenCount }) => }
+
+
+ );
+}
+
+export default Novu;
+```
+
+- New Implementation with `@novu/react` and Radix UI as an example
+
+```tsx
+import React from "react";
+import * as RadixPopover from "@radix-ui/react-popover";
+import { Inbox, Bell, Notifications } from "@novu/react";
+
+function Novu() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default Novu;
+```
+
+## Custom Notification Item
+
+Customize the appearance and structure of individual notification items using the `renderNotification` prop.
+
+- Old Implementation
+
+```tsx
+import {
+ NovuProvider,
+ PopoverNotificationCenter,
+ NotificationBell,
+} from "@novu/notification-center";
+
+function Novu() {
+ return (
+
+ {
+ return (
+ {
+ e.preventDefault();
+ handleNotificationClick();
+ }}
+ >
+ {notification.content}
+
+ );
+ }}
+ >
+ {({ unseenCount }) => {
+ return ;
+ }}
+
+
+ );
+}
+
+export default Novu;
+```
+
+- New Implementation with `@novu/react`
+
+```tsx
+import { Inbox } from "@novu/react";
+
+function Novu() {
+ const renderCustomNotificationItem = (notification) => (
+
notification.read()}
+ >
+
+
+
{notification.subject}
+
{notification.body}
+
+
+ );
+
+ return (
+
+ );
+}
+
+export default Novu;
+```
+
+## Styling with appearance Prop
+
+Customize the overall look and feel of the notification components using the appearance prop, which supports both CSS objects and class names (including Tailwind CSS classes).
+
+- Old Implementation
+
+```tsx
+import {
+ NovuProvider,
+ PopoverNotificationCenter,
+ NotificationBell,
+} from "@novu/notification-center";
+
+function Novu() {
+ return (
+
+
+ {({ unseenCount }) => }
+
+
+ );
+}
+
+export default Novu;
+```
+
+- New Implementation with `@novu/react`
+
+```tsx
+import { Inbox } from "@novu/react";
+
+function Novu() {
+ return (
+
+ );
+}
+
+export default Novu;
+```
+
+For more information on `appearance` customization visit [here](/inbox/react/styling).
+
+## Multiple Tabs Support
+
+Organize notifications into different categories using tabs by leveraging the tags property in workflow definitions and the tabs prop in the Inbox component.
+
+### Create Multiple Tabs
+
+- Old Implementation
+
+After defining the feeds on the workflow UI, you were able to filter notifications based on the feedIdentifier.
+
+```tsx
+import {
+ NovuProvider,
+ PopoverNotificationCenter,
+ NotificationBell,
+} from "@novu/notification-center";
+
+function Novu() {
+ return (
+
+
+ {({ unseenCount }) => {
+ return (
+
+ );
+ }}
+
+
+ );
+}
+
+export default Novu;
+```
+
+- New Implementation with `@novu/react`
+
+1. Define multiple workflows with relevant tags.
+
+```ts
+import { workflow } from "@novu/framework";
+
+workflow(
+ "security-alerts",
+ async (step) => {
+ await step.inApp("inbox", async () => ({
+ subject: "Security Alert",
+ body: "A new login attempt was detected.",
+ }));
+ },
+ { tags: ["security"] }
+);
+
+workflow(
+ "promotional-offers",
+ async (step) => {
+ await step.inApp("inbox", async () => ({
+ subject: "Exclusive Offer!",
+ body: "Get 50% off on your next purchase.",
+ }));
+ },
+ { tags: ["promotions"] }
+);
+```
+
+2. Assign relevant tags to each workflow to categorize notifications appropriately.
+
+```tsx
+import { Inbox } from "@novu/react";
+
+const tabs = [
+ { label: "All Notifications", value: [] },
+ { label: "Security", value: ["security"] },
+ { label: "Promotions", value: ["promotions"] },
+];
+
+function Novu() {
+ return (
+
+ );
+}
+
+export default Novu;
+```
+
+## Localization
+
+Customize the language and text content of the notification components using the localization prop.
+
+```tsx
+import { Inbox } from "@novu/react";
+
+function Novu() {
+ return (
+
+ );
+}
+
+export default Novu;
+```
+
+## HMAC Encryption
+
+The process remains the same as before. See the detailed guide [here](/inbox/react/production#hmac-encryption).
+
+## Handling Notifications
+
+Handle notifications using the methods provided by the notification object.
+
+### Marking Notifications as Read
+
+Mark notifications as read using the `read` method provided by the notification object.
+
+```tsx
+import { Inbox } from "@novu/react";
+
+function Novu() {
+ const handleNotificationClick = (notification) => {
+ notification.read();
+ };
+
+ return (
+
+ );
+}
+
+export default Novu;
+```
+
+### Marking Notifications as Unread
+
+Mark notifications as unread using the `unread` method provided by the notification object.
+
+```tsx
+import { Inbox } from "@novu/react";
+
+function Novu() {
+ const handleNotificationClick = (notification) => {
+ notification.unread();
+ };
+
+ return (
+
+ );
+}
+
+export default Novu;
+```
+
+### Marking Notifications as Archive
+
+Mark notifications as archive using the `archive` method provided by the notification object.
+
+```tsx
+import { Inbox } from "@novu/react";
+
+function Novu() {
+ const handleNotificationClick = (notification) => {
+ notification.archive();
+ };
+
+ return (
+
+ );
+}
+
+export default Novu;
+```
+
+### Marking Notifications as Unarchive
+
+Mark notifications as unarchive using the `unarchive` method provided by the notification object.
+
+```tsx
+import { Inbox } from "@novu/react";
+
+function Novu() {
+ const handleNotificationClick = (notification) => {
+ notification.unarchive();
+ };
+
+ return (
+
+ );
+}
+
+export default Novu;
+```
diff --git a/inbox/react/multiple-tabs.mdx b/inbox/react/multiple-tabs.mdx
new file mode 100644
index 000000000..0b0c156fb
--- /dev/null
+++ b/inbox/react/multiple-tabs.mdx
@@ -0,0 +1,54 @@
+---
+title: 'Configuring Multiple Tabs'
+sidebarTitle: 'Tabs'
+---
+
+Novu enables the creation of a multi-tab experience for the Inbox, allowing you to filter and display notification lists within distinct UI tabs.
+
+## Defining tabs
+
+Define the `tabs` prop to display multiple tabs in the Inbox component.
+
+Each tab object should include a `label` and `filter` properties. The `label` property represents the text displayed on the specific tab. The `filter` property is an object that serves as the "filter criteria" for the notifications displayed in the list. The filter should include the `tags` which is an array of strings.
+
+The notifications are filtered and matched by comparing the [workflow](/workflow/overview#tags) `tags` field with the tab `filter.tags` array. Each notification is a part of a specific [workflow](/concepts/workflows). You can combine tags from different workflows to create a customized tab experience.
+
+The example below demonstrates how to define multiple tabs in the Inbox component.
+
+```tsx
+import { Inbox } from '@novu/react';
+
+const tabs = [
+ {
+ label: 'All Notifications',
+ filter: { tags: [] },
+ },
+ {
+ label: 'Newsletter',
+ filter: { tags: ['newsletter'] },
+ },
+ {
+ label: 'React',
+ filter: { tags: ['react'] },
+ },
+];
+
+function InboxNovu() {
+ return (
+
+ );
+}
+```
+
+
+
+
+
+
+ Here tab `filter.tags` are taken from workflow tags. Tags can be configured in
+ options field of [workflow](/framework/typescript/workflow).
+
diff --git a/inbox/react/preference.mdx b/inbox/react/preference.mdx
new file mode 100644
index 000000000..f3a809be8
--- /dev/null
+++ b/inbox/react/preference.mdx
@@ -0,0 +1,22 @@
+---
+title: 'Managing Subscriber Preferences in React'
+sidebarTitle: 'Preference'
+description: 'Learn how to manage and customize subscriber notification preferences in your React application.'
+---
+
+By default, Novu will show the subscriber preferences cog icon on the Inbox component.
+
+Users can enable/disable any active channel in the workflow using subscriber preferences or they can update the preference globally for all workflows under the `Global Preferences`.
+
+
+
+### Hide global preferences
+Global preferences can be hidden by using following css style in root css file.
+```css
+.nv-workflowContainer:first-child {
+ display: none;
+}
+```
diff --git a/inbox/react/production.mdx b/inbox/react/production.mdx
new file mode 100644
index 000000000..817b9043f
--- /dev/null
+++ b/inbox/react/production.mdx
@@ -0,0 +1,47 @@
+---
+title: 'Production Setup for React'
+sidebarTitle: 'Going to production'
+description: 'Learn how to prepare your React notification inbox for production deployment including HMAC encryption and security best practices.'
+---
+
+
+## HMAC Encryption
+
+When Novu's user adds the Inbox to their application they are required to pass a `subscriberId` which identifies the user's end-customer, and the application Identifier which is acted as a public key to communicate with the notification feed API.
+
+A malicious actor can access the user feed by accessing the API and passing another `subscriberId` using the public application identifier.
+
+HMAC encryption will make sure that a `subscriberId` is encrypted using the secret API key, and those will prevent malicious actors from impersonating users.
+
+### Enabling HMAC Encryption
+
+In order to enable Hash-Based Message Authentication Codes, you need to visit the admin panel In-App settings page and enable HMAC encryption for your environment.
+
+
+
+
+
+1. Next step would be to generate an HMAC encrypted subscriberId on your backend:
+
+```tsx
+import { createHmac } from 'crypto';
+
+const hmacHash = createHmac('sha256', process.env.NOVU_SECRET_KEY)
+ .update(subscriberId)
+ .digest('hex');
+```
+
+2. Then pass the created HMAC to your client side application forward it to the component:
+
+```tsx
+
+```
+
+
+ If HMAC encryption is active in In-App provider settings and `subscriberHash`
+ along with `subscriberId` is not provided, then Inbox will not load
+
diff --git a/inbox/react/styling.mdx b/inbox/react/styling.mdx
new file mode 100644
index 000000000..665c15eb9
--- /dev/null
+++ b/inbox/react/styling.mdx
@@ -0,0 +1,308 @@
+---
+title: "Styling the Inbox component"
+sidebarTitle: "Styling"
+description: "Learn how to style the pre built Inbox component"
+---
+
+## Customization Hierarchy
+
+The Inbox component is built to allow for multiple layers of styling, which allows the specificity required to style the Inbox to meet the requirements of your use case.
+
+Depending on the level of customization you need, you can choose to style the inbox using one of the following approaches:
+
+- [Appearance Prop](#appearance-prop)
+ - [Variables](#variables) - Global primitives such as buttons, popovers, dropdowns and etc...
+ - [Elements](#elements) - Style individual elements
+- [Custom notification rendering](#render-notification-component) - Render a custom notification item with complete control
+- [Custom Composition](/inbox/react/components/overview#composition) - Compose our components for custom layouts
+
+You can see Styling in action on the [Inbox Playground](https://inbox.novu.co) with common themes like Notion, Reddit and more!.
+
+## Appearance Prop
+
+The `appearance` prop can be used to customise the Inbox. It has three main keys: `baseTheme`, `variables` and `elements`.
+
+- **Variables**: Global styling variables that apply to multiple elements within the inbox.
+- **Elements**: Elements are the individual UI components that make up the Inbox.
+- **Base theme**: This is the base theme applied to the ``. It has the same keys as `appearance`. Used for applying base themes like `dark`.
+
+### Variables
+
+Variables are used to define global styling properties that can be reused throughout the inbox.
+You might want to use variables to the styling of multiple components at once, for example, if you want to change the border radius of all the components at once, you can do so by updating the `colorPrimary` variable, which will modify the CTA buttons, unseen counter and etc...
+
+
+
+
+ The background color of the inbox component.
+
+
+
+ The primary text color used in the inbox.
+
+
+
+ The main accent color for interactive elements.
+
+
+
+ The text color used on primary-colored elements.
+
+
+
+ A secondary color for less prominent elements.
+
+
+
+ The text color used on secondary-colored elements.
+
+
+
+ The background color of notification counters.
+
+
+
+ The text color used in notification counters.
+
+
+
+ A neutral color used for borders or backgrounds.
+
+
+
+ The color of shadows applied to elements.
+
+
+
+ The base font size for text in the inbox.
+
+
+
+ The border radius applied to various elements.
+
+
+
+
+
+
+
+
+
+#### Styling Variables
+
+You can override the default elements by passing your own styles or CSS classes to the `elements` object.
+
+```tsx
+const appearance = {
+ variables: {
+ colorBackground: "yellow",
+ },
+};
+
+;
+```
+
+### Elements
+
+The `elements` object allows you to define styles for these components. Each key corresponds to an component, and the value is an object containing `style properties` or you can also pass your `css classes`.
+Here's a list of available elements that can be styled using the `elements` object in your appearance configuration:
+
+#### Finding element selectors
+
+You can inspect the elements you want to customize using the browser's dev tools, each element has a unique selector that you can use to style starting with `nv-`.
+
+Strip the `nv-` prefix when and add it to the `elements` object. For example, to style the `nv-notificationPrimaryAction__button` element, you can add the following to the `elements` object:
+
+```tsx
+const appearance = {
+ elements: {
+ notificationPrimaryAction__button: {
+ backgroundColor: "red",
+ },
+ },
+};
+```
+
+
+
+
+
+
+ Any selector that appears before the đ emoji, can be targeted via the
+ elements property in Appearance prop (stripping the `nv-` prefix). You can
+ also use TS autocomplete to find the available elements.
+
+
+### Dark theme
+
+No need to implement a custom dark theme. Just import our premade `dark` theme and use it via the `baseTheme` option in `appearance`.
+
+```tsx
+import { Inbox } from "@novu/react";
+import { dark } from "@novu/react/themes";
+import { useTheme } from "next-themes";
+
+export function Novu() {
+ const { resolvedTheme } = useTheme();
+
+ return (
+
+ );
+}
+```
+
+### Bring your own CSS
+
+You can override the default elements by passing your own styles or CSS classes to the `elements` object.
+
+#### Using Tailwind CSS
+
+You can also use Tailwind CSS classes to style the Inbox components. You can pass the classes
+directly to the `elements` object.
+
+```tsx
+import { Inbox } from "@novu/react";
+
+const appearance = {
+ elements: {
+ bellIcon: "p-4 bg-white rounded-full",
+ notification:
+ "bg-white rounded-lg shadow-sm hover:shadow-md hover:bg-gray-50",
+ },
+};
+
+export function Novu() {
+ return (
+
+ );
+}
+```
+
+#### Using CSS Modules
+
+You can also use `CSS Modules` to style the Inbox components. Here's how you can do it:
+
+- Create a CSS module file `(e.g. styles.module.css)` with the styles you want to apply to the Inbox components.
+
+```css
+.bellIcon {
+ padding: 1rem;
+ background-color: white;
+ border-radius: 50%;
+}
+
+.bellIcon:hover {
+ background-color: #f9fafb;
+}
+
+.notification {
+ background-color: white;
+ border-radius: 0.5rem;
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
+}
+
+.notification:hover {
+ background-color: #f9fafb;
+}
+```
+
+- Import the CSS module file and pass the classes to the elements object.
+
+```tsx
+import { Inbox } from "@novu/react";
+import styles from "./styles.module.css";
+
+const appearance = {
+ elements: {
+ bellIcon: styles.bellIcon,
+ notification: styles.notification,
+ },
+};
+
+export function Novu() {
+ return (
+
+ );
+}
+```
+
+#### Using Styles Object
+
+You can also use a styles object to style the Inbox components. You can pass the styles
+directly to the `elements` object.
+
+```tsx
+import { Inbox } from "@novu/react";
+
+const appearance = {
+ elements: {
+ bellIcon: {
+ padding: "1rem",
+ backgroundColor: "white",
+ borderRadius: "50%",
+ },
+ notification: {
+ backgroundColor: "white",
+ borderRadius: "0.5rem",
+ boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
+ },
+ },
+};
+
+export function Novu() {
+ return (
+
+ );
+}
+```
+
+#### Render subject and body with bold text
+
+By default, the Inbox notification text for the subject and body is rendered in a normal font weight.
+To highlight important words or phrases within your notification messages, you can wrap the desired subject or body text in double asterisks (\*\*).
+Hereâs an example of how you can do this using the Novu Framework:
+
+```js
+await step.inApp("inbox", async () => {
+ return {
+ subject: "**A new member joined the team!**",
+ body: "**John Doe** joined the team! Say hello and help them feel at home",
+ };
+});
+```
+
+
+ Please note, that when you are rendering the custom notification component you
+ will need to parse the text and apply the bold styling accordingly.
+
+
+Currently we only support bold text. We are working on adding more text formatting options in the future.
+You can learn more about the Novu Framework in-app step [here](/framework/typescript/steps/inApp).
+
+## Render Notification Component
+
+You can render your own custom notification item component by passing a `renderNotification` prop to the `Inbox` or `Notifications` component, this will allow you to style and render more complex notification items.
+
+```tsx
+ {
+ return ;
+ }}
+/>
+```
diff --git a/integrations/overview.mdx b/integrations/overview.mdx
new file mode 100644
index 000000000..c1b0f258a
--- /dev/null
+++ b/integrations/overview.mdx
@@ -0,0 +1,49 @@
+---
+title: "Novu Integration Hub"
+sidebarTitle: "Overview"
+description: "Discover how to integrate Novu with your tech stack including delivery providers, content frameworks, and validation libraries."
+---
+
+Novu was designed to be integrated with any part of your tech stack. This includes:
+
+- Delivery providers
+- Content frameworks
+- Validation and schema libraries
+- and more!
+
+## Delivery provider integrations
+
+You can find the list of available integrations for each channel:
+
+
+
+ Configure email providers and settings
+
+
+ Set up SMS messaging capabilities
+
+
+ Enable push notification delivery
+
+
+ Integrate with chat platforms
+
+
+ Manage in-app notification center
+
+
+
+## Framework integrations
+
+Those integrations are available for the [Novu Framework SDK](/framework/typescript/overview), and can be used to build custom notification workflows with your own runtime logic.
+
+
+
+
+
+ Use any content framework to build your notification content
+
+
+ Validate your notification logic with JSON schema
+
+
diff --git a/integrations/providers/chat/adding-chat.mdx b/integrations/providers/chat/adding-chat.mdx
new file mode 100644
index 000000000..74522d288
--- /dev/null
+++ b/integrations/providers/chat/adding-chat.mdx
@@ -0,0 +1,140 @@
+---
+title: "Adding Chat Channel"
+sidebarTitle: "Adding Chat Channel"
+description: "Learn how to add the Chat channel to your application"
+icon: "circle-plus"
+---
+
+import { MissingProvider } from "/snippets/missing-provider.mdx";
+
+Chat channels allow you to deliver instant, contextual messages to your subscribers via their preferred chat platform and apps.
+
+
+
+
+
+The Chat channel is not enabled by default. To use it, configure a provider like Slack, Discord, or others.
+
+
+1. Go to the Novu Dashboard and click **"Integrations"** on the left sidebar
+2. Click **"Add a provider"**
+3. Locate the **Chat** channel and select the provider you want to use and click **"Next"**
+4. Select for which environment you want to add the Provider
+5. (Optional) Add Conditions to activate the provider only under certain conditions, **useful for tenant-based providers**
+6. Click **"Create"**
+7. Add your Chat provider credentials:
+ Each chat provider requires defferent type of credentials. There are few providers which does not require any credentials example: `Discord`
+ - Provider-specific credentials such as API key / Auth token, Client ID, Client Secret, or password
+8. Save the configuration by clicking **"Update"**
+
+
+
+
+
+
+ 1. Go to the Novu Dashboard and click **"Workflows"** on the left sidebar.
+ 2. Click the **"Add a Workflow"** button.
+ 3. Add a step and select **"Chat"** as the channel.
+ 4. Configure the Chat content:
+ - Message body (e.g., `{{subscriber.firstName}}, your order {{orderId}} has shipped.`).
+ - Dynamic placeholders for personalized content.
+ 5. Optionally, set fallback channels to ensure reliable delivery if Chat fails.
+
+
+
+
+
+Novuâs server-side SDKs make integrating Novuâs REST APIs straightforward, letting you focus on implementing workflows without dealing with repetitive code.
+
+
+
+
+
+
+Ensure your Chat configuration is working correctly by testing the setup.
+
+1. Go to the Novu Dashboard, navigate to the **"Workflows"** section, and locate your configured workflow.
+2. Click **"Test Workflow"** and provide sample data, such as a phone number or dynamic variables.
+3. Verify delivery in the Novu Logs or your Chat providerâs dashboard.
+
+
+
+
+
+
+## Sending chat message
+
+Steps to send a chat message using Novu:-
+
+1. Add a chat provider integration to your Novu account from the integration store. Enter credentials if required and save the integration. Follow corresponding provider documentation to get the required credentials.
+2. Create a new subscriber
+
+> Step 2 can be skipped if you already have a subscriber. You can use the `subscriberId` of an existing subscriber.
+
+3. [Update](/integrations/providers/chat/overview#update-credential-webhookurl) the subscriber credential `webhookUrl` for this provider and integration.
+
+4. Create a new [worklow](/workflow/overview) or use an existing workflow. Add chat channel and [write content](/content-creation-design/notification-content-creation#chat) for the message.
+
+5. Trigger this workflow to above `subscriberId` using trigger identifier
+
+6. Check the chat provider if message is received.
+
+## Update credential webhookUrl
+
+
+
+```javaScript
+import {
+ Novu,
+ ChatProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+await novu.subscribers.setCredentials('subscriberId', ChatProviderIdEnum.Slack, {
+webhookUrl: "",
+});
+
+```
+
+
+```bash
+curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+-d '{
+ "providerId": "slack",
+ "credentials": {
+ "webhookUrl": ""
+ },
+ "integrationIdentifier": "slack-MnGLxp8uy"
+}'
+```
+
+
+
+
+Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
+
+
+ {" "}
+ Integration identifier is similar to Provider identifier but it is different than
+ Provider Id. It is unique for each integration. You can find the `integrationIdentifier`
+ in the integration store page.{" "}
+
+
+## Common errors
+
+Common erros and reason of those errors while sending chat messages using Novu.
+
+1. Subscriber does not have a configured channel.
+ - if the subscriber does not have credentials set up for any of the chat provider.
+2. Webhook URL for the chat channel is missing.
+ - `webhookUrl` field is null, undefined or not set. Check using [get subscriber api](/api-reference/subscribers/get-subscriber).
+3. Subscriber does not have an active integration.
+ - if subscriber have credentials set but integration is either not active or deleted for this credential.
+
+
+
+
diff --git a/integrations/providers/chat/discord.mdx b/integrations/providers/chat/discord.mdx
new file mode 100644
index 000000000..ff4048cdd
--- /dev/null
+++ b/integrations/providers/chat/discord.mdx
@@ -0,0 +1,63 @@
+---
+title: "Discord"
+description: "Learn about how to use Discord provider for chat notifications"
+---
+
+When using Discord, you will have to store the integration credentials within the subscriber entity. Discord supports two ways to do this:
+
+1. Using the **Discord Webhook** integration.
+2. Using the **Discord Bot** integration.
+
+Right now, Novu only supports the **Discord Webhook** integration. This approach has been because the easiest way to set it up is when you have a predefined destination for where the notifications should be sent. It's particularly useful for notifying a specific channel about updates.
+
+**Quickstart:**
+
+To get started with using Novuâs Discord Webhook integration, you need a âwebhook tokenâ. Hereâs how you can generate the same for testing purposes:
+
+1. Go to the channel you want to add the webhook to (you need to be an admin of the discord server).
+2. Right-click the channel and select "Edit Channel".
+3. Integrations -> Webhooks -> New Webhook
+4. Copy the webhook URL.
+5. After obtaining the webhook URL in the previous step, you need to store it within the subscriber entity. Doing this ensures that Novu knows where (in which discord channel) to send the notification to. Hereâs how to do it:
+
+
+
+```javaScript
+import {
+ Novu,
+ ChatProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+await novu.subscribers.setCredentials('subscriberId', ChatProviderIdEnum.Discord, {
+webhookUrl: "",
+});
+
+```
+
+
+```bash
+curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+-d '{
+ "providerId": "discord",
+ "credentials": {
+ "webhookUrl": ""
+ },
+ "integrationIdentifier": "discord-MnGLxp8uy"
+}'
+```
+
+
+
+
+Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
+
+ - `subscriberId`Â is a custom identifier used when identifying your users within the Novu platform.
+ - `providerId`Â is a unique provider identifier. We recommend using our ChatProviderIdEnum to specify the provider.
+ - The third parameter is the credentials object. In this case, we use the `webhookUrl` property to specify the webhook URL generated in the previous step.
+
+6. You are all set up and ready to send your first chat message via our `@novu/node` package or directly using the REST API in the channel you chose on your discord server.
diff --git a/integrations/providers/chat/mattermost.mdx b/integrations/providers/chat/mattermost.mdx
new file mode 100644
index 000000000..bda96458c
--- /dev/null
+++ b/integrations/providers/chat/mattermost.mdx
@@ -0,0 +1,70 @@
+---
+title: "Mattermost"
+description: "Learn about how to use Mattermost provider for chat notifications"
+---
+
+When using Mattermost, you will have to store the integration credentials within the subscriber entity. Mattermost supports two ways to do this:
+
+1. Using the **Mattermost Webhook** integration.
+2. Using the **Mattermost Bot** integration.
+
+### Mattermost Webhook Integration
+
+To integrate Mattermost with your application using the Mattermost Webhook integration, follow these steps:
+
+1. Create an incoming webhook in Mattermost. This can be done by going to the **Integrations** page and clicking on the **Incoming Webhooks** tab.
+2. Click on the **Add Incoming Webhook** button and configure the webhook settings. Be sure to select the channel where you want to receive notifications.
+3. Click on the **Save** button to generate a webhook URL.
+
+Once you have the webhook URL, you can store it in the subscriber entity in your application. This will allow you to send notifications to Mattermost using the following code:
+
+```jsx
+import { Novu, ChatProviderIdEnum } from "@novu/node";
+
+const novu = new Novu("");
+
+await novu.subscribers.setCredentials(
+ "subscriberId",
+ ChatProviderIdEnum.Mattermost,
+ { webhookUrl: "" }
+);
+
+// Send a notification to Mattermost using the subscriber ID and payload.
+await novu.trigger("", {
+ to: {
+ subscriberId: "",
+ },
+ payload: {
+ message: "This is a notification from my application!",
+ },
+});
+```
+
+### Mattermost Bot Integration
+
+To integrate Mattermost with your application using the Mattermost Bot integration, you will need to create a Mattermost bot account and generate an API token for the bot. Once you have the API token, you can store it in the subscriber entity in your application.
+
+Once you have stored the API token in the subscriber entity, you can send notifications to Mattermost using the following code:
+
+```jsx
+import { Novu, ChatProviderIdEnum } from "@novu/node";
+
+const novu = new Novu("");
+
+// Get the Mattermost bot API token for the subscriber.
+await novu.subscribers.setCredentials(
+ "subscriberId",
+ ChatProviderIdEnum.Mattermost,
+ { botApiToken: "" }
+);
+
+// Send a notification to Mattermost using the bot API token.
+await novu.trigger("", {
+ to: {
+ subscriberId: "",
+ },
+ payload: {
+ message: "This is a notification from my application!",
+ },
+});
+```
diff --git a/integrations/providers/chat/ms-teams.mdx b/integrations/providers/chat/ms-teams.mdx
new file mode 100644
index 000000000..059a1eb47
--- /dev/null
+++ b/integrations/providers/chat/ms-teams.mdx
@@ -0,0 +1,70 @@
+---
+title: "MS Teams"
+description: "Learn about how to use MS Teams provider for chat notifications"
+---
+
+import ProviderImplementation from "/snippets/provider-implementation.mdx";
+
+MS Teams does not need any `API Key` or `Client ID` to send notifications. Our current implementation is based on the [Incoming Webhook URL](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook?tabs=newteams%2Cjavascript). It is a URL that you can use to send messages to a specific channel. This URL needs to be stored on the subscriber entity
+
+Similar to [Discord](https://www.notion.so/Additional-Resources-65ef4aca5d0f4115947030c2f5705101?pvs=21), the credential for this provider needs to be stored in the [subscriber entity](/api-reference/subscribers/update-subscriber-credentials).
+
+## Creating incoming webhook URL
+
+Checkout step by step instructions on microsoft team's documentation on how to [create an incoming webhook url](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook?tabs=newteams%2Cjavascript).
+
+
+ {" "}
+
+
+## Storing webhook url on subscriber entity
+
+The URL generated above will be the target channel of a subscriber that you want to integrate with. To make this connection, you have to:
+
+1. Copy the URL that you generated above
+2. Update the subscriber credentials with this URL using the MS Teams provider id. You can do this step by using the `@novu/node` library, as shown below:
+
+
+
+```javaScript
+import {
+ Novu,
+ ChatProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+await novu.subscribers.setCredentials(
+'subscriberId',
+ChatProviderIdEnum.MsTeams, // providerId
+{ webhookUrl: "" },
+'msteams-MnGLxp8uy' // integration identifier
+);
+
+```
+
+
+```bash
+curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+-d '{
+ "providerId": "msteams",
+ "credentials": {
+ "webhookUrl": ""
+ },
+ "integrationIdentifier": "msteams-MnGLxp8uy"
+}'
+```
+
+
+
+
+Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
+
+- `subscriberId`Â is a custom identifier used when identifying your users within the Novu platform.
+- `providerId`Â is a unique provider identifier. We recommend using our ChatProviderIdEnum to specify the provider.
+- The third parameter is the credentials object, in this case, we use the `webhookUrl` property to specify the MS Teams channel webhook URL or by calling the `Update Subscriber Credentials` endpoint on Novu API. Check endpoint details [here](/api-reference/subscribers/update-subscriber-preference).
+
+
diff --git a/integrations/providers/chat/overview.mdx b/integrations/providers/chat/overview.mdx
new file mode 100644
index 000000000..e636c21f3
--- /dev/null
+++ b/integrations/providers/chat/overview.mdx
@@ -0,0 +1,37 @@
+---
+title: "Chat Providers Integration"
+sidebarTitle: "Overview"
+description: "Learn how to configure and use chat providers like Slack, Microsoft Teams, WhatsApp, and Discord with Novu's notification infrastructure."
+icon: "circle-info"
+---
+
+Novu brings chat notifications into your development workflow, giving you a unified way to manage messaging across platforms and apps. Whether you're working with tools like Slack or Microsoft Teams or apps like WhatsApp, Telegram, and Discord, Novu lets you integrate, manage, and scale chat notifications without unnecessary complexity.
+
+The Chat channel provides:
+
+- **Cross-Platform Integration**: A single system to handle messaging platforms (e.g., Slack, Teams) and apps (e.g., WhatsApp, Telegram, Discord)
+- **Scalability at Its Core**: Designed to handle high-frequency messaging without breaking a sweat
+- **Effortless Configuration**: Minimal setup, maximum control over your chat notification workflows
+
+## Key Features
+
+- **Platform and App Agnostic**: Supports workplace messaging platforms (Slack, Teams) and consumer apps (Discord, WhatsApp, Telegram) without additional overhead
+- **Dynamic Content Handling**: Inject real-time, user-specific data into messages with simple APIs
+- **Provider Independence**: Easily switch between chat providers or use multiple simultaneously
+- **Delivery Monitoring**: Full visibility into delivery status, failures, and message engagement
+- **Fallback Logic**: Automate retries and backup providers to ensure messages are delivered
+- **Reusable Message Templates**: Standardize message structure across your channels
+- **Developer-Centric APIs**: Clean, intuitive endpoints to plug notifications directly into your backend
+
+## Messaging Platforms vs. Messaging Apps
+
+- **Messaging Platforms** (e.g., Slack, Teams): Ideal for structured, workplace communication. Use these to notify teams or users in collaborative environments
+- **Messaging Apps** (e.g., WhatsApp, Telegram, Discord): Best for consumer-facing messaging. Engage users directly through personal or group chats
+
+## Common Use Cases
+
+- **Team Notifications**: Deliver updates to Slack channels or Teams users without needing complex integrations
+- **Customer Engagement**: Notify users on apps like Telegram or WhatsApp with real-time updates or alerts
+- **System Alerts**: Push critical system or workflow notifications to technical teams via chat platforms
+- **Event Reminders**: Send timely reminders for meetings, webinars, or deadlines
+- **Community Notifications**: Manage announcements, updates, or discussions in platforms like Discord
diff --git a/integrations/providers/chat/slack.mdx b/integrations/providers/chat/slack.mdx
new file mode 100644
index 000000000..2236df1a6
--- /dev/null
+++ b/integrations/providers/chat/slack.mdx
@@ -0,0 +1,141 @@
+---
+title: "Slack"
+description: "Learn about how to use Slack provider for chat notifications"
+---
+
+When using Slack you will have to save the integration credentials in the subscriber entity.
+
+This guide will walk you through the steps needed to obtain the `webhookUrl` that Novu requires to send chat messages to your customers.
+
+We will provide the basic flow that the user needs to perform, to successfully send notifications via the Slack integration.
+
+## Creating application
+
+This step is optional, if you already have a Slack application you can reuse it.
+
+1. Go to Slack's developer dashboard https://api.slack.com/apps.
+2. Create a new application.
+
+## Integrating Novu with Slack
+
+### Manually managed
+
+To use the manually managed option, you need to generate a `webhookUrl` and plug it into your backend.
+
+1. Goto 'Incoming Webhooks' in your Slack app settings and turn it on.
+
+ {" "}
+
+2. Click on the 'Add New Webhook to Workspace':
+
+ {" "}
+
+3. Now, go ahead and select the channel in which you want to send notifications and click 'allow'.
+
+ {" "}
+
+4. Then, copy the 'webhookUrl' from Slack.
+
+ {" "}
+
+5. Now, you need to save the `webhookUrl` on the relevant subscriber entity in Novu. Here's an example to do the same using our Node SDK:
+
+## Writing Slack content (Blocks API)
+
+Novu Framework supports using [blocks](https://api.slack.com/block-kit) as part of the delivered messages using the provider overrides of the `chat` channel:
+
+You can use the [Blocks Playground](https://app.slack.com/block-kit-builder/T02QYEPHZMM#%7B%22blocks%22:%5B%7B%22type%22:%22section%22,%22text%22:%7B%22type%22:%22mrkdwn%22,%22text%22:%22Hello,%20Assistant%20to%20the%20Regional%20Manager%20Dwight!%20*Michael%20Scott*%20wants%20to%20know%20where%20you'd%20like%20to%20take%20the%20Paper%20Company%20investors%20to%20dinner%20tonight.%5Cn%5Cn%20*Please%20select%20a%20restaurant:*%22%7D%7D,%7B%22type%22:%22divider%22%7D,%7B%22type%22:%22section%22,%22text%22:%7B%22type%22:%22mrkdwn%22,%22text%22:%22*Farmhouse%20Thai%20Cuisine*%5Cn:star::star::star::star:%201528%20reviews%5Cn%20They%20do%20have%20some%20vegan%20options,%20like%20the%20roti%20and%20curry,%20plus%20they%20have%20a%20ton%20of%20salad%20stuff%20and%20noodles%20can%20be%20ordered%20without%20meat!!%20They%20have%20something%20for%20everyone%20here%22%7D,%22accessory%22:%7B%22type%22:%22image%22,%22image_url%22:%22https://s3-media3.fl.yelpcdn.com/bphoto/c7ed05m9lC2EmA3Aruue7A/o.jpg%22,%22alt_text%22:%22alt%20text%20for%20image%22%7D%7D,%7B%22type%22:%22section%22,%22text%22:%7B%22type%22:%22mrkdwn%22,%22text%22:%22*Kin%20Khao*%5Cn:star::star::star::star:%201638%20reviews%5Cn%20The%20sticky%20rice%20also%20goes%20wonderfully%20with%20the%20caramelized%20pork%20belly,%20which%20is%20absolutely%20melt-in-your-mouth%20and%20so%20soft.%22%7D,%22accessory%22:%7B%22type%22:%22image%22,%22image_url%22:%22https://s3-media2.fl.yelpcdn.com/bphoto/korel-1YjNtFtJlMTaC26A/o.jpg%22,%22alt_text%22:%22alt%20text%20for%20image%22%7D%7D,%7B%22type%22:%22section%22,%22text%22:%7B%22type%22:%22mrkdwn%22,%22text%22:%22*Ler%20Ros*%5Cn:star::star::star::star:%202082%20reviews%5Cn%20I%20would%20really%20recommend%20the%20%20Yum%20Koh%20Moo%20Yang%20-%20Spicy%20lime%20dressing%20and%20roasted%20quick%20marinated%20pork%20shoulder,%20basil%20leaves,%20chili%20&%20rice%20powder.%22%7D,%22accessory%22:%7B%22type%22:%22image%22,%22image_url%22:%22https://s3-media2.fl.yelpcdn.com/bphoto/DawwNigKJ2ckPeDeDM7jAg/o.jpg%22,%22alt_text%22:%22alt%20text%20for%20image%22%7D%7D,%7B%22type%22:%22divider%22%7D,%7B%22type%22:%22actions%22,%22elements%22:%5B%7B%22type%22:%22button%22,%22text%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Farmhouse%22,%22emoji%22:true%7D,%22value%22:%22click_me_123%22%7D,%7B%22type%22:%22button%22,%22text%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Kin%20Khao%22,%22emoji%22:true%7D,%22value%22:%22click_me_123%22,%22url%22:%22https://google.com%22%7D,%7B%22type%22:%22button%22,%22text%22:%7B%22type%22:%22plain_text%22,%22text%22:%22Ler%20Ros%22,%22emoji%22:true%7D,%22value%22:%22click_me_123%22,%22url%22:%22https://google.com%22%7D%5D%7D%5D%7D) from Slack to learn more about the diffrent blocks available.
+
+```typescript
+await step.chat('send-chat', async () => {
+ return {
+ // This will be used as a fallback for the chat provider if other than Slack provider is used
+ body: 'A new post has been created',
+ };
+}, {
+ providers: {
+ slack: async ({ inputs }) => ({
+ text: 'A new post has been created',
+ blocks: [
+ {
+ type: 'section',
+ text: {
+ type: 'mrkdwn',
+ text: 'A new post has been created',
+ },
+ },
+ ],
+ }),
+ }
+});
+```
+
+
+## Update credential webhookUrl
+
+
+
+```javaScript
+import {
+ Novu,
+ ChatProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+await novu.subscribers.setCredentials('subscriberId', ChatProviderIdEnum.Slack, {
+ webhookUrl: "",
+});
+
+```
+
+
+```bash
+curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+-d '{
+ "providerId": "slack",
+ "credentials": {
+ "webhookUrl": ""
+ },
+ "integrationIdentifier": "slack-MnGLxp8uy"
+}'
+```
+
+
+
+Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
+
+- `subscriberId` is a custom identifier used when identifying your users within the Novu platform.
+- `providerId` is a unique provider identifier. We recommend using our ChatProviderIdEnum.Slack if youâre using Node, else string of Slack to specify the provider.
+- The third parameter is the credentials object. In this case, we use the `webhookUrl` property to specify the webhook URL generated in the previous step.
+
+6. You are all set up and ready to send your first chat message via our @novu/node package or directly using the REST API.
+
+## Configuring Slack application
+
+1. Go to OAuth & Permissions on Slack's Developer Dashboard and add your REDIRECT_URL in Redirect URLs.
+ - If you use a manual Management solution, add the API endpoint you created in Step 1.
+2. Go to Incoming Webhooks from the left menu and Activate Incoming Webhooks.
+3. Go to Manage Distribution and at the bottom of the page, tick Remove Hard Coded Information and Activate Public Distribution.
+
+### Enabling HMAC Encryption
+
+To enable Hash-Based Message Authentication Codes, you need to do the following steps:
+
+1. Visit the integration store page and enable HMAC encryption under your chat provider.
+2. The next step would be to generate an HMAC encrypted subscriberId on your backend:
+
+ ```jsx
+ import { createHmac } from "crypto";
+
+ const hmacHash = createHmac("sha256", process.env.NOVU_SECRET_KEY)
+ .update(subscriberId)
+ .digest("hex");
+ ```
+
+3. Add the newly created hash HMAC to the Sharable URL as a query.
+
+This concludes the Slack provider guide.
diff --git a/integrations/providers/chat/whats-app.mdx b/integrations/providers/chat/whats-app.mdx
new file mode 100644
index 000000000..542c62d7b
--- /dev/null
+++ b/integrations/providers/chat/whats-app.mdx
@@ -0,0 +1,108 @@
+---
+title: "How to send WhatsApp Business notifications with Novu"
+sidebarTitle: "WhatsApp Business"
+description: "Learn about how to use WhatsApp for chat notifications"
+---
+
+## Getting Started
+
+To integrate WhatsApp Business with Novu, You will have to create a facebook developer app and obtain the necessary credentials.
+
+### Step 1: Create a Facebook developer app
+
+Visit the [Facebook Developer Portal](https://developers.facebook.com/apps/) and create a new app.
+
+Select "Other" for "What do you want your app to do?" and select "Business" for "Select an app type".
+
+### Step 2: Setup WhatsApp product
+
+On the App Setup page, click on "Set Up" under the "WhatsApp" product. You will need to create or add a Facebook Business Account to your app.
+
+### Step 3: Send a sandbox message
+
+Copy the following pieces and paste them in the Novu WhatsApp Business integration settings:
+
+- Temporary access token - Access API token field
+- Phone Number ID - Phone number identification field
+
+
+ It's important to note that the test credentials for whatsapp cannot be used
+ in production and will expire in 24 hours. You will need to submit your app
+ for review to obtain production credentials.
+
+
+### Step 4: Add a test phone number
+
+You can add a test phone number to the sandbox by clicking on the **"Add Phone Number"** button.
+This number can be used to test your integration with Novu before submitting for a review.
+
+### Step 5: Send a test notification from Novu
+
+You can now create a new workflow with a "chat" node, and add your content. Save your workflow, and click on **"Trigger Notification"** button.
+
+In the to field, specify the phone number you added in the sandbox, and click on "Send Notification".
+
+```json
+{
+ "subscriberId": "TEST_SUBSCRIBER_ID",
+ "phone": "+11111111111"
+}
+```
+
+and in the `overrides` field, add the following:
+
+```json
+{
+ "chat": {
+ "template": {
+ "name": "hello_world",
+ "language": {
+ "code": "en_US"
+ }
+ }
+ }
+}
+```
+
+
+ For test credentials you can only used the built in Whats App Template.
+
+
+## Going to production
+
+### Register a business phone number
+
+To go live you will need to add a real business phone number and submit your app for review.
+Follow the [Facebook Instructions](https://developers.facebook.com/docs/whatsapp/cloud-api/get-started/add-a-phone-number) on how to proceed.
+
+### Generate a permanent access token
+
+Follow the [Facebook Instructions](https://developers.facebook.com/docs/whatsapp/business-management-api/get-started/) on how to generate a permanent access token.
+Depending on your use case.
+
+### Create a WhatsApp template
+
+You will need to create a WhatsApp Template to send notifications to your customers. Create a template in the [Business Manager](https://business.facebook.com/wa/manage/message-templates) and submit it for review.
+After your template is approved, you can use the `template_name` to send notifications to your customers.
+
+To send a notification with a template, you will need to add the following to the `overrides` field:
+
+```typescript
+novu.trigger("workflow-id", {
+ to: {
+ subscriberId: "SUBSCRIBER_ID",
+ phone: "+11111111111",
+ },
+ payload: {},
+ overrides: {
+ chat: {
+ template: {
+ name: "template_name",
+ language: {
+ code: "en_US",
+ },
+ },
+ },
+ },
+});
+```
diff --git a/integrations/providers/chat/zulip.mdx b/integrations/providers/chat/zulip.mdx
new file mode 100644
index 000000000..ed9fae29f
--- /dev/null
+++ b/integrations/providers/chat/zulip.mdx
@@ -0,0 +1,86 @@
+---
+title: "Zulip"
+description: "Learn about how to use Zulip provider for chat notifications"
+---
+
+Zulip does not need any API Key or client ID to push messages in it. All it needs is the webhook URL of the channel you want to send messages to. That itself acts as the credential.
+
+Similar to Discord, the credential for this provider needs to be stored in the subscriber entity.
+
+## Getting a Zulip webhook URL
+
+- Sign up or Login to your Zulip account.
+
+- Click on the Settings icon in the top right corner of the screen, and then click "Personal settings" from the drop-down menu.
+
+
+
+
+
+- Click "Add a new bot" button in "Bots" tab.
+
+
+ {" "}
+
+
+- Set bot type as "Incoming webhook".
+
+
+ {" "}
+
+
+- Click the small link icon to generate webhook URL for provider. Set Integration as `Slack compatible webhook`, choose your channel and copy webhook URL.
+
+
+ {" "}
+
+
+## Connecting our subscribers to Zulip
+
+The URL generated above will be the target channel of a subscriber that you want to integrate with. To make this connection, you have to:
+
+1. Copy the URL that you generated above
+
+2. Update the subscriber credentials with this URL using the Zulip provider id. You can do this step by using the `@novu/node` library, as shown below:
+
+## Update credential webhookUrl
+
+
+
+```javaScript
+import {
+ Novu,
+ ChatProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+await novu.subscribers.setCredentials('subscriberId', ChatProviderIdEnum.Zulip, {
+webhookUrl: "",
+});
+
+```
+
+
+```bash
+curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+-d '{
+ "providerId": "zulip",
+ "credentials": {
+ "webhookUrl": ""
+ },
+ "integrationIdentifier": "zulip-MnGLxp8uy"
+}'
+```
+
+
+
+
+- `subscriberId` is a custom identifier used when identifying your users within the Novu platform.
+- `providerId` is a unique provider identifier. We recommend using our ChatProviderIdEnum to specify the provider.
+- The third parameter is the credentials object, in this case, we use the `webhookUrl` property to specify the MS Teams channel webhook URL or by calling the `Update Subscriber Credentials` endpoint on Novu API. Check endpoint details [here](/api-reference/subscribers/update-subscriber-preference).
+
+3. You are all set up and ready to send your first chat message via our `@novu/node` package or directly using the REST API.
diff --git a/integrations/providers/default-providers.mdx b/integrations/providers/default-providers.mdx
new file mode 100644
index 000000000..dacc0e18a
--- /dev/null
+++ b/integrations/providers/default-providers.mdx
@@ -0,0 +1,55 @@
+---
+title: "Novu Providers"
+description: "Learn about the default Novu email and sms providers"
+---
+
+import CloudOnlyFeature from "/snippets/cloud-only-feature.mdx";
+
+## Novu Providers
+
+To help you evaluate our services better, Novu provides an email and sms provider by default for every account. After signing up, you can go to the [Integrations store](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-default-providers) on the Novu web dashboard to see this.
+
+
+
+## Novu Email Provider
+
+If you've a newly signed-up account on Novu, it will look like this:
+
+
+ {" "}
+
+
+## Novu SMS Provider
+
+And this is what the default Novu SMS provider looks like:
+
+
+ {" "}
+
+
+
+ The default email and sms providers are for evaluation purposes only and their
+ use in production-grade apps is not recommended. You should switch to any of
+ our [numerous other providers](/additional-resources/glossary#3-providers) for
+ production apps. Also, there are two modes for default Novu providers -
+ Development and Production.
+
+
+## Novu In-app Provider
+
+In addition to email and sms, we also have in-app provider:
+
+
+ {" "}
+
+
+It is the only provider for the in-app channel and it _can be used in production apps_. Unlike sms and email, it is not active by default and needs to be turned on separately. It can be scaled as per your need and it is a 'pay as you go' offering. You can check [this](https://novu.co/pricing/?utm_campaign=docs-default-providers) for more details.
+
+## Limits of the Novu Providers
+
+Following are the limits for our email and sms providers:
+
+1. Email: 300 emails per organization per month
+2. SMS: 20 messages per organization per month
+
+To send more than these limits, you can configure a different provider for a specific channel.
diff --git a/integrations/providers/email/adding-email.mdx b/integrations/providers/email/adding-email.mdx
new file mode 100644
index 000000000..322d00cf4
--- /dev/null
+++ b/integrations/providers/email/adding-email.mdx
@@ -0,0 +1,55 @@
+---
+title: "Adding Email Channel"
+sidebarTitle: "Adding Email Channel"
+description: "Learn how to add the Email channel to your application"
+icon: "circle-plus"
+---
+
+The Email channel enables you to send email notifications to users for events like password resets, onboarding, or system alerts.
+
+
+
+
+
+By default, the Email channel is enabled and cofigured with Novu's default provider. If it is disabled, notifications sent to this channel will not be processed.
+
+
+1. Go to the Novu Dashboard and click **"Integrations"** on the left sidebar
+2. Click **"Add a provider"**
+3. Locate the **Email** channel and select the provider you want to use and click **"Next"**
+4. Select for which environment you want to add the Provider
+5. (Optional) Add Conditions to activate the provider only under certain conditions, **useful for tenant-based providers**
+6. Click **"Create"**
+7. Add your Email provider credentials:
+ - **From**: Displayed as the sender of the email (ensure compliance with local regulations)
+ - **Sender Name**: The name that will be used to send the email
+ - Provider-specific credentials such as API key / Auth token, Account SID, username, or password
+8. Save the configuration by clicking **"Update"**
+
+
+
+
+
+
+ 1. Go to the Novu Dashboard and click **"Workflows"** on the left sidebar.
+ 2. Click the **"Add a Workflow"** button.
+ 3. Add a step and select **"Email"** as the channel.
+ 4. Configure the email content, such as subject, message body, and any dynamic variables.
+
+
+
+
+
+Novuâs server-side SDKs make integrating Novuâs REST APIs straightforward, letting you focus on implementing workflows without dealing with repetitive code.
+
+
+
+
+
+Ensure your configuration is working by sending a test notification.
+
+ 1. Go to the Novu Dashboard, navigate to the "Workflows" section, and locate your configured workflow.
+ 2. Click **"Test Workflow"** and provide sample data (e.g., user ID, email address).
+ 3. Verify the email delivery in the Novu Logs or your email provider dashboard.
+
+
\ No newline at end of file
diff --git a/integrations/providers/email/amazon-ses.mdx b/integrations/providers/email/amazon-ses.mdx
new file mode 100644
index 000000000..5fe4794d3
--- /dev/null
+++ b/integrations/providers/email/amazon-ses.mdx
@@ -0,0 +1,50 @@
+---
+title: "Amazon SES"
+description: "Learn how to use the Amazon SES provider to send email notifications using Novu"
+---
+
+You can use the [Amazon SES](https://aws.amazon.com/ses/) provider to send transactional emails to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+## Getting Started
+
+To use the Amazon SES provider in the email channel, you will need to create an SES account and add your credentials to the Amazon SES integration on the Novu platform.
+
+## Setting up SES in AWS?
+
+- Either use a root AWS account or create a new IAM account with appropriate permission policies.
+ Example policy rule `arn:aws:ses:::identity/*`
+- Create a new access key and save generated `ACCESS_KEY_ID` and `ACCESS_SECRET_KEY` carefully
+- Choose Amazon Simple Email Service.
+- Create a new identity.
+- Either choose domain or email.
+- Verify your domain (by adding a few DNS records as mentioned in SES instructions) or email (AWS sends a verification email to your email).
+- Verify the recipient email also by creating a new email identity type [only in sandbox mode].
+- Test if your SES is set up correctly using the test email feature.
+
+## Creating an SES integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-integrations-ses) page on Novu.
+- Click on Add a Provider.
+- Select Amazon SES service.
+- Enter previously saved `ACCESS_KEY_ID` and `ACCESS_SECRET_KEY`.
+- Fill in the `From email address` field using the authenticated sender email id in the previous step.
+- Enter `region` and `Sender name` also.
+
+
+ Example region format:- `us-east-1`. By default Novu uses `us-east-1` region.
+
+
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Amazon SES in Novu.
+
+## FAQs
+
+
+
+ Possible reasons: 1. You have not verified the subscriber's email address in
+ SES (if you are in a sandbox environment). 2. Your daily sending limit has
+ been reached (if you are in a sandbox environment). 3. You have entered the
+ wrong aws region in the integration form.
+
+
diff --git a/integrations/providers/email/braze.mdx b/integrations/providers/email/braze.mdx
new file mode 100644
index 000000000..7a789873b
--- /dev/null
+++ b/integrations/providers/email/braze.mdx
@@ -0,0 +1,34 @@
+---
+title: "Braze"
+description: "Learn how to use the Braze provider to send email notifications using Novu"
+---
+
+You can use the [Braze](https://braze.com/) provider to send transactional emails to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the Braze provider in the email channel, you will need to create a [Braze account](https://braze.com/) and add your API key and other credentials to the Braze integration on the Novu platform.
+
+# Generating an API Key
+
+To generate a new API key in Braze, you can follow these steps:
+
+- [Sign up](https://braze.com) or [Log in](https://braze.com) to your Braze account.
+- Go to **Settings > API Keys**.
+- Click **+ Create New API Key**.
+- Give your new key a name for identification at a glance.
+- Select the right permission you want to be associated with the new API key.
+
+# Creating a Braze integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-braze) page on Novu.
+- Click on `Add a Provider`.
+- Locate **Braze** under the Email section and click on the **Next** button.
+- Select Your Environment add condition (Optional).
+- Click on the `Create` button.
+- Click on the `Disabled` button and mark it as `Active`.
+- Enter the `API Key`.
+- Enter the `Base URL`.
+- Enter the `From email address`.
+- Enter the `Sender name`.
+- Click on the **Update** button.
diff --git a/integrations/providers/email/custom-smtp.mdx b/integrations/providers/email/custom-smtp.mdx
new file mode 100644
index 000000000..931e46e1b
--- /dev/null
+++ b/integrations/providers/email/custom-smtp.mdx
@@ -0,0 +1,39 @@
+---
+title: "Custom SMTP"
+description: "Learn how to use the Custom SMTP provider to send email notifications using Novu"
+---
+
+You can use a Custom SMTP provider like [Nodemailer](https://nodemailer.com/about/) to send transactional emails through your custom SMTP server to your customers using the Novu Platform with a single API.
+
+# Getting Started
+
+To use the Custom SMTP provider in the email channel, you will need to have your personal SMTP server configured and add `host`, `port`, `user`, and `password` to the Custom SMTP integration on the Novu platform.
+
+You can also provide value **`true`** for the `secure` field if you want the connection to be secure, and if not, leave it empty.
+
+### DKIM (DomainKeys Identified Mail)
+
+DKIM options can be used in order to sign messages sent using Custom SMTP with DKIM keys.
+
+Those options are:
+
+- `DKIM Domain`
+- `DKIM Private Key`
+- `DKIM Key Selector`
+
+# Creating a Custom SMTP integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-customsmtp) page on Novu.
+- Click on Add a Provider.
+- Select Custom SMTP service.
+- Enter your SMTP credentials
+ - `host`
+ - `port`
+ - `username`
+ - `password`
+ - `secure`Â (on demand)
+ - And `DKIM` options if you want to sign messages with *DKIM*
+- Fill in the `From email address` field using the authenticated email from the previous step.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Custom SMTP in Novu.
diff --git a/integrations/providers/email/infobip.mdx b/integrations/providers/email/infobip.mdx
new file mode 100644
index 000000000..00948d288
--- /dev/null
+++ b/integrations/providers/email/infobip.mdx
@@ -0,0 +1,31 @@
+---
+title: "Infobip - email"
+description: "Learn how to use the Infobip provider to send email notifications using Novu"
+---
+
+You can use the [Infobip](https://www.infobip.com/developers/) provider to send transactional emails to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the Infobip provider in the email channel, you will need to create an Infobip account and add your API key and Base URL to the Infobip integration on the Novu platform.
+
+# Generating an API Key
+
+To generate a new API key in Infobip, you can follow these steps:
+
+- [Sign up](https://www.infobip.com/signup) or [Log in](https://portal.infobip.com/login/) to your Infobip account.
+- Navigate to the [Settings](https://portal.infobip.com/settings/accounts/api-keys) of your account and look for the API Keys section at the top of the settings page.
+
+# Creating an Infobip integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-infobip) page on Novu.
+- Click on Add a Provider.
+- Select Infobip service.
+- Enter your Infobip API Key.
+- Enter your Base URL.
+ - To see your base URL, log in to the account. Once logged in, on all pages, you should see your base URL in this format:Â `xxxxx.api.infobip.com`.
+- Fill in the `From email address` field using the authenticated email from the previous step.
+- Fill in the `Sender's name`.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Infobip in Novu.
diff --git a/integrations/providers/email/mailersend.mdx b/integrations/providers/email/mailersend.mdx
new file mode 100644
index 000000000..40f550ed0
--- /dev/null
+++ b/integrations/providers/email/mailersend.mdx
@@ -0,0 +1,133 @@
+---
+title: "Mailersend"
+description: "Learn how to use the MailerSend provider to send email notifications using Novu"
+---
+
+[MailerSend](https://www.mailersend.com/)Â is an email delivery service that allows you to send emails from your application.
+
+## Getting Started
+
+To use the MailerSend provider in the email channel, you will need to create a MailerSend account and add your API key to the MailerSend integration on the Novu platform. To generate the API token go visit the [MailerSend API Tokens](https://www.mailersend.com/help/managing-api-tokens) page.
+
+## Creating the MailerSend integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-mailersend) page on Novu.
+- Click on Add a Provider.
+- Select MailerSend service.
+- Enter the API key.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using MailerSend in Novu.
+
+## Using MailerSend template
+
+Novu has its own email editor for writing email template. If you want to use pre made template from MailerSend, you can use `customData` filed of email overrides to send template details. Make sure your `Api Key` has enough permission to read and process the template.
+
+
+
+```jsx
+import {
+ Novu
+} from '@novu/node';
+
+const novu = new Novu('');
+
+await novu.subscribers.trigger("workflowIdentifier", {
+to: "subscriberId",
+payload: {},
+overrides: {
+email: {
+customData: {
+// mailersend template templateId
+templateId: 'mailersend-template-id',
+// mailersend template variables
+personalization: [{
+email: 'recipient@email.com',
+data: {
+items: {
+price: '',
+product: '',
+quantity: '',
+},
+order: {
+date: '',
+order_number: '',
+billing_address: '',
+customer_message: '',
+},
+store: {
+name: '',
+},
+invoice: {
+total: '',
+subtotal: '',
+pay_method: '',
+},
+customer: {
+name: '',
+email: '',
+phone: '',
+},
+},
+}, ],
+},
+}
+},
+// actorId is subscriberId of actor
+actor: "actorId"
+tenant: "tenantIdentifier"
+});
+
+```
+
+
+```bash
+curl --location 'https://api.novu.co/v1/events/trigger' \
+--header 'Content-Type: application/json' \
+--header 'Accept: application/json' \
+--header 'Authorization: ApiKey ' \
+--data '{
+ "name": "workflowIdentifier",
+ "to": ["subscriberId"],
+ "payload": {},
+ "overrides": {
+ "email": {
+ "customData": {
+ "templateId": "mailersend-template-id",
+ "personalization": [{
+ "email": "recipient@email.com",
+ "data": {
+ "items": {
+ "price": "",
+ "product": "",
+ "quantity": ""
+ },
+ "order": {
+ "date": "",
+ "order_number": "",
+ "billing_address": "",
+ "customer_message": ""
+ },
+ "store": {
+ "name": ""
+ },
+ "invoice": {
+ "total": "",
+ "subtotal": "",
+ "pay_method": ""
+ },
+ "customer": {
+ "name": "",
+ "email": "",
+ "phone": ""
+ }
+ }
+ }]
+ }
+ }
+ }
+}'
+```
+
+
+
diff --git a/integrations/providers/email/mailgun.mdx b/integrations/providers/email/mailgun.mdx
new file mode 100644
index 000000000..d063858c7
--- /dev/null
+++ b/integrations/providers/email/mailgun.mdx
@@ -0,0 +1,43 @@
+---
+title: "Mailgun"
+description: "Learn how to use the Mailgun provider to send email notifications using Novu"
+---
+
+You can use the [Mailgun](https://mailgun.com/) provider to send transactional emails to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the Mailgun provider in the email channel, you will need to create a Mailgun account and add your API key and domain name to the Mailgun integration on the Novu platform.
+
+# Generating an API Key
+
+To generate a new API key in Mailgun, you can follow these steps:
+
+- [Sign up](https://signup.mailgun.com/new/signup) or [Log in](https://login.mailgun.com/login/) to your Mailgun account.
+- Click on the **Profile** section in the top right corner of the screen, and then click "API Keys" from the drop-down menu.
+- On the [API Keys](https://app.mailgun.com/app/account/security/api_keys) page, copy the generated **Private API Key**
+
+# Adding a new domain name
+
+Mailgun recommends that you add a subdomain as a domain name. To do so:
+
+- Visit the page to add a [domain name](https://app.mailgun.com/app/sending/domains/new).
+ - During this process, you will need to choose a region for the domain name which is between `US` and `EU`. The default is `US`.
+- Follow the [instructions](https://documentation.mailgun.com/en/latest/user_manual.html#verifying-your-domain-1) to verify the domain name.
+
+# Creating a Mailgun integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-mailgun) page on Novu.
+- Click on Add a Provider.
+- Select Mailgun service.
+- Enter your Mailgun API Key.
+- Enter your Base URL.
+ - For domains created in the EU region, the base URL is:Â `https://api.eu.mailgun.net/`
+ - Otherwise, leave the base URL blank.
+- Fill in the `Username`.
+- Fill in the `Domain name` registered on Mailgun.
+- Fill in the `From email address` field using the authenticated email from the previous step.
+- Fill in the `Sender's name`.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Mailgun in Novu.
diff --git a/integrations/providers/email/mailjet.mdx b/integrations/providers/email/mailjet.mdx
new file mode 100644
index 000000000..ae143b701
--- /dev/null
+++ b/integrations/providers/email/mailjet.mdx
@@ -0,0 +1,40 @@
+---
+title: "Mailjet"
+description: "Learn how to use the Mailjet provider to send email notifications using Novu"
+---
+
+You can use the [Mailjet](https://mailjet.com/) provider to send transactional emails to your customers using the Novu Platform with a single API.
+
+# Getting Started
+
+To use the Mailjet provider in the email channel, you will need to create a Mailjet account and add your API key to the Mailjet integration on the Novu platform.
+
+# Generating an API Key
+
+To generate a new API key in Mailjet, you can follow these steps:
+
+- Log in to your Mailjet account.
+- Click on **Settings** in the top-right corner of the screen, and then click **API KEYS & TRACKING** from the drop-down menu.
+- On the API Keys page, click the **Create an API Key** button.
+- Give the API key a name and choose the access level **Write and Read**
+- Click the **Generate Key** button to create the new key. Once generated you can see the key but it will be hidden after the refresh
+
+# Authenticating your sender identity
+
+Before you can send emails on a large scale, you will need to authenticate your Sender identity. This is due to the latest regulatory changes regarding SPAM rules and email fraud. Most of the providers including Mailjet require you to authenticate your Sender identity before you can send emails.
+
+Mailjet allows you to authenticate your sender identity using one of the following methods:
+
+- [Single Sender Verification](https://dev.mailjet.com/email/guides/senders-and-domains/#sender-validation)Â - This is the easiest way to authenticate your sender identity.
+- [Entire Domain Authentication](https://dev.mailjet.com/email/guides/senders-and-domains/#spf-and-dkim-validation)Â - This is recommended if you are sending emails from multiple accounts under your domain.
+
+# Creating a Mailjet integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-mailjet) page on Novu.
+- Click on Add a Provider.
+- Select Mailjet service.
+- Enter your Mailjet API key.
+- Fill in the `From email address` field using the authenticated email from the previous step.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Mailjet in Novu.
diff --git a/integrations/providers/email/mailtrap.mdx b/integrations/providers/email/mailtrap.mdx
new file mode 100644
index 000000000..aa2881dfc
--- /dev/null
+++ b/integrations/providers/email/mailtrap.mdx
@@ -0,0 +1,34 @@
+---
+title: "Mailtrap"
+description: "Learn how to use the Mailtrap provider to send email notifications using Novu"
+---
+
+You can use the [Mailtrap](https://mailtrap.io/email-sending/) provider to send transactional emails to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the Mailtrap provider in the email channel, you will need to create a Mailtrap account and add your API key to the Mailtrap integration on the Novu platform.
+
+# Generating an API Key
+
+To generate a new API key in Mailtrap, you can follow these steps:
+
+- [Sign Up](https://mailtrap.io/register/signup) or [Log in](https://mailtrap.io/signin) to your Mailtrap account.
+- Click on the **Email Sending** link on the sidebar, and then click the "Sending Domains" link that pops up from the available options.
+- On the [Sending Domains](https://mailtrap.io/sending/domains) page, type your domain name and confirm with the `Add Your Domain` button. Then, proceed to copy DNS records Mailtrap provides to your domainâs DNS.
+- Go to [API Keys](https://mailtrap.io/api-tokens) page and copy token with `Domain Admin` access level for your registered domain.
+
+# Authenticating your Sender Identity
+
+Before you can send emails, you will need to [verify your sending domain ownership](https://help.mailtrap.io/article/69-sending-domain-setup). Mailtrap rejects sending emails from unverified domains to prevent spam and email fraud.
+
+# Creating a Mailtrap integration with Novu
+
+- Visit the [Integrations store](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-mailtrap) on the Novu web dashboard.
+- Click on Add a Provider.
+- Select Mailtrap service.
+- Enter your Mailtrap API Key.
+- Fill in the `From email address` field using the authenticated email from the previous step.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications through Mailtrap using Novu.
diff --git a/integrations/providers/email/mandrill.mdx b/integrations/providers/email/mandrill.mdx
new file mode 100644
index 000000000..28babd963
--- /dev/null
+++ b/integrations/providers/email/mandrill.mdx
@@ -0,0 +1,38 @@
+---
+title: "Mandrill"
+description: "Learn how to use the Mandrill provider to send email notifications using Novu"
+---
+
+You can use the [Mandrill by Mailchimp](https://mandrillapp.com/) provider to send transactional emails to your customers using the Novu Platform with a single API.
+
+# Getting Started
+
+To use the Mandrill provider in the email channel, you will need to create a Mandrill account and add your API key to the Mandrill integration on the Novu platform.
+
+# Generating an API Key
+
+To generate a new API key in Mandrill, you can follow these steps:
+
+- [Sign up](https://login.mailchimp.com/signup/) or [Log in](https://login.mailchimp.com/) to your Mandrill account.
+- Navigate to the [Settings](https://mandrillapp.com/settings) of your account and look for the API Keys section at the bottom of the settings page.
+- Click on the **+ Add API Key** button to create an API key. Copy the generated key immediately and store it in a secure location. You wonât be able to see or copy the key once you finish generating it.
+
+# Adding a sending domain
+
+To get started, youâll need to add the domain that you want to send messages from.
+
+- Navigate to the [Settings page](https://mandrillapp.com/settings/sending-domains) and choose Domains
+- Type a new domain in the domain input and click Add
+- Follow the instructions to [verify ownership](https://mailchimp.com/developer/transactional/docs/authentication-delivery/#authentication) of your sending domain and [update your DNS records](https://mailchimp.com/developer/transactional/docs/authentication-delivery/#configure-your-dns).
+
+# Creating the Mandrill integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-mandrill) page on Novu.
+- Click on Add a Provider.
+- Select Mandrill service.
+- Enter your Mandrill API key.
+- Fill in the `From email address` field using the authenticated email from the previous step.
+- Fill in the `Sender's name`.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Mandrill in Novu.
diff --git a/integrations/providers/email/maqsam.mdx b/integrations/providers/email/maqsam.mdx
new file mode 100644
index 000000000..2778394cd
--- /dev/null
+++ b/integrations/providers/email/maqsam.mdx
@@ -0,0 +1,22 @@
+---
+title: "Maqsam"
+description: "Learn how to use the Maqsam provider to send sms notifications using Novu"
+---
+
+You can use the [Maqsam](https://maqsam.com/) provider to send SMS messages to your customers using the Novu platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the Maqsam provider in the sms channel, you will need to create a Maqsam account and add your access key & secret to the Maqsam integration on the Novu platform.
+Contact `support@maqsam.com` to enable the API feature for your account, then you can generate `access_key_id` and `access_secret` combination from the account settings.
+
+# Creating the Maqsam integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-maqsam) page on Novu.
+- Click the "Add a provider" button.
+- Select Maqsam service
+- Click `Next`
+- Choose your preferred deployment environment: `Development` or `Production`. Then Click the `Create` button.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Maqsam in Novu.
diff --git a/integrations/providers/email/netcore.mdx b/integrations/providers/email/netcore.mdx
new file mode 100644
index 000000000..cd2d9ca67
--- /dev/null
+++ b/integrations/providers/email/netcore.mdx
@@ -0,0 +1,36 @@
+---
+title: "Netcore"
+description: "Learn how to use the Netcore provider to send email notifications using Novu"
+---
+
+You can use the [Netcore](https://netcorecloud.com/) provider to send transactional emails to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the Netcore provider in the email channel, you will need to create a Netcore account and add your API key to the Netcore integration on the Novu platform.
+
+# Generating an API Key
+
+To generate a new API key in Netcore, you can follow these steps:
+
+- [Log in](https://email.netcorecloud.com/)Â to your Netcore account.
+- Go to the **Integration** page under the **Settings** menu and click on the **API** tab.
+- The API Key is hidden for security purposes. Click Show. The system will prompt you to enter your account password. Once you enter the password, the API key will be accessible.
+
+# Setting up sending domains
+
+To start sending emails, you need to add and verify your sending domains. You can either use your top-level domain (e.g. my-company.com) or a sub-domain like email.my-company.com. The verification is done to ensure your sending domainâs security.
+
+Follow the instructions on this [page](https://emaildocs.netcorecloud.com/docs/what-is-a-sending-domain-how-to-set-up-sending-domains) to get started
+
+# Creating a Netcore integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-netcore) page on Novu.
+- Click on Add a Provider.
+- Select Netcore service.
+- Enter your Netcore API Key.
+- Fill in the `From email address` field using the authenticated email from the previous step.
+- Fill in the `Sender's name`.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Netcore in Novu.
diff --git a/integrations/providers/email/outlook365.mdx b/integrations/providers/email/outlook365.mdx
new file mode 100644
index 000000000..090cc7615
--- /dev/null
+++ b/integrations/providers/email/outlook365.mdx
@@ -0,0 +1,29 @@
+---
+title: "Outlook 365"
+description: "Learn how to use the Outlook 365 provider to send email notifications using Novu"
+---
+
+You can use the [Outlook 365](https://office.com/) provider to send transactional emails through your instance of Office 365 to your customers using the Novu Platform with a single API.
+
+## Getting Started
+
+To use the Outlook 365 provider in the email channel, you will need to have the sender's email (user) and the password for the account. This account cannot be a shared mailbox or distribution list. It will need to be properly licensed to send email via Office 365.
+
+## Creating the Outlook 365 integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-office365) page on Novu.
+- Click on Add a Provider.
+- Select Outlook service.
+- Enter your SMTP credentials
+ - `from`: The Complete email address of the sending user. (e.g. [jdoe@mycompany.com](mailto:jdoe@mycompany.com))
+ - `senderName`: Sender Name should be the same email address of the sending user. (e.g. [jdoe@mycompany.com](mailto:jdoe@mycompany.com))
+ - `password`: Password used to sign in with the email account.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Outlook 365 in Novu.
+
+
+ {" "}
+ In order to create outlook integration, turn off multi factor authentication from
+ account security settings.
+
diff --git a/integrations/providers/email/overview.mdx b/integrations/providers/email/overview.mdx
new file mode 100644
index 000000000..f296c7692
--- /dev/null
+++ b/integrations/providers/email/overview.mdx
@@ -0,0 +1,179 @@
+---
+title: "Email Providers Integration"
+sidebarTitle: "Overview"
+description: "Learn how to configure the Email channel"
+icon: "circle-info"
+---
+
+The Email Channel is a critical component for delivering notifications reliably. Whether it's a password reset, an onboarding email, or an alert about account activity, email remains a trusted medium for reaching users.
+Novu simplifies this process, allowing you to focus on implementation rather than infrastructure.
+
+## Key Features
+
+- **Multi-Provider Support**: Integrate any major provider like SendGrid, SES, or Mailgun.
+- **Failover Mechanisms**: Automatically retry with a backup provider to ensure reliability.
+- **Customizable Templates**: Leverage templates with dynamic placeholders to personalize messages.
+- **Delivery Insights (Coming Soon)**: Track delivery status, open rates, and more in the Novu dashboard.
+
+## Common Use Cases
+
+- **Transactional Emails**: Password resets, account verification, purchase confirmations
+- **System Alerts**: Security notifications, system updates
+- **Engagement Emails**: Onboarding, reminders, promotional updates
+
+
+
+import { MissingProvider } from "/snippets/missing-provider.mdx";
+
+Novu can be used to deliver email messages to your subscribers using a unified delivery API. You can easily integrate your favorite email provider using the built-in integration store.
+
+## Configuring email providers
+
+When creating an email provider integration you will be asked to provide additional fields alongside the provider-specific credentials:
+
+- **Sender name** - Will be displayed as the sender of the message
+- **From email address** - Emails sent using Novu will be sent using this address
+
+For some email providers including SendGrid you will have to authenticate the **From email address** to make sure you will send email messages using an authorized address.
+
+## Sending Email Overrides
+
+The overrides field supports an email property. The email overrides field have properties like `to`, `from`, `senderName` etc
+
+
+
+```javascript
+import { Novu } from '@novu/node';
+
+const novu = new Novu('');
+
+novu.trigger('', {
+ to: {
+ subscriberId: '',
+ },
+ overrides: {
+ email: {
+ to: ['to@novu.co'],
+ from: 'from@novu.co',
+ senderName: 'Novu Team',
+ text: 'text version of email using overrides',
+ replyTo: 'no-reply@novu.co',
+ cc: ['1@novu.co'],
+ bcc: ['2@novu.co'],
+ },
+ },
+});
+```
+
+
+
+It's very important to know that Novu merges the `to` field in the email overrides with the subscriber email. It DOES NOT REPLACE IT.
+
+## Sending Email attachments
+
+You can easily send attachments with the Novu API by passing the attachments array when triggering an Email based workflow. Attachment file can either be in the `buffer` or `base64` format.
+
+
+
+
+```javascript
+import { Novu } from '@novu/node';
+
+const novu = new Novu('');
+
+novu.trigger('', {
+ to: {
+ subscriberId: '',
+ },
+ payload: {
+ attachments: [
+ {
+ // buffer format
+ file: fs.readFileSync(__dirname + '/data/novu.jpeg'),
+ name: 'novu.jpeg',
+ mime: 'image/jpeg',
+ },
+ {
+ // base64 format
+ file: 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mNkYPhfz0AEYBxVSF+FAP5FDvcfRYWgAAAAAElFTkSuQmCC',
+ name: 'blue.png',
+ mime: 'image/png',
+ }
+ ],
+ },
+});
+```
+
+
+ Use https://eu.api.novu.co/v1/events/trigger api endpoint for the EU region.
+```bash
+curl -L -X POST 'https://api.novu.co/v1/events/trigger' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+--data-raw '{
+ "name": "workflow_trigger_identifier",
+ "to": [
+ {
+ "subscriberId": "subscriber_id",
+ "email": "email_address"
+ }
+ ],
+ "payload": {
+ "attachments": [
+ {
+ "file": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII",
+ "name": "transparent.png",
+ "mime": "image/png"
+ },
+ {
+ "file": "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mNkYPhfz0AEYBxVSF+FAP5FDvcfRYWgAAAAAElFTkSuQmCC",
+ "name": "blue.png",
+ "mime": "image/png"
+ }
+ ]
+ }
+}'
+```
+
+
+
+## Using different email integration
+
+In Novu integration store, multiple email channel type provider integrations can be active at the same time. But only one provider integration can be primary at a time. This primary integration will be used as a provider to deliver the email by default. If you want to use a different active provider integration then you can use the `integrationIdentifier` email overrides field.
+
+If there are 4 active email integrations with these identifiers:-
+
+1. sendgrid-abcdef
+2. sendgrid-ghijkl
+3. brevo-abcdef
+4. mailersend-abcdef
+
+Here, if `sendgrid-abcdef` is primary integration and you want to use `brevo-abcdef` with this trigger then you can use `integrationIdentifier` email overrides field as below:-
+
+
+
+```javascript
+import { Novu } from '@novu/node';
+
+const novu = new Novu('');
+
+novu.trigger('', {
+ to: {
+ subscriberId: '',
+ },
+ overrides: {
+ email: {
+ integrationIdentifier: "brevo-abcdef"
+ },
+ },
+});
+```
+
+
+
+ Integration identifier is similar to Provider identifier but it is different than Provider Id. It is unique for each integration.You can find the `integrationIdentifier` in the integration store page.
+
+
+
+
diff --git a/integrations/providers/email/plunk.mdx b/integrations/providers/email/plunk.mdx
new file mode 100644
index 000000000..e4bc116d8
--- /dev/null
+++ b/integrations/providers/email/plunk.mdx
@@ -0,0 +1,33 @@
+---
+title: "Plunk"
+description: "Learn how to use the Plunk provider to send email notifications using Novu"
+---
+
+You can use the [Plunk](https://useplunk.com/) provider to send transactional emails to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+## Getting Started
+
+To use the Plunk provider in the email channel, you will need to create a Plunk account and add your API key to the Plunk integration on the Novu platform.
+
+## Get API Key
+
+To generate a new API key in Plunk, you can follow these steps:
+
+- Log in to your Plunk account.
+- Click on `Project Settings` on the side bar and then `API keys` on the tab.
+- On the API Keys page, click on `Secret API key` to copy.
+
+## Authenticate your sender identity
+
+Before you can send emails on a large scale, you will need to authenticate your Sender Identity. Plunk allows you to authenticate your sender identity using [Domain Authentication](https://app.useplunk.com/settings/identity)
+
+## Create a Plunk integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-plunk) page on Novu.
+- Click on Add a Provider.
+- Select Plunk service.
+- Enter your Plunk secret API Key.
+- Fill the `From email address` field using the authenticated email from the previous step.
+- Click on the `Disabled` button and mark as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Plunk in Novu.
diff --git a/integrations/providers/email/postmark.mdx b/integrations/providers/email/postmark.mdx
new file mode 100644
index 000000000..7022ed0de
--- /dev/null
+++ b/integrations/providers/email/postmark.mdx
@@ -0,0 +1,35 @@
+---
+title: "Postmark"
+description: "Learn how to use the Postmark provider to send email notifications using Novu"
+---
+
+It is possible to use [Postmark](https://postmarkapp.com/) as a provider to send transactional emails to your customers using the Novu Platform with a single API.
+
+# Getting Started
+
+The first step to use the Postmark provider in the email channel is to create a Postmark account and add the personal API key to the Postmark integration on the Novu platform.
+
+# Getting the API Key
+
+- To find the Postmark API key, log into the personal Postmark account and navigate to the servers page.
+- After selecting the server to use, the API key (referred to as "Server API tokens") will be in the "API Tokens" section of the server chosen.
+
+# Authenticating the sender's identity
+
+Due to the latest regulatory changes regarding SPAM rules and email fraud, it is needed to authenticate the sender's identity before sending emails on a large scale. Most of the providers, including Postmark, require authentication to unlock the possibility of sending emails.
+
+Postmark allows the authentication of the sender's identity using one of the following methods:
+
+- [Single Sender Verification](https://account.postmarkapp.com/signatures/new)Â - This is the easiest way to authenticate the sender's identity.
+- [Entire Domain Authentication](https://postmarkapp.com/support/article/1046-how-do-i-verify-a-domain#:~:text=be%20verified%20automatically.-,Navigate%20to%20Sender%20Signatures.,to%20your%20DNS%2C%20choose%20Verify.)Â - This is recommended for sending emails from multiple accounts under the same domain.
+
+# Create a Postmark integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-postmark) page on Novu.
+- Click on Add a Provider.
+- Select Postmark service.
+- Enter the Postmark API key.
+- Fill in the `From email address` field using the authenticated email from the previous step.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- Now is possible to send notifications using Postmark in Novu.
diff --git a/integrations/providers/email/resend.mdx b/integrations/providers/email/resend.mdx
new file mode 100644
index 000000000..ebf2bb5d9
--- /dev/null
+++ b/integrations/providers/email/resend.mdx
@@ -0,0 +1,39 @@
+---
+title: "Resend"
+description: "Learn how to use the Resend provider to send email notifications using Novu"
+---
+
+You can use the [Resend](https://resend.com/) provider to send transactional emails to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the Resend provider in the email channel, you will need to create a Resend account and add your API key to the Resend integration on the Novu platform.
+
+# Generating an API Key
+
+To generate a new API key in Resend, you can follow these steps:
+
+- [Sign up](https://resend.com/secret) or [Log in](https://resend.com/login) to your Resend account.
+- Click on the **API Keys** link in the left sidebar, and then click the "Create API Key" button on the top right part of the page.
+- On the [API Keys](https://resend.com/api-keys) page, click the **Create API Key** button.
+- Give the API key a name and click on the **Add** button.
+- Copy the generated API Key.
+
+# Authenticating your Sender Identity
+
+Before you can send emails on a large scale, you will need to authenticate your Sender Identity.
+
+Resend allows you to authenticate your sender identity using [Domain Authentication](https://resend.com/docs/dashboard/domains/introduction).
+
+# Creating a Resend integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-resend) page on Novu.
+- Click on Add a Provider.
+- Select Resend service.
+- Enter your Resend API Key.
+- Fill in the `From email address` field using the authenticated email from the previous step.
+ - For testing, you can use `onboarding@resend.dev` if you have not authenticated your sender identity.
+- Fill in the `Sender's name`.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Resend in Novu.
diff --git a/integrations/providers/email/sendgrid.mdx b/integrations/providers/email/sendgrid.mdx
new file mode 100644
index 000000000..d2ab6aca1
--- /dev/null
+++ b/integrations/providers/email/sendgrid.mdx
@@ -0,0 +1,213 @@
+---
+title: "SendGrid"
+description: "Learn how to use the Sendgrid provider to send email notifications using Novu"
+---
+
+You can use the [SendGrid](https://sendgrid.com/) provider to send transactional emails to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+### Getting Started
+
+To use the Sendgrid provider in the email channel, you will need to create a Sendgrid account and add your API key to the SendGrid integration on the Novu platform.
+
+### Generating an API Key
+
+To generate a new API key in SendGrid, follow these steps:
+
+- Log in to your SendGrid account.
+- Click on the **Settings** gear icon in the top right corner of the screen, and then click "API Keys" from the drop-down menu.
+- On the API Keys page, click the **Create API Key** button.
+- Give the API key a name and select the following permissions
+- **Mail Send**Â - Full Access
+- (Optional) Template Engine - Read Only
+- Click the **Create & View** button to generate the API key. The key will be displayed on the screen, but you will only be able to view it once, so make sure to save it in a safe place.
+
+NOTE
+
+The access level of the key will determine what actions the API Key can take, so please choose the correct one.
+
+- **Mail Send**Â - Full Access
+- (Optional) Template Engine - Read Only
+
+### Authenticating your [Sender Identity](https://docs.sendgrid.com/for-developers/sending-email/sender-identity)
+
+Before you can send emails on a large scale, you will need to authenticate your Sender Identity. This is due to the latest regulatory changes regarding SPAM rules and email fraud. Most of the providers including Sendgrid require you to authenticate your Sender Identity before you can send emails.
+
+SendGrid allows you to authenticate your sender identity using one of the following methods:
+
+- [Single Sender Verification](https://docs.sendgrid.com/ui/sending-email/sender-verification)Â - This is the easiest way to authenticate your sender identity.
+- [Entire Domain Authentication](https://docs.sendgrid.com/ui/account-and-settings/how-to-set-up-domain-authentication)Â - This is recommended if you are sending emails from multiple accounts under your domain.
+
+### SendGrid integration with Novu
+
+- Visit the [Integrations store](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sendgrid) on the Novu web dashboard.
+- Click on Add a Provider.
+- Select SendGrid service.
+- Enter your SendGrid API Key.
+- Fill in the `From email address` field using the authenticated email from the previous step.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications through SendGrid using Novu.
+
+### Using SendGrid template
+
+Novu has its own email editor for writing email template. To send pre-made template in SendGrid, `customData` filed of email overrides can be used to send template details. Make sure sendgrid `Api Key` has enough permission to read and process the template. This `customData` field can be used to send custom args and extra data in the form of key-value pairs.
+
+customData override is available from version 0.21.0
+
+
+
+```typescript
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+await novu.subscribers.trigger("workflowIdentifier", {
+ to: "subscriberId",
+ payload: {},
+ overrides: {
+ email: {
+ customData: {
+ // sendgrid template templateId
+ templateId: "sendgrid-template-id",
+ // sendgrid template variables
+ dynamicTemplateData: {
+ total: "$ 239.85",
+ items: [
+ {
+ text: "New Line Sneakers",
+ image:
+ "https://marketing-image-production.s3.amazonaws.com/uploads/8dda1131320a6d978b515cc04ed479df259a458d5d45d58b6b381cae0bf9588113e80ef912f69e8c4cc1ef1a0297e8eefdb7b270064cc046b79a44e21b811802.png",
+ price: "$ 79.95",
+ },
+ {
+ text: "Old Line Sneakers rlfjrjrh4hr4rh4",
+ image:
+ "https://marketing-image-production.s3.amazonaws.com/uploads/3629f54390ead663d4eb7c53702e492de63299d7c5f7239efdc693b09b9b28c82c924225dcd8dcb65732d5ca7b7b753c5f17e056405bbd4596e4e63a96ae5018.png",
+ price: "$ 79.95",
+ },
+ ],
+ receipt: true,
+ name: "Sample Name",
+ address01: "1234 Fake St.",
+ address02: "Apt. 123",
+ city: "Place",
+ state: "CO",
+ zip: "80202",
+ },
+ },
+ },
+ },
+ // actorId is subscriberId of actor
+ actor: "actorId",
+ tenant: "tenantIdentifier",
+});
+```
+
+
+```bash
+curl --location 'https://api.novu.co/v1/events/trigger' \
+--header 'Content-Type: application/json' \
+--header 'Accept: application/json' \
+--header 'Authorization: ApiKey ' \
+--data '{
+ "name": "workflowIdentifier",
+ "to": ["subscriberId"],
+ "payload": {},
+ "overrides": {
+ "email": {
+ "customData": {
+ "templateId": "sendgrid-template-id",
+ "dynamicTemplateData": {
+ "total": "$ 239.85",
+ "items": [
+ {
+ "text": "New Line Sneakers",
+ "image": "https://marketing-image-production.s3.amazonaws.com/uploads/8dda1131320a6d978b515cc04ed479df259a458d5d45d58b6b381cae0bf9588113e80ef912f69e8c4cc1ef1a0297e8eefdb7b270064cc046b79a44e21b811802.png",
+ "price": "$ 79.95"
+ },
+ {
+ "text": "Old Line Sneakers rlfjrjrh4hr4rh4",
+ "image": "https://marketing-image-production.s3.amazonaws.com/uploads/3629f54390ead663d4eb7c53702e492de63299d7c5f7239efdc693b09b9b28c82c924225dcd8dcb65732d5ca7b7b753c5f17e056405bbd4596e4e63a96ae5018.png",
+ "price": "$ 79.95"
+ }
+ ],
+ "receipt": true,
+ "name": "Sample Name",
+ "address01": "1234 Fake St.",
+ "address02": "Apt. 123",
+ "city": "Place",
+ "state": "CO",
+ "zip": "80202"
+ }
+ }
+ }
+ }
+}'
+```
+
+
+```typescript
+import { workflow } from "@novu/framework";
+import { z } from "zod";
+
+export const sendgridOverridesEmailExample = workflow(
+ "sendgrid-email-overrides",
+ async ({ step, payload }) => {
+ await step.email(
+ "sendgrid-email-overrides",
+ async () => {
+ return {
+ subject: "SendGrid Overrides Example",
+ body: "This body content should be overridden by the SendGrid template",
+ };
+ },
+ {
+ providers: {
+ sendgrid: ({}) => ({
+ _passthrough: {
+ body: {
+ templateId: payload.dynamicTemplateId,
+ dynamicTemplateData: {
+ // Example variables to be used in the template
+ total: "$ 239.85",
+ items: [
+ {
+ text: payload.itemName,
+ image:
+ "https://marketing-image-production.s3.amazonaws.com/uploads/8dda1131320a6d978b515cc04ed479df259a458d5d45d58b6b381cae0bf9588113e80ef912f69e8c4cc1ef1a0297e8eefdb7b270064cc046b79a44e21b811802.png",
+ price: "$ 79.95",
+ },
+ {
+ text: "Old Line Sneakers rlfjrjrh4hr4rh4",
+ image:
+ "https://marketing-image-production.s3.amazonaws.com/uploads/3629f54390ead663d4eb7c53702e492de63299d7c5f7239efdc693b09b9b28c82c924225dcd8dcb65732d5ca7b7b753c5f17e056405bbd4596e4e63a96ae5018.png",
+ price: "$ 79.95",
+ },
+ ],
+ receipt: true,
+ name: "Sample Name",
+ address01: "1234 Fake St.",
+ address02: "Apt. 123",
+ city: "Place",
+ state: "CO",
+ zip: "80202",
+ },
+ },
+ },
+ }),
+ },
+ }
+ );
+ },
+ {
+ payloadSchema: z.object({
+ itemName: z.string().default("New Line Sneakers"),
+ dynamicTemplateId: z
+ .string()
+ .default("d-d965b02b1b5d4856bf332a5e98c7470c"),
+ }),
+ }
+);
+```
+
+
diff --git a/integrations/providers/email/sendinblue.mdx b/integrations/providers/email/sendinblue.mdx
new file mode 100644
index 000000000..be5bda26e
--- /dev/null
+++ b/integrations/providers/email/sendinblue.mdx
@@ -0,0 +1,132 @@
+---
+title: "Brevo"
+description: "Learn how to use the Brevo provider to send email notifications using Novu"
+---
+
+You can use the [Brevo](https://www.brevo.com/) provider to send transactional emails to your customers using the Novu Platform with a single API.
+
+# Getting Started
+
+To use the Brevo provider in the email channel, you will need to create a Brevo account and add your API key to the Brevo integration on the Novu platform.
+
+# Finding the API Key
+
+- To find your Brevo API key, log into your Brevo account and navigate to the [API Keys](https://account.brevo.com/advanced/api) page.
+
+# Authenticating your sender identity
+
+Before you can send emails on a large scale, you will need to authenticate your sender's identity. This is due to the latest regulatory changes regarding SPAM rules and email fraud. Most of the providers including Brevo require you to authenticate your sender identity before you can send emails.
+
+Brevo allows you to authenticate your sender identity using one of the following methods:
+
+- [Single Sender Verification](https://account.brevo.com/senders)Â - This is the easiest way to authenticate your sender identity.
+- [Entire Domain Authentication](https://help.brevo.com/hc/en-us/articles/12163873383186-Authenticate-your-domain-with-Brevo-Brevo-code-DKIM-record-DMARC-record)Â - This is recommended if you are sending emails from multiple accounts under your domain.
+
+# Creating a Brevo integration with Novu
+
+- Visit the [Integrations store](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-brevo) on the Novu web dashboard.
+- Click on Add a Provider.
+- Select Brevo service.
+- Enter your Brevo API key.
+- Fill in the `From email address` field using the authenticated email from the previous step.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Brevo in Novu.
+
+## Using Brevo template
+
+Novu has its own email editor for writing email template. If you want to use pre made template from Brevo, you can use `customData` filed of email overrides to send template details. Make sure your `Api Key` has enough permission to read and process the template.
+
+customData override is available from version 0.21.0
+
+
+
+```jsx
+import { Novu } from '@novu/node';
+
+const novu = new Novu('');
+
+await novu.subscribers.trigger("workflowIdentifier", {
+to: "subscriberId",
+payload: {},
+overrides: {
+email: {
+customData: {
+// sendinblue template templateId
+templateId: 1,
+// sendinblue template variables
+templateParams: {
+total: '$ 239.85',
+items: [{
+text: 'New Line Sneakers',
+image: 'https://marketing-image-production.s3.amazonaws.com/uploads/8dda1131320a6d978b515cc04ed479df259a458d5d45d58b6b381cae0bf9588113e80ef912f69e8c4cc1ef1a0297e8eefdb7b270064cc046b79a44e21b811802.png',
+price: '$ 79.95',
+},
+{
+text: 'Old Line Sneakers rlfjrjrh4hr4rh4',
+image: 'https://marketing-image-production.s3.amazonaws.com/uploads/3629f54390ead663d4eb7c53702e492de63299d7c5f7239efdc693b09b9b28c82c924225dcd8dcb65732d5ca7b7b753c5f17e056405bbd4596e4e63a96ae5018.png',
+price: '$ 79.95',
+},
+],
+receipt: true,
+name: 'Sample Name',
+address01: '1234 Fake St.',
+address02: 'Apt. 123',
+city: 'Place',
+state: 'CO',
+zip: '80202',
+},
+},
+}
+},
+// actorId is subscriberId of actor
+actor: "actorId",
+tenant: "tenantIdentifier"
+});
+
+```
+
+
+```bash
+curl --location 'https://api.novu.co/v1/events/trigger' \
+--header 'Content-Type: application/json' \
+--header 'Accept: application/json' \
+--header 'Authorization: ApiKey ' \
+--data '{
+ "name": "workflowIdentifier",
+ "to": ["subscriberId"],
+ "payload": {},
+ "overrides": {
+ "email": {
+ "customData": {
+ "templateId": 1,
+ "templateParams": {
+ "total": "$ 239.85",
+ "items": [
+ {
+ "text": "New Line Sneakers",
+ "image": "https://marketing-image-production.s3.amazonaws.com/uploads/8dda1131320a6d978b515cc04ed479df259a458d5d45d58b6b381cae0bf9588113e80ef912f69e8c4cc1ef1a0297e8eefdb7b270064cc046b79a44e21b811802.png",
+ "price": "$ 79.95"
+ },
+ {
+ "text": "Old Line Sneakers rlfjrjrh4hr4rh4",
+ "image": "https://marketing-image-production.s3.amazonaws.com/uploads/3629f54390ead663d4eb7c53702e492de63299d7c5f7239efdc693b09b9b28c82c924225dcd8dcb65732d5ca7b7b753c5f17e056405bbd4596e4e63a96ae5018.png",
+ "price": "$ 79.95"
+ }
+ ],
+ "receipt": true,
+ "name": "Sample Name",
+ "address01": "1234 Fake St.",
+ "address02": "Apt. 123",
+ "city": "Place",
+ "state": "CO",
+ "zip": "80202"
+ }
+ }
+ }
+ }
+}'
+```
+
+
+
diff --git a/integrations/providers/email/sparkpost.mdx b/integrations/providers/email/sparkpost.mdx
new file mode 100644
index 000000000..9b7e503bb
--- /dev/null
+++ b/integrations/providers/email/sparkpost.mdx
@@ -0,0 +1,42 @@
+---
+title: "Sparkpost"
+description: "Learn how to use the Sparkpost provider to send email notifications using Novu"
+---
+
+You can use the [SparkPost](https://messagebird.com/email/cloud-sending) provider to send transactional emails to your customers using the Novu Platform with a single API.
+
+# Getting Started
+
+To use the SparkPost provider in the email channel, you will need to create a SparkPost account and add your API key to the SparkPost integration on the Novu platform.
+
+# Generating an API Key
+
+To generate a new API key in SparkPost, you can follow these steps:
+
+- [Sign up](https://app.sparkpost.com/join) or [Log in](https://app.sparkpost.com/auth) to your SparkPost account.
+ > During sign up, note that SparkPost is available in multiple regions. "SparkPost" refers to the SparkPost service hosted in North America. "SparkPost EU" refers to the SparkPost service hosted in Western Europe. An account created with SparkPost cannot be used with SparkPost EU, and vice-versa. You may use accounts in both regions.
+ >
+ > ~Â *[SparkPost Documentation](https://support.sparkpost.com/docs/getting-started/getting-started-sparkpost/)*
+- Click on the **Configuration** link on the navbar, and then click the "API Keys" link that pops up from the available options.
+- On the [API Keys](https://app.sparkpost.com/account/api-keys) page, click the **Create API Key** button.
+- Give the API key a name and click on the **Create API key** button.
+- Copy the generated API Key.
+
+# Authenticating your Sender Identity
+
+Before you can send emails on a large scale, you will need to authenticate your Sender Identity.
+
+SparkPost allows you to authenticate your sender identity using [Sending Domains](https://app.sparkpost.com/domains/list/sending).
+
+# Creating a SparkPost integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sparkpost) page on Novu.
+- Click on Add a Provider.
+- Select SparkPost service.
+- Enter your SparkPost API Key.
+- Fill in the `From email address` field using the authenticated email from the previous step.
+- Fill in the `Sender's name`.
+- Toggle the `eu` switch to true if you're in Western Europe
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using SparkPost in Novu.
diff --git a/integrations/providers/email/webhook.mdx b/integrations/providers/email/webhook.mdx
new file mode 100644
index 000000000..f51c4b4b8
--- /dev/null
+++ b/integrations/providers/email/webhook.mdx
@@ -0,0 +1,23 @@
+---
+title: "Email Webhook"
+description: "Learn how to use the Email Webhook provider to send email notifications using Novu"
+---
+
+[Email Webhooks](https://www.socketlabs.com/blog/what-is-a-webhook/#:~:text=Email%20webhooks%20are%20an%20extremely,%2C%20successful%20messages%2C%20and%20bounces.) are an extremely flexible way for developers to monitor the health of their mail stream in real time
+
+# Getting Started
+
+First go to [Email Settings](https://dashboard-v2.novu.co/settings/email?utm_campaign=docs-webhook) in Settings menu to configure Email Webhook.
+
+# Creating the Email Webhook integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-webhook) page on Novu.
+- Click the "Add a provider" button.
+- Select Email Webhook service
+- Click `Next`
+- Choose your preferred deployment environment: `Development` or `Production`. Then Click the `Create` button.
+- Add `Webhook URL` & `Secret Hmac Key` to sign off the email
+- Finally add `From email address` & `Sender name` to identify email sender
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using Email Webhook in Novu.
diff --git a/integrations/providers/email/writing-email-template.mdx b/integrations/providers/email/writing-email-template.mdx
new file mode 100644
index 000000000..3e34d5225
--- /dev/null
+++ b/integrations/providers/email/writing-email-template.mdx
@@ -0,0 +1,78 @@
+---
+title: "Writing Email Template"
+sidebarTitle: "Writing Email Template"
+description: "Learn how to write an email template in Novu. This document will guide you through the process of creating an email template using the Novu email editor, all supported blocks and how to use them"
+icon: "file-pen"
+---
+
+## Email Editor
+
+The Email Editor is a `WYSIWYG` editor that allows you to create and edit email templates. It has two fields: `Subject` and `Body`.
+
+
+
+
+
+- **Subject** - Title of the email. It supports variables and can be customized based on the subscriber properties and payload variables.
+- **Body** - Main content of the email. It is made of blocks.
+
+## Email Editor Blocks
+
+Email editor body is made of blocks. A block can be added by clicking on the plus icon on the top left corner of the editor or by adding a forward slash `/`. In both the cases, a popover will appear with the list of supported blocks. Click on the desired block to add it to the editor. Menu option besides plus (+) icon can be used to **duplicate** or **delete** the block.
+
+
+
+
+
+The Email Editor supports the following blocks:
+
+- **Text** - Regular text
+- **Heading 1** - Large heading (H1)
+- **Heading 2** - Medium heading (H2)
+- **Heading 3** - Small heading (H3)
+- **Bullet List** - Bullet list (bullet points like âą)
+- **Numbered List** - Numbered list (numeric digits like 1,2,3)
+- **Image** - Full widh image with absolute url, image position can be customized
+- **Section** - Create a section to group content together
+- **Column** - Creates columns to group content together, useful for responsive design
+- **Divider** - Separates the content, adds a line to highlight the separation
+- **Spacer** - Spacer to add space between two blocks (available in sm, lg and xl sizes)
+- **Button** - Call to action button to link to a page or url (can be customised with text, url, color and size and background color)
+- **Hard Break** - Adds a line break
+- **Blockquote** - Adds a blockquote
+- **Repeat** - Can be used for interation on array of data
+- **Show** - Can be used to conditionally show content based on a condition, use eye icon to toggle the visibility of the content
+
+### Repeat Block
+
+`Repeat` block is synonym with the javascript language `for` loop. It can be used to iterate over an array of data and render a block for each item in the array. Use + icon or / to add a `Repeat` block. Checkout the below video on how to use `Repeat` block
+
+
+
+In above video:
+- `{{payload.order.items}}` is array of items in the order and can be used to iterate over the items
+
+then each item in the iteration has following properties:
+- `{{payload.order.items.name}}` is the name of the item
+- `{{payload.order.items.price}}` is the price of the item
+
+
+### Show Block
+
+Show block can be used to conditionally show content based on a condition. Use the eye icon to toggle the visibility of the content. Few components supports eye icon. Conditions could be based on subscribr properties, payload variables.
+
+
+
+
+
+In above example, if subscriber has `showTracking` field set to `true` in custom `data` attribute, then the `Track your order` button will be shown in the email sent to the subscriber. Similarly, paylaod variables can be used to conditionally show the content.
+
+
diff --git a/integrations/providers/in-app/adding-in-app.mdx b/integrations/providers/in-app/adding-in-app.mdx
new file mode 100644
index 000000000..900a3ba12
--- /dev/null
+++ b/integrations/providers/in-app/adding-in-app.mdx
@@ -0,0 +1,45 @@
+---
+title: "Adding In-App Channel"
+sidebarTitle: "Adding In-App Channel"
+description: "Learn how to add the In-App channel to your application"
+icon: "circle-plus"
+---
+
+The In-App channel allows you to display notifications, messages, and other content directly within your application's interface.
+
+
+
+
+
+By default, the In-App channel is enabled. If it is disabled, you will not be able to send notifications to this channel.
+
+
+1. Go to the Novu Dashboard and click "Integrations" on the left sidebar
+2. Click "Channels" on the left sidebar
+3. Enable the In-App channel
+
+
+
+ 1. Go to the Novu Dashboard and click "Workflows" on the left sidebar
+2. Click **"Add a Workflow"** button
+3. Select "In-App" as the channel
+
+
+Novuâs server-side SDKs streamline the integration of Novuâs REST APIs, eliminating boilerplate code and reducing development effort when adding Novu to your server-side application.
+
+
+
+
+
+
+
+
+Novu's client-side SDKs simplify integration into your applications, offering powerful tools to customize and scale in-app notification experiences effortlessly, all while supporting multi-channel capabilities.
+
+
+
+
+
+
+
+
diff --git a/integrations/providers/in-app/media-assets/component_composition.png b/integrations/providers/in-app/media-assets/component_composition.png
new file mode 100644
index 000000000..8b88dac20
Binary files /dev/null and b/integrations/providers/in-app/media-assets/component_composition.png differ
diff --git a/integrations/providers/in-app/overview.mdx b/integrations/providers/in-app/overview.mdx
new file mode 100644
index 000000000..8b2d1ba74
--- /dev/null
+++ b/integrations/providers/in-app/overview.mdx
@@ -0,0 +1,53 @@
+---
+title: "In-App Notification Integration"
+sidebarTitle: "Overview"
+description: "Learn how to configure the in-app channel"
+icon: "circle-info"
+---
+
+Novu extends beyond traditional notification channels like email, SMS, and push by providing a robust framework for in-app notifications. With Novu, you can build reliable, stateful systems that integrate seamlessly into your applications.
+
+The inbox component and SDKs give you tools to create fully customizable, in-app notification experiences, including:
+
+- Inboxes
+- Floating feeds
+- Toasts
+- Banners
+
+These components are designed to integrate cleanly into your architecture while being flexible enough to adapt to any design system or interaction model.
+
+
+
+## Key features
+
+- **Real-time updates:** Use WebSockets to push notifications instantly
+- **Stateful Management:** Handle read/unread states, archiving, and user interaction seamlessly
+- **Developer-first customization:** Components are built to be modified at every layer, from UI to behavior
+- **Multi-platform support:** Consistent APIs across web and mobile SDKs
+- **Integration-ready:** Plug into your existing backend with minimal effort
+- **Actionable notifications:** Add clickable actions to notifications to drive user engagement
+
+## Common use cases
+
+- **User activity notifications:** Display updates like mentions, comments, or approvals in real time
+- **System alerts:** Notify users of status changes, outages, or important updates directly in your application
+- **Workflow tracking:** Keep users informed on task progress, deadlines, or assigned work
+- **Collaboration tools:** Enable notification feeds for shared projects or team activities
+
+## Available SDKs
+
+
+
+ Build notification interfaces with Novu's prebuilt UI components and React hooks for web applications
+
+
+ Build fully custom notification UIs for iOS and Android apps using Novu's React Native hooks SDK
+
+
+ A lightweight, standalone package for building custom notification interfaces with essential API methods and real-time WebSocket connections
+
+
+
+## Try It Out
+
+Explore the [Inbox Playground â](https://inbox.novu.co)
\ No newline at end of file
diff --git a/integrations/providers/push/adding-push.mdx b/integrations/providers/push/adding-push.mdx
new file mode 100644
index 000000000..6399f84cf
--- /dev/null
+++ b/integrations/providers/push/adding-push.mdx
@@ -0,0 +1,148 @@
+---
+title: "Adding Push Channel"
+sidebarTitle: "Adding Push Channel"
+description: "Learn how to add the push channel to your application"
+icon: "circle-plus"
+---
+
+import { MissingProvider } from "/snippets/missing-provider.mdx";
+
+
+
+ To send push notifications using Novu, you need to set up a provider in the integration store.
+
+ 1. Go to the Novu Dashboard and click **"Integrations"** on the left sidebar
+ 2. Locate your desired push provider and configure it with the required credentials
+ 3. Ensure the provider is enabled
+
+
+
+
+ Add push notifications to a new or existing workflow.
+
+ 1. Navigate to the **"Workflows"** section in the Novu Dashboard
+ 2. Click **"Add a Workflow"** or select an existing workflow
+ 3. Add a step and choose **"Push"** as the channel
+ 4. Configure the push step by adding static or dynamic content such as title, message body, and variables
+
+
+
+
+ For push notifications to reach the right subscribers, store provider-specific device tokens or identifiers.
+
+ - Follow your providerâs documentation to obtain device tokens
+ - Use Novuâs subscriber management features to add these tokens to the subscriber profiles
+
+
+
+
+ Before triggering workflows, ensure your provider configuration is complete.
+
+ - Refer to your push provider's documentation to confirm all required steps are correctly set up
+ - Double-check any provider-specific settings in the integration store
+
+
+
+
+ Test the push workflow to ensure everything is working as expected
+
+ 1. Go to the **"Workflows"** section in the Novu Dashboard and select your configured workflow
+ 2. Use the **"Test Workflow"** option
+ 3. Verify the push notification delivery in Novu Logs or the push providerâs dashboard
+
+
+
+
+
+## Supported providers
+
+- [Firebase Cloud Messaging (FCM)](/integrations/providers/push/fcm)
+- [Expo push](/integrations/providers/push/expo-push)
+- [Apple push notification Service](/integrations/providers/push/apns)
+- [OneSignal](/integrations/providers/push/onesignal)
+- [Pushpad](/integrations/providers/push/pushpad)
+- [Push webhook](/integrations/providers/push/push-webhook)
+
+Novu supports multiple active providers for push channel.
+
+
+
+
+
+## Managing push device tokens
+
+To send push notifications to subscribers, you need to store device tokens or identifiers in subscriber profiles. These tokens are unique identifiers that help push notification providers deliver messages to the correct devices. Each provider has its own method for obtaining and storing device tokens.
+
+Novu offers to ways of keeping your device tokens in sync with subscriber profiles:
+
+- Just-in-time: Pass device tokens in the payload when triggering a workflow. Novu will automatically update subscriber profiles with the new device tokens.
+- Manual: Update subscriber profiles with device tokens using the Novu set credentials API.
+
+### Just-in-time
+
+When triggering a workflow, you can pass the `channels` array on the subscriber object with the device tokens for the push provider of your choice. Here is an example with fcm:
+
+```typescript
+novu.trigger("workflow-id", {
+ to: {
+ subscriberId: "subscriber-id",
+ channels: [
+ {
+ providerId: "fcm",
+ credentials: {
+ deviceTokens: ["token-1", "token-2"],
+ },
+ },
+ ],
+ },
+ payload: {},
+});
+```
+
+### Manual
+
+Use the Novu Set Credentials API to update subscriber profiles with device tokens. You can read more about the API in the [API Reference](/api-reference/subscribers/update-subscriber-credentials) or the [FCM Example](/integrations/providers/push/fcm#setting-device-token)
+
+## Frequently Asked Questions
+
+### How to remove one device token from subscriber credentials?
+
+To remove a device token from subscriber credentials, you need to get the current device tokens from subscriber credentials, remove all `deviceTokens`, remove the token you want to remove and then update the subscriber credentials with new device tokens.
+
+
+
+```ts
+import { Novu, PushProviderIdEnum } from '@novu/node';
+
+const novu = new Novu('');
+
+// fetch subscriber details
+const subscriber = await novu.subscribers.get('subscriberId');
+
+// get current device tokens from subscriber credentials for the provider
+const currentDeviceTokens = subsciber.data.data.channels.find(
+// \_integrationId can also be checked in place of providerId ;
+(channel) => channel.providerId === PushProviderIdEnum.FCM,
+).credentials.deviceTokens;
+
+// remove all device tokens
+await this.novu.subscribers.setCredentials(
+'subscriberId',
+PushProviderIdEnum.FCM,
+{ deviceTokens: [] },
+);
+
+// remove the token you want to remove
+const newDeviceTokens = currentDeviceTokens.filter(
+(token) => token !== 'token-to-be-removed',
+);
+
+// update subscriber credentials with new device tokens
+await this.novu.subscribers.setCredentials(
+'subscriberId',
+PushProviderIdEnum.FCM,
+{ deviceTokens: newDeviceTokens },
+);
+```
+
+
diff --git a/integrations/providers/push/apns.mdx b/integrations/providers/push/apns.mdx
new file mode 100644
index 000000000..93bfb0ceb
--- /dev/null
+++ b/integrations/providers/push/apns.mdx
@@ -0,0 +1,124 @@
+---
+title: "Apple Push Notification Service (APNS)"
+sidebarTitle: "APNS"
+description: "Learn how to use the Apple Push Notification Service (APNS) provider to send push notifications using Novu"
+---
+
+[Apple Push Notification Service](https://docs.expo.dev/push-notifications/overview/), as the name suggests, is a notification delivery service provided by Apple.
+
+Apple provides two authentication methods to make a secure connection to APNs. The first is Certificate-Based Authentication (using a .p12 certificate). The second is Token-Based Authentication (using a .p8 key). We'll make use of the **.p8** key.
+
+To enable APNS integration, you need to create an [Apple Developer](https://developer.apple.com/) account with an [Admin role](https://appstoreconnect.apple.com/access/users).
+
+To generate the p8 key for your account:
+
+1. Head over to **Certificates, Identifiers & Profiles > Keys**.
+2. Register a new key and give it a name.
+3. Enable the Apple Push Notifications service (APNs) checkbox by selecting it.
+4. Click the **Continue** button and on the next page, select **Register**.
+5. Download the **.p8** key file.
+
+You also need the following to connect to APNs:
+
+1. **Key ID**Â - This is a 10-character unique identifier for the authentication key. You can find it in the key details section of the newly created key in your Apple developer account.
+2. **Team ID**Â - This is available in your Apple developer account.
+3. **Bundle ID**Â - This is the ID of your app. You can find it in the app info section of your Apple developer account.
+
+The overrides field supports all [Notification payload](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification?language=objc) values, as shown below:
+
+```typescript
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+novu.trigger("", {
+ to: {
+ subscriberId: "",
+ },
+ payload: {
+ abc: "def", // If the notification is a data notification, the payload will be sent as the data
+ },
+ overrides: {
+ apns: {
+ payload: {
+ aps: {
+ notification: {
+ title: "Test",
+ body: "Test push",
+ },
+ data: {
+ key: "value",
+ },
+ },
+ },
+ },
+ },
+});
+```
+
+```typescript
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+novu.trigger("", {
+ to: {
+ subscriberId: "",
+ },
+ payload: {
+ key1: "val1",
+ key2: "val2", // If the notification is a data notification, the payload will be sent as the data
+ },
+ overrides: {
+ type: "data",
+ apns: {
+ headers: {
+ "apns-priority": "5",
+ },
+ payload: {
+ aps: {
+ alert: {
+ "loc-key": "GAME_PLAY_REQUEST_FORMAT",
+ "loc-args": ["Shelly", "Rick"],
+ },
+ sound: "demo.wav",
+ },
+ },
+ },
+ },
+});
+```
+
+Before triggering the notification to a subscriber(user) with push as a step in the workflow, make sure you have added the subscriber's device token as follows:
+
+
+
+```javaScript
+import {
+ Novu,
+ ChatProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+await novu.subscribers.setCredentials('subscriberId', PushProviderIdEnum.APNS, {
+ deviceTokens: ['token1', 'token2'],
+});
+```
+
+
+```bash
+curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+-d '{
+ "providerId": "apns",
+ "deviceTokens": ["token1", "token2"],
+ "integrationIdentifier": "apns-MnGLxp8uy"
+}'
+```
+
+
+
+Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
diff --git a/integrations/providers/push/expo-push.mdx b/integrations/providers/push/expo-push.mdx
new file mode 100644
index 000000000..023731c88
--- /dev/null
+++ b/integrations/providers/push/expo-push.mdx
@@ -0,0 +1,59 @@
+---
+title: "Expo Push"
+description: "Learn how to use the Expo push provider to send push notifications using Novu"
+---
+
+[Expo Push](https://docs.expo.dev/push-notifications/overview/)Â is a notification delivery service provided by Expo.
+
+To enable Expo Push integration, you need to create an [Expo Application Services (EAS)](https://expo.dev/)account and generate an access token in the EAS dashboard.
+
+The overrides field supports all [Message Request](https://docs.expo.dev/push-notifications/sending-notifications/#message-request-format) values. An example of the same follows:
+
+```typescript
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+novu.trigger("", {
+ to: {
+ subscriberId: "",
+ },
+ payload: {
+ abc: "def",
+ },
+});
+```
+
+Before triggering the notification to a subscriber(user) with push as a step in the workflow, make sure you have added the subscriber's device token as follows:
+
+
+
+```javaScript
+import {
+ Novu,PushProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+await novu.subscribers.setCredentials('subscriberId', PushProviderIdEnum.EXPO, {
+ deviceTokens: ['token1', 'token2'],
+});
+```
+
+
+```bash
+curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+-d '{
+ "providerId": "expo",
+ "deviceTokens": ["token1", "token2"],
+ "integrationIdentifier": "expo-MnGLxp8uy"
+}'
+```
+
+
+
+
+Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
diff --git a/integrations/providers/push/fcm.mdx b/integrations/providers/push/fcm.mdx
new file mode 100644
index 000000000..4f7d6b8e9
--- /dev/null
+++ b/integrations/providers/push/fcm.mdx
@@ -0,0 +1,221 @@
+---
+title: "Firebase Cloud Messaging (FCM)"
+sidebarTitle: "FCM"
+description: "Learn how to use the Firebase Cloud Messaging (FCM) provider to send push notifications using Novu"
+---
+
+[Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging)Â is a free notification delivery service provided by Google Firebase.
+
+To enable the FCM integration, you need to get your service account key from the [Firebase Console](https://console.firebase.google.com/).
+
+## Generating a Service Account Key JSON
+
+To acquire the account key JSON file for your service account
+
+1. Select your project, and click the gear icon on the top of the sidebar.
+2. Head to project settings.
+3. Navigate to the service account tab.
+4. Click **Generate New Private Key,** then confirm by clicking **Generate Key.**
+5. Clicking **Generate Key** downloads the JSON file.
+
+After that, paste the entire JSON file content in the Service Account field of the FCM provider in the integration store on Novuâs web dashboard.
+
+Make sure your service account json content contains these fields
+
+```json
+{
+ "type": "service_account",
+ "project_id": "PROJECT_ID",
+ "private_key_id": "PRIVATE_KEY_ID",
+ "private_key": "PRIVATE_KEY",
+ "client_email": "FIREBASE_ADMIN_SDK_EMAIL",
+ "client_id": "CLIENT_ID",
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+ "token_uri": "https://oauth2.googleapis.com/token",
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+ "client_x509_cert_url": "CLIENT_X509_CERT_URL"
+}
+```
+
+## FCM Overrides
+
+The overrides field supports apns, android, webpush and fcmOptions overrides
+
+| Override Field | Type / Interface | Link |
+| -------------- | ---------------- | -------------------------------------------------------------------------------------------- |
+| android | AndroidConfig | https://firebase.google.com/docs/reference/admin/node/firebase-admin.messaging.androidconfig |
+| apns | ApnsConfig | https://firebase.google.com/docs/reference/admin/node/firebase-admin.messaging.apnsconfig |
+| webPush | WebpushConfig | https://firebase.google.com/docs/reference/admin/node/firebase-admin.messaging.webpushconfig |
+| fcmOptions | FcmOptions | https://firebase.google.com/docs/reference/admin/node/firebase-admin.messaging.fcmoptions |
+
+## Setting Device Token
+
+Before triggering the notification to a subscriber(user) with push as a step in the workflow, make sure you have added the subscriber's device token as follows:
+
+
+
+```javaScript
+import {
+ Novu,
+ PushProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+await novu.subscribers.setCredentials(
+ 'subscriberId',
+ PushProviderIdEnum.FCM, {
+ deviceTokens: ['token1', 'token2']
+ },
+ 'fcm-MnGLxp8uy'
+);
+```
+
+
+
+```bash
+curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+-d '{
+ "providerId": "fcm",
+ "credentials": {
+ "deviceTokens" : [
+ "token1",
+ "token2"
+ ]
+ },
+ "integrationIdentifier": "fcm-MnGLxp8uy"
+}'
+```
+
+
+
+
+Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
+
+## SDK Trigger Example
+
+```typescript
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+novu.trigger("", {
+ to: {
+ subscriberId: "",
+ },
+ payload: {
+ abc: "def", // If the notification is a data notification, the payload will be sent as the data
+ },
+ overrides: {
+ fcm: {
+ // type: 'data' => will turn this into an FCM data notification, where the payload is sent as a data notification. If the type is not set, you can use the "data" override to send notification messages with optional data payload
+ type: "data",
+
+ // URL of an image to be displayed in the notification.
+ imageUrl: "https://domain.com/image.png",
+
+ // If type is not set, you can use the "data" override to send notification messages with optional data payload
+ data: {
+ key: "value",
+ },
+
+ // Check FCM Overrides section above for these types
+ android: {},
+ apns: {},
+ webPush: {},
+ fcmOptions: {},
+ },
+ },
+});
+```
+
+Device/notification identifiers can be set by using [setCredentials](#set-device-token)Â
+
+ Novu uses FCM version V1
+
+## Relative Link in Webpush
+
+Suppose youâre using the Firebase (FCM) provider to send push notifications to web browsers via Novu and want users to be returned to the website after clicking the notification.
+
+In that case, you must use the `link` property with a relative URL.
+
+
+
+
+```javascript
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+novu.trigger("", {
+ to: {
+ subscriberId: "",
+ },
+ payload: {
+ abc: "def", // If the notification is a data notification, the payload will be sent as the data
+ },
+ overrides: {
+ fcm: {
+ webPush: {
+ fcmOptions: {
+ link: "/foo",
+ },
+ },
+ },
+ },
+});
+```
+
+
+
+ ```bash
+ curl --location --request POST 'https://url.to.our.selfhosted.novu' \
+ --header 'Authorization: ApiKey KEY' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "workflow-name",
+ "to": {
+ ...
+ },
+ "overrides": {
+ "fcm": {
+ "webPush": {
+ "fcm_options": {
+ "link": "/foo"
+ }
+ }
+ }
+ }
+ }'
+ ```
+
+
+
+## FCM Cost
+
+As per Firebase [pricing](https://firebase.google.com/pricing), **Cloud Messaging** product is free of cost to use. If other Firebase products are used, the cost will be charged as per the product.
+
+## FAQs
+
+
+
+ You may come across an error like so:
+
+ ""Sending message failed due to "The registration token is not a valid FCM registration token""".
+
+ This error happens because of invalid or stale token. The fix for this is to remove old tokens, generate a new token and save it into user subscribers.
+
+
+
+ Try to generate a new token after clearing device cache and retry with this fresh token.
+
+
+ This error occurs when your token is no longer valid. To fix this, generate a new token and use it.
+
+
+ This error occurs if the fcm integration is active but subscriber is missing from the fcm credentials (deviceTokens). The credentials (deviceTokens) for the subscriber needs to be set.
+
+
diff --git a/integrations/providers/push/onesignal.mdx b/integrations/providers/push/onesignal.mdx
new file mode 100644
index 000000000..4a0ce50fa
--- /dev/null
+++ b/integrations/providers/push/onesignal.mdx
@@ -0,0 +1,87 @@
+---
+title: "Onesignal"
+description: "Learn how to use the Onesignal provider to send push notifications using Novu"
+---
+
+[OneSignal](https://onesignal.com/) is a paid push notification service that supports sending messages via both [Apple Push Notification Service](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server) (APNs) as well as [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging) (FCM).
+
+To configure the OneSignal integration, you will need an active account which has credentials for APNs, FCM or both, and have access to the `OneSignal App ID` and `Rest API Key` available via your [application's settings page](https://documentation.onesignal.com/docs/keys-and-ids).
+
+## Setting the Device Token
+
+Once OneSignal has been configured with your credentials for APNs/FCM, and the OneSignal SDK has been [set up and configured](https://documentation.onesignal.com/docs/onboarding-with-onesignal#step-1-setup-onesignal-sdk) for your application, your users will begin to be automatically assigned a unique OneSignal [player_id](https://documentation.onesignal.com/docs/users#player-id) identifier by the SDK.
+
+This identifier allows targeting your user when sending push notifications without having to retrieve the specific Android or iOS device tokens - which are managed by OneSignal.
+
+In order to target the OneSignal user from Novu, you must register the OneSignal `player_id`as the `deviceToken` for your Novu subscriber. This value can be retrieved via the [OneSignal SDK](https://documentation.onesignal.com/docs/users-and-devices#finding-users) for your platform.
+
+Once you have the user's `player_id` value, the `deviceToken` for your Novu subscriber can be set via:
+
+
+
+```javaScript
+import {
+ Novu,
+ ChatProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+await novu.subscribers.setCredentials('subscriberId', PushProviderIdEnum.OneSignal, {
+ // Your user's unique 'player_id' from OneSignal
+ deviceTokens: [ 'ad0452ca-3ca7-43b5-bf9b-fa93fd322035' ],
+});
+```
+
+
+```bash
+curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+-d '{
+ "providerId": "one-signal",
+ "deviceTokens": ["ad0452ca-3ca7-43b5-bf9b-fa93fd322035"],
+ "integrationIdentifier": "one-signal-MnGLxp8uy"
+}'
+```
+
+
+
+
+Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
+
+## SDK Trigger Example
+
+```typescript
+novu.trigger("", {
+ to: {
+ subscriberId: "",
+ },
+ payload: {
+ abc: "def", // If the notification is a data notification, the payload will be sent as the data
+ },
+ overrides: {
+ subtitle: "This is subtitle value",
+ mutableContent: "Mutable content value",
+ // for android notification categories
+ channelId: "category_id",
+ // for ios notification categories
+ categoryId: "Category id",
+ // same value is used for all sizes and browsers
+ icon: "https://image.com/icon.png",
+ // used for both android and ios
+ sound: "sound file url"
+ }
+});
+```
+
+Device/notification identifiers can be set by using [setCredentials](/integrations/providers/push/fcm#setting-device-token)
+
+## Using external user id
+
+By default, Novu uses player id to send notifications, `External ID` option can be selected in the onesignal integration settings. If `External ID` option is selected, `deviceTokens` stored in subscriber credentials for onesignal provider, will be used as external user ids.
+
+
+
+
\ No newline at end of file
diff --git a/integrations/providers/push/overview.mdx b/integrations/providers/push/overview.mdx
new file mode 100644
index 000000000..3ff6f434a
--- /dev/null
+++ b/integrations/providers/push/overview.mdx
@@ -0,0 +1,133 @@
+---
+title: "Push Providers Integration"
+sidebarTitle: "Overview"
+description: "Learn how to configure the Push channel"
+icon: "circle-info"
+---
+import { MissingProvider } from "/snippets/missing-provider.mdx";
+
+Push notifications are a powerful way to deliver real-time updates, reminders, and personalized messages to your users across mobile and web platforms.
+Whether it's a promotional alert, a system notification, or a critical update, push notifications are key to enhancing engagement and retention.
+
+Novu simplifies the process by offering a unified API that supports multiple push notification providers, enabling reliable and efficient message delivery.
+
+## Key Features
+
+- **Multi-Provider Support**: Integrate with providers like Firebase Cloud Messaging (FCM), OneSignal, or Apple Push Notification Service (APNS)
+- **Unified Delivery**: Streamline your push notifications with a single API for mobile and web platforms
+- **Dynamic Content**: Customize notifications with variables for personalized user experiences
+- **Device Management**: Keep subscriber device tokens in sync using just-in-time or manual updates
+
+## Common Use Cases
+- **Transactional Notifications**: Payment updates, delivery alerts, appointment reminders
+- **Engagement Notifications**: Promotions, re-engagement campaigns, social media interactions
+- **System Alerts**: Security warnings, downtime alerts, account activity updates
+
+
+## How to send push notifications
+To send a push notification to subscribers (users) using Novu:
+
+- Add a push channel provider in integration store
+- Add push channel as a step in existing or new workflow.
+- Add static or dynamic content using variables in push step fields
+- Store provider specific device tokens/identifiers in subscriber profile. Read provider specific documentation on how to obtain and store device tokens.
+- Make sure all provider specific steps are configured properly before triggering workflow. Read provider related documentation for all required steps.
+- Trigger the workflow.
+
+## Supported providers
+
+- [Firebase Cloud Messaging (FCM)](/channels-and-providers/push/fcm)
+- [Expo Push](/channels-and-providers/push/expo-push)
+- [Apple Push Notification Service](/channels-and-providers/push/apns)
+- [OneSignal](/channels-and-providers/push/onesignal)
+- [Pushpad](/channels-and-providers/push/pushpad)
+- [Push Webhook](/channels-and-providers/push/push-webhook)
+
+Novu supports multiple active providers for push channel.
+
+## Managing push device tokens
+
+To send push notifications to subscribers, you need to store device tokens or identifiers in subscriber profiles. These tokens are unique identifiers that help push notification providers deliver messages to the correct devices. Each provider has its own method for obtaining and storing device tokens.
+
+Novu offers to ways of keeping your device tokens in sync with subscriber profiles:
+
+- Just-in-time: Pass device tokens in the payload when triggering a workflow. Novu will automatically update subscriber profiles with the new device tokens.
+- Manual: Update subscriber profiles with device tokens using the Novu Set Credentials API.
+
+### Just-in-time
+
+When triggering a workflow, you can pass the `channels` array on the subscriber object with the device tokens for the push provider of your choice. Here is an example with fcm:
+
+```typescript
+novu.trigger("workflow-id", {
+ to: {
+ subscriberId: "subscriber-id",
+ channels: [
+ {
+ providerId: "fcm",
+ credentials: {
+ deviceTokens: ["token-1", "token-2"],
+ },
+ },
+ ],
+ },
+ payload: {},
+});
+```
+
+### Manual
+
+Use the Novu Set Credentials API to update subscriber profiles with device tokens. You can read more about the API in the [API Reference](/api-reference/subscribers/update-subscriber-credentials) or the [FCM Example](/integrations/providers/push/fcm#setting-device-token)
+
+## Frequently Asked Questions
+
+### How to remove one device token from subscriber credentials?
+
+To remove a device token from subscriber credentials, you need to get the current device tokens from subscriber credentials, remove all deviceTokens, remove the token you want to remove and then update the subscriber credentials with new device tokens.
+
+
+
+```ts
+import {
+ Novu,
+ PushProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu('');
+
+// fetch subscriber details
+const subscriber = await novu.subscribers.get('subscriberId');
+
+// get current device tokens from subscriber credentials for the provider
+const currentDeviceTokens = subsciber.data.data.channels.find(
+ // _integrationId can also be checked in place of providerId ;
+ (channel) => channel.providerId === PushProviderIdEnum.FCM,
+).credentials.deviceTokens;
+
+// remove all device tokens
+await this.novu.subscribers.setCredentials(
+ 'subscriberId',
+ PushProviderIdEnum.FCM, {
+ deviceTokens: []
+ },
+);
+
+// remove the token you want to remove
+const newDeviceTokens = currentDeviceTokens.filter(
+ (token) => token !== 'token-to-be-removed',
+);
+
+// update subscriber credentials with new device tokens
+await this.novu.subscribers.setCredentials(
+ 'subscriberId',
+ PushProviderIdEnum.FCM, {
+ deviceTokens: newDeviceTokens
+ },
+);
+```
+
+
+
+
+
+
diff --git a/integrations/providers/push/push-webhook.mdx b/integrations/providers/push/push-webhook.mdx
new file mode 100644
index 000000000..d9b6961f6
--- /dev/null
+++ b/integrations/providers/push/push-webhook.mdx
@@ -0,0 +1,137 @@
+---
+title: "Push Webhook"
+description: "Learn how to use the Push Webhook provider to send notifications using Novu"
+---
+
+Push Webhook provider is a bit different different from other push providers as it does not depend on other third party services.
+Users can use their own api url as webhook url and novu will make a post request on that webhook url.
+
+## Steps To Configure
+
+1. Go to [integration store](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-push-webhook) and click on `Add a provider` button. Choose `Push` channel and then `Push Webhook` provider.
+2. Enter your Webhook URL. For quick testing use [this](https://webhook.site/) website.
+3. Enter Secret Hmac Key. Novu will use this secret hmac key to encrypt the data using `HMAC SHA256` algorithm and send the hash as value of `x-novu-signature` header. User can use `x-novu-signature` header to test authenticity of the request. Read more [here](#checking-authenticity)
+4. Click on the update button.
+5. Update the subscriber credentials using SDK or API. Read more [here](#set-device-token)
+
+Your webhook url should accept `POST` request.
+
+## Set Device Token
+
+This step is a mandatory step. Other push providers have third party dependencies where a device token can be generated. But in case of push webhook provider, there is no any way to generate device token. Any random string can be used as device token.
+
+
+
+```javaScript
+import {
+ Novu,
+ ChatProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+// PushProviderIdEnum.PushWebhook = push-webhook
+await novu.subscribers.setCredentials('subscriberId', PushProviderIdEnum.PushWebhook, {
+ deviceTokens: ['ANY_RANDOM_STRING'],
+});
+```
+
+
+```bash
+curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+-d '{
+ "providerId": "push-webhook",
+ "deviceTokens": ['ANY_RANDOM_STRING'],
+ "integrationIdentifier": "push-webhook-MnGLxp8uy"
+}'
+```
+
+
+
+
+Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
+
+## Example paylod sent by novu to webhook url
+
+```json
+{
+ "target": ["subscriber-token-for-push-webhook-provider"],
+ "title": "Push Webhook message title",
+ "content": "push Webhook content body",
+ "overrides": {
+ "data": {
+ "custom_message": "this is custom message from payload push webhook demo"
+ }
+ },
+ "payload": {
+ "custom_message": "this is custom message from payload push webhook demo",
+ "__source": "test-workflow",
+ "subscriber": {
+ // subscriber fields
+ "_id": "65c0d71c0959a38e8857b131",
+ "_organizationId": "organizationId",
+ "_environmentId": "environmentId",
+ "firstName": "Pawan",
+ "lastName": "Jain",
+ "phone": "+123456789",
+ "subscriberId": "push-webhook-demo-subscriber-id",
+ "email": "pawan+push+web+hook+demo@domain.com",
+ "channels": [
+ {
+ "credentials": {
+ "deviceTokens": ["subscriber-token-for-push-webhook-provider"]
+ },
+ "_integrationId": "integrationId",
+ "providerId": "push-webhook"
+ }
+ ],
+ "data": {
+ // custom data field of subscriber
+ "isDeveloper": "true"
+ },
+ "deleted": false,
+ "createdAt": "2024-02-05T12:39:56.379Z",
+ "updatedAt": "2024-02-05T12:54:08.684Z",
+ "__v": 0,
+ "id": "65c0d71c0959a38e8857b131"
+ },
+ "step": {
+ // digest variables
+ "digest": false,
+ "events": [],
+ "total_count": 0
+ }
+ }
+}
+```
+
+## Checking Authenticity
+
+```typescript
+import crypto from "crypto"
+
+// secret key added in step 3
+const secretKey = "YOUR_HMAC_SECRET_KEY"
+
+// function to handle webhook url route request
+async acceptNovuPushWebHookRequest(request, response){
+
+ const payloadSentByNovu = request.body
+ const hmacHashSentByNovu = request.headers['x-novu-signature']
+
+ const actualHashValue = crypto
+ .createHmac('sha256', secretKey)
+ .update(payloadSentByNovu, 'utf-8')
+ .digest('hex');
+
+ if(hmacHashSentByNovu === actualHashValue){
+ // handle the notification
+ console.log("Request sent by Novu")
+ } else {
+ throw new Error("Not a valid request")
+ }
+}
+```
diff --git a/integrations/providers/push/pusher-beams.mdx b/integrations/providers/push/pusher-beams.mdx
new file mode 100644
index 000000000..d67e3fc24
--- /dev/null
+++ b/integrations/providers/push/pusher-beams.mdx
@@ -0,0 +1,69 @@
+---
+title: "Pusher Beams"
+description: "Learn how to use the Pusher Beams provider to send push notifications using Novu"
+---
+
+[Pusher Beams](https://pusher.com/beams/)Â is a cross-platform push notification API service provided by Pusher.
+
+To enable Pusher Beams integration, you need to create a Pusher Beams Instance and use both `Instance ID` and `Secret Key` from the Instance [dashboard](https://dashboard.pusher.com/beams/).
+
+## Setting the Device Token
+
+Once Pusher Beams instance has been created, and the Pusher Beams SDK has been [set up and configured](https://pusher.com/docs/beams/reference/all-libraries/) for your application, you can associate users with their devices using [Authenticated Users](https://pusher.com/docs/beams/guides/publish-to-specific-user/web/).
+
+This identifier allows targeting your user when sending push notifications without having to retrieve the specific Web, Android or iOS device tokens - which are managed by Pusher Beams.
+
+In order to target the Pusher Beams user from Novu, you must register the Pusher Beams Authenticated Users with their `userId` as the `deviceToken` for your Novu subscriber. This value can be retrieved via [getUserId()](https://pusher.com/docs/beams/reference/web/#getuserid) method from the SDK for your platform.
+
+Once you have the user's `userId` value, the `deviceToken` for your Novu subscriber can be set via:
+
+
+
+```javaScript
+import {
+ Novu,
+ ChatProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+await novu.subscribers.setCredentials('subscriberId', PushProviderIdEnum.PusherBeams, {
+ // Your user's unique 'userId' from Pusher Beams
+ deviceTokens: ['userId-from-pusher-beams'],
+});
+```
+
+
+```bash
+curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+-d '{
+ "providerId": "pusher-beams",
+ "deviceTokens": ['userId-from-pusher-beams'],
+ "integrationIdentifier": "pusher-beams-MnGLxp8uy"
+}'
+```
+
+
+
+
+Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
+
+## SDK Trigger Example
+
+```typescript
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+novu.trigger("", {
+ to: {
+ subscriberId: "",
+ },
+ payload: {
+ custom_data: "custom_data", // the payload will be sent as notification data object. Cannot contain the key âpusherâ
+ },
+});
+```
diff --git a/integrations/providers/push/pushpad.mdx b/integrations/providers/push/pushpad.mdx
new file mode 100644
index 000000000..265780b90
--- /dev/null
+++ b/integrations/providers/push/pushpad.mdx
@@ -0,0 +1,67 @@
+---
+title: "Pushpad"
+description: "Learn how to use the Pushpad provider to send web push notifications using Novu"
+---
+
+[Pushpad](https://pushpad.xyz) is a web push service that supports sending notifications to all major browsers (Chrome, Firefox, Edge, Safari, etc.) via FCM, Mozilla autopush, Windows Push Notification Services and Apple Push Notification service, with just one simple API.
+
+To configure the Pushpad integration, you will need an active account and you need to have a `Pushpad Auth Token` (from the [account settings](https://pushpad.xyz/access_tokens)) and the `Pushpad Project ID` (from the project settings).
+
+## Setting the Device Token
+
+Once Pushpad has been configured with your credentials and the Pushpad SDK has been [set up and installed](https://pushpad.xyz/docs/pushpad_pro_getting_started) on your website, you can [assign a user ID (uid)](https://pushpad.xyz/docs/identifying_users) to the push subscriptions.
+
+This identifier (`uid` or `user ID`) allows targeting a specific browser when sending push notifications.
+
+In order to target the Pushpad user from Novu, you must register the Pushpad `uid` as the `deviceToken` for your Novu subscriber. For example, if you invoked the [Pushpad JavaScript SDK](https://pushpad.xyz/docs/javascript_sdk_reference) with `pushpad('uid', 'user123')`, then `user123` is the user ID for that browser.
+
+Once you have the `uid` value, the `deviceToken` for your Novu subscriber can be set using this code:
+
+
+
+```javaScript
+import {
+ Novu,
+ ChatProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+await novu.subscribers.setCredentials('subscriberId', PushProviderIdEnum.Pushpad, {
+ // the user ID (uid) that you used for Pushpad
+ deviceTokens: ['user123'],
+});
+```
+
+
+```bash
+curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
+-H 'Content-Type: application/json' \
+-H 'Accept: application/json' \
+-H 'Authorization: ApiKey ' \
+-d '{
+ "providerId": "pushpad",
+ "deviceTokens": ['user123'],
+ "integrationIdentifier": "pushpad-MnGLxp8uy"
+}'
+```
+
+
+
+
+Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
+
+# SDK Trigger Example
+
+```typescript
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+novu.trigger("", {
+ to: {
+ subscriberId: "",
+ },
+ payload: {},
+});
+```
\ No newline at end of file
diff --git a/integrations/providers/sms/46elks.mdx b/integrations/providers/sms/46elks.mdx
new file mode 100644
index 000000000..3ad4df7d8
--- /dev/null
+++ b/integrations/providers/sms/46elks.mdx
@@ -0,0 +1,21 @@
+---
+title: "46elks"
+description: "Learn how to use the 46elks provider to send sms notifications using Novu"
+---
+
+You can use the [46elks](https://46elks.com/) provider to send SMS messages to your customers using the Novu platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the 46elks provider in the sms channel, you will need to create a 46elks account and add your `API Username` & `API Password` to the 46elks integration on the Novu platform.
+
+# Creating the 46elks integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-46elks) page on Novu.
+- Click the "Add a provider" button.
+- Select 46elks service
+- Click `Next`
+- Choose your preferred deployment environment: `Development` or `Production`. Then Click the `Create` button.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send SMS, MMS, using 46elks in Novu.
diff --git a/integrations/providers/sms/adding-sms.mdx b/integrations/providers/sms/adding-sms.mdx
new file mode 100644
index 000000000..7eba3c204
--- /dev/null
+++ b/integrations/providers/sms/adding-sms.mdx
@@ -0,0 +1,135 @@
+---
+title: "Adding SMS Channel"
+sidebarTitle: "Adding SMS Channel"
+description: "Learn how to add the SMS channel to your application"
+icon: "circle-plus"
+---
+
+import { MissingProvider } from "/snippets/missing-provider.mdx";
+
+
+
+
+
+The SMS channel is not enabled by default. To use it, configure a provider like Twilio, Nexmo, or others, and ensure compliance with country-specific restrictions for sender IDs (`from`).
+
+
+1. Go to the Novu Dashboard and click **"Integrations"** on the left sidebar
+2. Click **"Add a provider"**
+3. Locate the **SMS** channel and select the provider you want to use and click **"Next"**
+4. Select for which environment you want to add the Provider
+5. (Optional) Add Conditions to activate the provider only under certain conditions, **useful for tenant-based providers**
+6. Click **"Create"**
+7. Add your SMS provider credentials:
+ - **From**: Displayed as the sender of the SMS (ensure compliance with local regulations)
+ - Provider-specific credentials such as API key / Auth token, Account SID, username, or password
+8. Save the configuration by clicking **"Update"**
+
+
+
+
+
+
+ 1. Go to the Novu Dashboard and click **"Workflows"** on the left sidebar.
+ 2. Click the **"Add a Workflow"** button.
+ 3. Add a step and select **"SMS"** as the channel.
+ 4. Configure the SMS content:
+ - Message body (e.g., `{{userName}}, your order {{orderId}} has shipped.`).
+ - Dynamic placeholders for personalized content.
+ 5. Optionally, set fallback channels to ensure reliable delivery if SMS fails.
+
+
+
+
+
+Novuâs server-side SDKs make integrating Novuâs REST APIs straightforward, letting you focus on implementing workflows without dealing with repetitive code.
+
+
+
+
+
+
+Ensure your SMS configuration is working correctly by testing the setup.
+
+1. Go to the Novu Dashboard, navigate to the **"Workflows"** section, and locate your configured workflow.
+2. Click **"Test Workflow"** and provide sample data, such as a phone number or dynamic variables.
+3. Verify delivery in the Novu Logs or your SMS providerâs dashboard.
+
+
+
+
+
+ Some countries have strict restriction of using verified `from` sender id
+ (name). Kindly check country and provider specific requirements first.
+
+
+## Sending SMS overrides
+
+The overrides field supports a `sms` property and `from`, `to`, `content` field overrides. This allows you to send a message to a different recipient, from a different sender, or with a different content.
+
+```javascript
+import { Novu } from '@novu/node';
+
+const novu = new Novu('');
+
+novu.trigger('', {
+ to: {
+ subscriberId: '',
+ }
+ overrides: {
+ sms: {
+ to: '+123012345678',
+ from: 'Novu Team',
+ content: 'This SMS message is from overrides'
+ },
+ },
+});
+```
+
+## Using different SMS integration
+
+In Novu integration store, multiple SMS channel type provider integrations can be active at the same time. But only one provider integration can be primary at a time. This primary integration will be used as a provider to deliver the SMS by default. If you want to use a different active provider integration then you can use the `integrationIdentifier` sms overrides field.
+
+If there are 4 active SMS integrations with these identifiers:-
+
+1. twilio-abcdef
+2. twilio-ghijkl
+3. firetext-abcdef
+4. infobip-abcdef
+
+Here, if `twilio-abcdef` is primary integration and you want to use `infobip-abcdef` with this trigger then you can use `integrationIdentifier` sms overrides field as below:-
+
+
+
+```javascript
+import { Novu } from '@novu/node';
+
+const novu = new Novu('');
+
+novu.trigger('', {
+ to: {
+ subscriberId: '',
+ },
+ overrides: {
+ sms: {
+ integrationIdentifier: 'infobip-abcdef',
+ },
+ },
+});
+
+```
+
+
+
+ Integration identifier is similar to Provider identifier but it is different than Provider Id. It is unique for each integration. You can find the `integrationIdentifier` in the integration store page.
+
+## Common errors
+
+Common errors and reason for these errors while sending sms messages using Novu.
+
+1. Subscriber does not have a configured channel.
+ - if the `from` field is missing / null / undefined.
+
+
+
+
diff --git a/integrations/providers/sms/africas-talking.mdx b/integrations/providers/sms/africas-talking.mdx
new file mode 100644
index 000000000..4a4393c48
--- /dev/null
+++ b/integrations/providers/sms/africas-talking.mdx
@@ -0,0 +1,97 @@
+---
+title: "Africa's Talking"
+description: "Learn how to use the Africa's Talking provider to send sms notifications using Novu"
+---
+
+You can use [Africa's Talking](https://africastalking.com/) provider to send SMS messages to your customers using the Novu platform with a single API to create multi-channel experiences.
+
+## Getting Started
+
+To use Africa's Talking provider in the SMS channel, the first step is to create an Africa's Talking account and add your `API Key`, `username` and `Sender's ID` to Africa's Talking integration on the Novu platform.
+
+## Creating a username
+
+Youâll need to create an application to create a username in Africaâs Talking. To do so, follow the steps below:
+
+- [Sign up](https://account.africastalking.com/auth/register) or [Log in](https://account.africastalking.com/auth/login) to your Africa's Talking account.
+- Select the team you want your app to be in.
+
+ {" "}
+
+- If you're a new user and don't have a team yet, you'll have to do so by clicking on New Team and entering your team name. Click on Save when you're done.
+
+ {" "}
+
+- On the page that appears, click on the Create App button.
+- On the pop-up that appears, enter your application name, username and select a country. Then click Save. The `username` is what you will use on the Novu platform.
+
+ {" "}
+
+
+## Generating an API key
+
+To generate a new API key, you can follow these steps:
+
+Ensure you have created an app in your team.- Click on the app you created.
+
+ {" "}
+
+- On the page that appears, click on Settings(on the menu on your left). This will
+display a dropdown. Click on API Key from the dropdown options.
+
+ {" "}
+
+- On the page that appears, enter your password and click Generate.
+
+ {" "}
+
+- Copy the API Key generated and paste it into the Novu platform or record it somewhere
+safe for later use because you will not see it from the dashboard on subsequent visits.
+
+
+ Once you've generated your API Key, wait about 3 minutes before testing it.
+
+
+## Getting your Sender's ID
+
+Sender IDs allow you to brand your messages as you send them to your customers. There are two kinds of sender IDs, **shortcodes** and **alphanumerics**. The difference is that you can send and receive messages with shortcodes but only send messages with an alphanumeric.
+
+To create a Short Code:
+
+- On your app dashboard, click on SMS (on the menu on your left). This will display a dropdown. Click on `Shortcodes` from the dropdown options. This will also display a dropdown from which you can then click on `My Shortcodes` to view your codes.
+
+ {" "}
+
+- If you have not created one yet, on the `Shortcodes` dropdown option, click on `Request`.
+ On the page that appears, fill in the form and submit.
+
+ {" "}
+
+
+## To create an Alphanumeric:
+
+- On your app dashboard, click on SMS (on the menu on your left). This will display a dropdown. Click on `Alphanumerics` from the dropdown options. This will also display a dropdown from which you can then click on `My Alphanumerics` to view your codes.
+
+
+ {" "}
+
+
+- If you have not created one yet, on the `Alphanumerics` dropdown option, click on `Request`.
+ On the page that appears, fill in the form and submit
+
+ {" "}
+
+- Once you're done, add either your short code or alphanumeric to the `from` field on the Novu platform.
+
+## Creating an Africa's Talking integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-africastalking) page on Novu.
+- Click the "Add a provider" button.
+- Locate **Africa's Talking** under the SMS section and click on the **Connect** button.
+- Enter the `API key`.
+- Fill in the `username` field.
+- Fill in the `from` field. This is your registered `short code` or `alphanumeric` value.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Connect** button.
+
+Now it is possible to send SMS notifications using Africa's Talking in Novu.
diff --git a/integrations/providers/sms/aws-sns.mdx b/integrations/providers/sms/aws-sns.mdx
new file mode 100644
index 000000000..ad977382a
--- /dev/null
+++ b/integrations/providers/sms/aws-sns.mdx
@@ -0,0 +1,30 @@
+---
+title: "AWS SNS"
+description: "Learn how to use the AWS SNS provider to send sms notifications using Novu"
+---
+
+You can use the [AWS SNS](https://aws.amazon.com/sns/) provider to send transactional emails to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To integrate AWS SNS on the Novu platform, you will need to have in AWS, an IAM user who has the `sns:Publish` permission.
+
+# Create User
+
+To create a user, log in to AWS Console and follow these steps:
+
+- Go to the `IAM` service page.
+- Create a new user with `sns:Publish` permission, or add `sns:Publish` permission to an existing user.
+- Add the `Access Key` credential to the user and copy the `Access key ID` and the `Secret access key`.
+
+For security reasons, it is suggested that you create a new User to use with Novu.
+
+# Create an AWS SNS integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-sns) page on Novu.
+- Click the "Add a provider" button.
+- Locate **Amazon SNS** and click on the **Connect** button.
+- Enter your `Access Key ID`, `Secret Access key`, and `AWS region`.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Save** button.
+- You should now be able to send SMS notifications using **Amazon SNS** in Novu.
diff --git a/integrations/providers/sms/azure.mdx b/integrations/providers/sms/azure.mdx
new file mode 100644
index 000000000..2dc0e7df4
--- /dev/null
+++ b/integrations/providers/sms/azure.mdx
@@ -0,0 +1,24 @@
+---
+title: "Azure SMS"
+description: "Learn how to use the Azure SMS provider to send sms notifications using Novu"
+---
+
+You can use the [Azure SMS](https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/sms/send?tabs=windows&pivots=platform-azcli) SMS provider to send SMS messages to the customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use Azure SMS provider in the SMS channel, the first step is to create an Azure account and grab the communication services connection string from your account dashboard.
+
+# Creating a Azure SMS integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-azure) page on Novu.
+- Click the "Add a provider" button.
+- Locate **Azure Sms** under the SMS section and click on the **Next** button.
+- Select Your Environment add condition (Optional).
+- Click on the `Create` button.
+- Click on the `Disabled` button and mark it as `Active`.
+- Enter the `Connection string`.
+- Enter the `From` value.
+- Click on the **Update** button.
+
+Now it is possible to send SMS notifications using **Azure Sms** in Novu.
diff --git a/integrations/providers/sms/bulk-sms.mdx b/integrations/providers/sms/bulk-sms.mdx
new file mode 100644
index 000000000..d4a490aca
--- /dev/null
+++ b/integrations/providers/sms/bulk-sms.mdx
@@ -0,0 +1,23 @@
+---
+title: "BulkSMS"
+description: "Learn how to use the BulkSMS provider to send sms notifications using Novu"
+---
+
+You can use the [BurstSMS](https://bulksms.com/) provider to send SMS messages to the customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use BulkSMS provider in the SMS channel, the first step is to create a BulkSMS account and create an [API token](https://www.bulksms.com/account/#!/advanced-settings/api-tokens).
+
+# Creating a BulkSMS integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co.co/integrations?utm_campaign=docs-sms-bulksms) page on Novu.
+- Click the "Add a provider" button.
+- Locate **BulkSMS** under the SMS section and click on the **Next** button.
+- Select Your Environment add condition (Optional).
+- Click on the `Create` button.
+- Click on the `Disabled` button and mark it as `Active`.
+- Enter the `API Token`.
+- Click on the **Update** button.
+
+Now it is possible to send SMS notifications using **BulkSMS** in Novu.
diff --git a/integrations/providers/sms/burst-sms.mdx b/integrations/providers/sms/burst-sms.mdx
new file mode 100644
index 000000000..ec6591993
--- /dev/null
+++ b/integrations/providers/sms/burst-sms.mdx
@@ -0,0 +1,25 @@
+---
+title: "BurstSMS"
+description: "Learn how to use the BurstSMS provider to send sms notifications using Novu"
+---
+
+You can use the [BurstSMS](https://burstsms.com/) provider to send SMS messages to the customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use BurstSMS provider in the SMS channel, the first step is to create an BurstSMS account and add the personal BurstSMS API key and your BurstSMS API Secret to the BurstSMS integration on the Novu platform.
+
+# Find the API and Secret key
+
+To find the BurstSMS API and Secret key, log into the personal BurstSMS account and navigate to the API Keys section tab present at the end of the Navbar. It is suggested to create a new API and Secret key for use with Novu. Copy the newly created API and Secret key.
+
+# Creating a BurstSMS integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-burstsms) page on Novu.
+- Click the "Add a provider" button.
+- Locate **BurstSMS** under the SMS section and click on the **Next** button.
+- Select Your Environment add condition (Optional)
+- Click on the `Disabled` button and mark it as `Active`.
+- Enter the `API key` and `API Secret`.
+- Click on the **Upload** button.
+- Now it is possible to send SMS notifications using **BurstSMS** in Novu.
diff --git a/integrations/providers/sms/clickatell.mdx b/integrations/providers/sms/clickatell.mdx
new file mode 100644
index 000000000..fa21da398
--- /dev/null
+++ b/integrations/providers/sms/clickatell.mdx
@@ -0,0 +1,62 @@
+---
+title: "Clickatell"
+description: "Learn how to use the Clickatell provider to send sms notifications using Novu"
+---
+
+You can use the [Clickatell](https://www.clickatell.com/) provider to send SMS messages to your customers using the Novu Platform.
+Let's see how to do it:
+
+## Getting Started
+
+To use the [Clickatell](https://www.clickatell.com/) provider in the SMS channel, the first step is to [create a Clickatell account](https://www.clickatell.com/sign-up/) and add your API key to the Clickatell integration on the [Novu web dashboard](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-clickatell).
+
+## Retrieving your API Key
+
+To find your Clickatell API key:
+
+- [Sign up](https://www.clickatell.com/sign-up/) or [Login](https://app.clickatell.com/signin) to your Clickatell account.
+- Click on the `My Workspace`, and then click `SMS` in Channels Section.
+
+
+ {" "}
+
+
+- Click on the `New SMS Setup`.
+
+
+ {" "}
+
+
+- Select `API` then `Messaging Type` and click Next.
+
+
+ {" "}
+
+
+- Select `Basic HTTP API` then `create a new HTTP API` and click Next.
+
+
+ {" "}
+
+
+- Now fill in all details and Click Next.
+
+
+ {" "}
+
+
+- Copy the API key and click complete.
+
+ {" "}
+
+
+## Create a Clickatell integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-clickatell) page on Novu.
+- Click the "Add a provider" button.
+- Locate **Clickatell** under the SMS section and click on the **Connect** button.
+- Enter your Clickatell API Key.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Connect** button.
+
+Now it is possible to send SMS notifications using **Clickatell** in Novu.
diff --git a/integrations/providers/sms/clicksend.mdx b/integrations/providers/sms/clicksend.mdx
new file mode 100644
index 000000000..bd7659fe5
--- /dev/null
+++ b/integrations/providers/sms/clicksend.mdx
@@ -0,0 +1,31 @@
+---
+title: "Clicksend"
+description: "Learn how to use the Clicsend provider to send sms notifications using Novu"
+---
+
+You can use the [Clicksend](https://www.clicksend.com/in/) provider to send SMS messages to your customers using the Novu Platform.
+Let's see how to do it:
+
+# Getting Started
+
+To use the [Clicksend](https://www.clicksend.com/in/) provider in the SMS channel, the first step is to [create a Clicksend account](https://dashboard.clicksend.com/signup/step1) and add your API key to the Clicksend integration on the [Novu web dashboard](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-clicksend).
+
+# Retrieving your API Key
+
+- **Generate an API Key**: After logging into your ClickSend account, navigate to the API Keys section. This is usually located in your account settings or developer dashboard.
+- **Create a New API Key**: It's recommended to create a new API key specifically for your integration with Novu. Click on the option to create a new API key, and it will be generated for you.
+- **Copy the API Key**: Once your API key is created, make sure to copy it to your clipboard. You will need this key to connect ClickSend with Novu.
+
+# Create a Clicksend integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-clicksend) page on Novu.
+- Click on Add a Provider.
+- Select Clicksend service.
+- Choose your preferred deployment environment: `Development` or `Production`. Then Click the `Create` button.
+- Enter your Clicksend Username.
+- Enter your Clicksend API Key.
+- Fill in the `From` field.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+
+Now it is possible to send SMS notifications using **Clicksend** in Novu.
diff --git a/integrations/providers/sms/firetext.mdx b/integrations/providers/sms/firetext.mdx
new file mode 100644
index 000000000..a54f6d2a2
--- /dev/null
+++ b/integrations/providers/sms/firetext.mdx
@@ -0,0 +1,46 @@
+---
+title: "Firetext"
+description: "Learn how to use the firetext provider to send sms notifications using Novu"
+---
+
+You can use the [firetext](https://www.firetext.co.uk) provider to send SMS messages to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+## Getting Started
+
+To use the firetext provider in the SMS channel, the first step is to create a firetext account and add your API key and Sender ID to the firetext integration on the Novu platform.
+
+- Note : Firetext is only available in uk region. Others may require additional verification.
+
+## Retrieving your API Key
+
+To find your firetext API key:
+
+- [Sign up](https://app.firetext.co.uk/signup) or [Login](https://app.firetext.co.uk/) to your firetext account.
+- Click on the `Settings` icon in the top right corner of the screen.
+
+
+ {" "}
+
+
+- Now Click on the `API` in `My Settings` Section.
+
+
+ {" "}
+
+
+- On the API Keys page, copy the `API key`.
+
+ {" "}
+
+
+## Create a firetext integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-firetxt) page on Novu.
+- Click the "Add a provider" button.
+- Locate **firetext** under the SMS section and click on the **Connect** button.
+- Enter your `firetext` API Key.
+- Fill in the `From` field.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Connect** button.
+
+Now it is possible to send SMS notifications using **firetext** in Novu.
diff --git a/integrations/providers/sms/gupshup.mdx b/integrations/providers/sms/gupshup.mdx
new file mode 100644
index 000000000..14d82b33c
--- /dev/null
+++ b/integrations/providers/sms/gupshup.mdx
@@ -0,0 +1,27 @@
+---
+title: "gupshup"
+description: "Learn how to use the gupshup provider to send sms notifications using Novu"
+---
+
+You can use the [gupshup](https://www.gupshup.io/) provider to send SMS messages to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the gupshup provider in the SMS channel, the first step is to create a gupshup account and add the Account Username and Password to the gupshup integration on the Novu platform.
+
+# What is User id and Password?
+
+- `userid` : The account number provided by the Enterprise SMS GupShup.
+- `Password` : Password is provided by Gupshup for authentication of user id. The password must be the same as used to log on to the Enterprise SMS GupShup website.
+
+# Creating a gupshup integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-gupshup) page on Novu.
+- Click the "Add a provider" button.
+- Locate **gupshup** under the SMS section and click on the **Connect** button.
+- Enter the `User id`.
+- Enter the `Password`.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Connect** button.
+
+Now it is possible to send SMS notifications using **gupshup** in Novu.
diff --git a/integrations/providers/sms/infobip.mdx b/integrations/providers/sms/infobip.mdx
new file mode 100644
index 000000000..d168b13fe
--- /dev/null
+++ b/integrations/providers/sms/infobip.mdx
@@ -0,0 +1,59 @@
+---
+title: "Infobip - SMS"
+description: "Learn how to use the Infobip provider to send sms notifications using Novu"
+---
+
+You can use the [Infobip](https://www.infobip.com/developers/) provider to send SMS messages to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+## Getting Started
+
+To use the Infobip provider in the SMS channel, you will need to create an Infobip account and add your API key and Base URL to the Infobip integration on the Novu platform.
+
+## Retrieving your API Key
+
+To Find a new API key in Infobip, you can follow these steps:
+
+- [Sign up](https://www.infobip.com/signup) or [Log in](https://portal.infobip.com/login/) to your Infobip account.
+- On the [Homepage](https://portal.infobip.com/homepage/), you'll see your API key.
+
+
+ {" "}
+
+Alternatively, you can find the API key on the Developer Tools page.
+
+- On the sidebar (on the left), click on `Developer Tools`.
+- This will display a dropdown from which you can then click on `API Ksys` to view your API key.
+
+
+ {" "}
+
+
+If you want to create an API key:
+
+- Click on the `CREATE API KEY` button
+- Fill the form
+- Click on `GENERATE`
+
+ {" "}
+
+
+## Finding the Base URL
+
+To see your base URL, log in to the account. Once logged in, on the Homepage, you should see your base URL in this format:Â `xxxxx.api.infobip.com`.
+
+
+ {" "}
+
+
+## Create an Infobip integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-infobip) page on Novu.
+- Click the "Add a provider" button.
+- Locate **Infobip** under the SMS section and click on the **Connect** button.
+- Enter your Infobip API Key.
+- Enter your Base URL.
+- Fill in the `From` field.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Connect** button.
+
+You should now be able to send SMS notifications using Infobip in Novu.
diff --git a/integrations/providers/sms/kannel.mdx b/integrations/providers/sms/kannel.mdx
new file mode 100644
index 000000000..2707c68e8
--- /dev/null
+++ b/integrations/providers/sms/kannel.mdx
@@ -0,0 +1,79 @@
+---
+title: "Kannel"
+description: "Learn how to use the Kannel sms provider to send sms notifications using Novu"
+---
+
+Before integrating Kannel with Novu, you should have Kannel set up and configured as an SMS gateway on your server. Letâs look at how you can do that:
+
+# Setting up Kannel
+
+1. First, you need to install Kannel on your server. You can download it from the [official-website](https://www.kannel.org/download.shtml) or use a package manager specific to your operating system (e.g., apt-
+ get for Ubuntu, yum for CentOS, etc.).
+2. Kannel's configuration is done through a file called kannel.conf. You need to edit this file to specify your SMS provider settings. Here's a basic configuration example:
+
+ ```bash
+ group = smsc
+ smsc = smpp
+ smsc-id = YourSMSCID
+ host = SMSC_Hostname_or_IP
+ port = SMSC_Port
+ system-type = SMSC_System_Type
+ smsc-username = YourUsername
+ smsc-password = YourPassword
+ max-pending-submits = 10
+ allow-ip = "127.0.0.1"
+ ```
+
+ Replace the placeholders (e.g., **YourSMSCID**, **SMSC_Hostname_or_IP**, **SMSC_Port**, **SMSC_System_Type**, **YourUsername**, and **YourPassword**) with the actual values provided by your SMS provider.
+
+3. You can define services that will handle incoming and outgoing SMS messages. These services specify how Kannel should process SMS requests. Here's an example of an SMS service configuration:
+
+ ```bash
+ group = sendsms-user
+ username = YourUsername
+ password = YourPassword
+ concatenation = true
+ max-messages = 3
+ ```
+
+ Adjust the settings to your needs.
+
+4. Start Kannel with the following command:
+
+ ```bash
+ bearerbox /path/to/kannel.conf
+ ```
+
+ Make sure to replace /path/to/kannel.conf with the actual path to your Kannel configuration file.
+
+# Creating a Kannel integration with Novu
+
+After setting up your Kannel, follow these steps to integrate with novu:
+
+- Visit the [Integrations Store](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-kannel) on Novu.
+- Click the "Add a provider" button.
+- Select Kannel service.
+- Choose your preferred deployment environment: `Development` or `Production`. Then Click the `Create` button.
+- Once the integration is active, you'll need to configure it. This configuration usually involves providing the necessary details for Novu to connect to your Kannel SMS gateway. These details typically include:
+
+ - **Kannel Gateway URL or IP Address**: If your Kannel SMS gateway is hosted on your server, you should use the server's IP address or hostname.
+ - **Port**: The port number through which Novu should communicate with Kannel (usually 13013, or a custom port you've configured in Kannel).
+ - **Username and Password**: If you've set up authentication for your Kannel SMS gateway, provide the username and password required for authentication:
+
+ ```bash
+ group = smsc
+ smsc = smpp
+ smsc-id = YourSMSCID
+ host = SMSC_Hostname_or_IP
+ port = SMSC_Port
+ smsc-username = YourUsername
+ smsc-password = YourPassword
+ max-pending-submits = 10
+ allow-ip = "127.0.0.1"
+ ```
+
+ In this example, **YourUsername** and **YourPassword** are the credentials you'd use for authentication.
+
+- Fill in the `From` field.
+- Click on the `Update` button.
+- You should now be able to send notifications using Kannel in Novu.
diff --git a/integrations/providers/sms/messagebird.mdx b/integrations/providers/sms/messagebird.mdx
new file mode 100644
index 000000000..0d018dd95
--- /dev/null
+++ b/integrations/providers/sms/messagebird.mdx
@@ -0,0 +1,23 @@
+---
+title: "MessageBird"
+description: "Learn how to use the messagebird provider to send sms notifications using Novu"
+---
+
+You can use the [MessageBird](https://www.messagebird.com) provider to send SMS messages to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the MessageBird provider in the SMS channel, the first step is to create a [MessageBird account](https://www.messagebird.com/en/sign-up) and then generate an `Access Key` within the developers' section section of your MessageBird account. This access key is essential for authenticating your requests to the MessageBird API.
+
+# Creating a MessageBird integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-messagebird) page on Novu.
+- Click the "Add a provider" button.
+- Locate **MessageBird** under the SMS section. Click it and the **Next** button.
+- Select Your Environment add condition (Optional).
+- Click on the `Disabled` button and mark it as `Active`.
+- Enter the `Access Key` value.
+- Enter the `From` value.
+- Click on the **Update** button.
+
+Now it is possible to send SMS notifications using **MessageBird** in Novu.
diff --git a/integrations/providers/sms/nexmo.mdx b/integrations/providers/sms/nexmo.mdx
new file mode 100644
index 000000000..bb503668c
--- /dev/null
+++ b/integrations/providers/sms/nexmo.mdx
@@ -0,0 +1,25 @@
+---
+title: "Nexmo"
+description: "Learn how to use the Nexmo provider to send sms notifications using Novu"
+---
+
+You can use the [Nexmo By Vonage](https://www.vonage.com/) provider to send SMS messages to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the Nexmo provider in the SMS channel, the first step is to create a Nexmo account and add the API key and API Secret to the Nexmo integration on the Novu platform.
+
+# Finding the API key and secret
+
+First, [sign up for a Vonage account](https://ui.idp.vonage.com/ui/auth/login) if you don't already have one, and make a note of your API key and secret on the [dashboard getting started page](https://dashboard.nexmo.com/getting-started-guide).
+
+# Create a Nexmo integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-nexmo) page on Novu.
+- Click the "Add a provider" button.
+- Locate **Nexmo** under the SMS section and click on the **Connect** button.
+- Enter the `API key` and `API Secret`.
+- Enter a valid `From` email address.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Connect** button.
+- Now it is possible to send SMS notifications using **Nexmo** in Novu.
diff --git a/integrations/providers/sms/overview.mdx b/integrations/providers/sms/overview.mdx
new file mode 100644
index 000000000..c3d54bdfe
--- /dev/null
+++ b/integrations/providers/sms/overview.mdx
@@ -0,0 +1,30 @@
+---
+title: "SMS Providers Integration"
+sidebarTitle: "Overview"
+description: "Configure and manage SMS notification providers like Twilio, Nexmo, and others with Novu's notification infrastructure."
+icon: "circle-info"
+---
+
+Novu makes SMS notifications simple, scalable, and reliable, enabling seamless integration with your communication stack. Whether you're sending OTPs, updates, or transactional messages, Novu ensures your SMS notifications are delivered efficiently and effectively.
+
+With the SMS channel, you can:
+
+- **Switch Providers Effortlessly:** Integrate popular services like Twilio, Nexmo, or a custom provider
+- **Deliver at Scale:** Handle high-volume messaging with confidence
+- **Customize and Track:** Tailor SMS content dynamically and monitor delivery status in real time
+
+## Key Features
+
+- **Dynamic Messaging:** Inject user-specific data into messages for personalization
+- **Multi-Provider Support:** Switch or combine providers to maximize reliability
+- **Delivery Insights:** Track message delivery, failures, and user engagement
+- **Fallback Mechanisms:** Ensure reliable messaging with backup providers
+- **Template Management:** Simplify content creation with reusable SMS templates
+- **Streamlined API Integration:** Easily connect your backend for automated messaging workflows
+
+## Common Use Cases
+
+- **Transactional Notifications:** Send OTPs, receipts, or order updates instantly
+- **Marketing Campaigns:** Deliver promotional offers and updates to your audience
+- **Critical Alerts:** Notify users of urgent events, like security breaches or system outages
+- **Reminders and Scheduling:** Automate reminders for appointments, events, or deadlines
\ No newline at end of file
diff --git a/integrations/providers/sms/plivo.mdx b/integrations/providers/sms/plivo.mdx
new file mode 100644
index 000000000..9266c96d6
--- /dev/null
+++ b/integrations/providers/sms/plivo.mdx
@@ -0,0 +1,27 @@
+---
+title: "Plivo"
+description: "Learn how to use the Plivo provider to send sms notifications using Novu"
+---
+
+You can use the [Plivo](https://www.plivo.com/) provider to send SMS messages to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the Plivo provider in the SMS channel, the first step is to create a Plivo account and add the Account SID and Auth token to the Plivo integration on the Novu platform.
+
+# Finding the Account SID and Auth token
+
+[Sign up](https://console.plivo.com/accounts/register/) or [Login](https://console.plivo.com/accounts/login/) to your Plivo account, and make a note of your Account SID and Auth token on the [Plivo console page](https://console.plivo.com/dashboard/).
+
+# Creating a Plivo integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-plivo) page on Novu.
+- Click the "Add a provider" button.
+- Locate **Plivo** under the SMS section and click on the **Connect** button.
+- Enter the `Account SID`.
+- Enter the `Auth token`.
+- Fill in the `From` field.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Connect** button.
+
+Now it is possible to send SMS notifications using **Plivo** in Novu.
diff --git a/integrations/providers/sms/sendchamp.mdx b/integrations/providers/sms/sendchamp.mdx
new file mode 100644
index 000000000..003de3384
--- /dev/null
+++ b/integrations/providers/sms/sendchamp.mdx
@@ -0,0 +1,67 @@
+---
+title: "Sendchamp"
+description: "Learn how to use the Sendchamp provider to send sms notifications using Novu"
+---
+
+You can use the [Sendchamp](https://www.sendchamp.com/) provider to send SMS messages to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+## Getting Started
+
+To use the Sendchamp provider in the SMS channel, the first step is to create a Sendchamp account and add your API key and Sender ID to the Sendchamp integration on the Novu platform.
+
+## Retrieving your API Key
+
+To find your Sendchamp API key:
+
+- [Sign up](https://my.sendchamp.com/signup) or [Login](https://my.sendchamp.com/login) to your Sendchamp account.
+- Click on the Avatar icon in the top right corner of the screen, and then click `API & Integrations` from the drop-down menu.
+
+
+ {" "}
+
+ Alternatively, you can access the API key from the Accounts menu.
+
+- Scroll to the bottom of the sidebar (on the left) and click on `Accounts`.
+- This will display a dropdown from which you can then click on `API keys & Webhooks` to view your API key.
+
+ {" "}
+
+- On the API Keys page, copy the Public access key.
+
+ {" "}
+
+
+## Get your Sender's ID
+
+The Sender ID represents the sender of the message to your customers.
+
+To get your Sender's ID:
+
+- On the sidebar (on the menu on your left), click on `SMS`. This will display a dropdown. Click on `Sender ID` from the dropdown options.
+- On the page that appears, you'll find a list of your Sender IDs
+
+
+ {" "}
+
+ If you have not created one yet:
+
+- Click on the `Create Sender ID` button to request a Sender ID.
+- Fill in the form.
+- Click on `Add Sender ID` button.
+
+ {" "}
+
+
+Once it is approved, you can use your Sender ID as the from field on the Novu platform.
+
+## Create a Sendchamp integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-sendchamp) page on Novu.
+- Click the "Add a provider" button.
+- Locate **Sendchamp** under the SMS section and click on the **Connect** button.
+- Enter your Sendchamp API Key.
+- Fill in the `From` field.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Connect** button.
+
+Now it is possible to send SMS notifications using **Sendchamp** in Novu.
diff --git a/integrations/providers/sms/simpletexting.mdx b/integrations/providers/sms/simpletexting.mdx
new file mode 100644
index 000000000..5ac0b056e
--- /dev/null
+++ b/integrations/providers/sms/simpletexting.mdx
@@ -0,0 +1,24 @@
+---
+title: "SimpleTexting"
+description: "Learn how to use the SimpleTexting provider to send sms notifications using Novu"
+---
+
+You can use the [SimpleTexting](https://simpletexting.com/) SMS provider to send SMS messages to the customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use SimpleTexting provider in the SMS channel, the first step is to create a SimpleTexting account and grab your `API KEY` in your settings.
+
+# Creating a SimpleTexting integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-simpletexting) page on Novu.
+- Click the "Add a provider" button.
+- Locate **SimpleTexting** under the SMS section and click on the **Next** button.
+- Select Your Environment add condition (Optional).
+- Click on the `Create` button.
+- Click on the `Disabled` button and mark it as `Active`.
+- Enter the `API Key`.
+- Enter the `From` value.
+- Click on the **Update** button.
+
+Now it is possible to send SMS notifications using **SimpleTexting** in Novu.
diff --git a/integrations/providers/sms/sms-central.mdx b/integrations/providers/sms/sms-central.mdx
new file mode 100644
index 000000000..8ade8930d
--- /dev/null
+++ b/integrations/providers/sms/sms-central.mdx
@@ -0,0 +1,23 @@
+---
+title: "SMS Central"
+description: "Learn how to use the SMS Central provider to send sms notifications using Novu"
+---
+
+You can use the [SMS Central](https://www.smscentral.com.au/) provider to send SMS messages to your customers using the Novu platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the SMS Central provider in the sms channel, you will need to create a SMS Central account and add your SMS Central `Username` & `Password` to the SMS Central integration on the Novu platform.
+
+# Creating the SMS Central integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-smscentral) page on Novu.
+- Click the "Add a provider" button.
+- Select SMS Central service
+- Click `Next`
+- Choose your preferred deployment environment: `Development` or `Production`. Then Click the `Create` button.
+- Add `Username` & `Password`
+- Fill up the `From` section with the number you wish to send sms from.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Update** button.
+- You should now be able to send notifications using SMS Central in Novu.
diff --git a/integrations/providers/sms/sms77.mdx b/integrations/providers/sms/sms77.mdx
new file mode 100644
index 000000000..03ec886bb
--- /dev/null
+++ b/integrations/providers/sms/sms77.mdx
@@ -0,0 +1,24 @@
+---
+title: "SMS77"
+description: "Learn how to use the SMS77 provider to send sms notifications using Novu"
+---
+
+It is possible to use the [SMS77](https://www.sms77.io/en) provider to send SMS messages to the customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the SMS77 provider in the SMS channel, the first step is to create an SMS77 account and add the personal API key to the SMS77 integration on the Novu platform.
+
+# Find the API key
+
+To find the SMS77 API key, log into the personal SMS77 account and navigate to the API Keys page by clicking on the 'Developer' tab present at the end of the sidebar. It is suggested to create a new API key for use with Novu. Copy the newly created API key.
+
+# Creating an SMS77 integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-sms77) page on Novu.
+- Click the "Add a provider" button.
+- Locate **SMS77** under the SMS section and click on the **Connect** button.
+- Enter the `API key`.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the **Save** button.
+- Now it is possible to send SMS notifications using **SMS77** in Novu.
diff --git a/integrations/providers/sms/sns.mdx b/integrations/providers/sms/sns.mdx
new file mode 100644
index 000000000..798c3305a
--- /dev/null
+++ b/integrations/providers/sms/sns.mdx
@@ -0,0 +1,25 @@
+---
+title: "SNS"
+description: "Learn how to use the SNS provider to send sms notifications using Novu"
+---
+
+You can use the [SNS](https://aws.amazon.com/sns/) provider to send transactional emails to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+Before you can use SNS as your SMS provider in the Novu platform, you'll need to set up an Amazon Web Services (AWS) account and configure the necessary settings. Here are the steps to get started:
+
+- **Create an AWS Account**: If you don't already have an AWS account, you'll need to create one. You can sign up for an AWS account on the [AWS website](https://aws.amazon.com/).
+- **Set Up Amazon SNS**: After you've created your AWS account, navigate to the AWS Management Console. In the Services menu, locate and click on "Simple Notification Service (SNS)." Follow the prompts to set up SNS for your account.
+- **Configure SMS Preferences**: In your SNS dashboard, configure your SMS preferences. This includes setting up your sender ID and opting in for SMS messaging.
+- **Create Access Keys**: To access SNS programmatically, you'll need to create AWS Access Keys. These keys are used to authenticate your integration with the Novu platform. Go to the [AWS Identity and Access Management console](https://signin.aws.amazon.com/) to create access keys.
+
+# Create an SNS integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-sms-sns) page on Novu.
+- Click the "Add a provider" button.
+- Choose your preferred deployment environment: `Development` or `Production`. Then Click the `Create` button.
+- Enter your `Access Key ID`, `Secret Access key`, and `AWS region`.
+- Click on the `Disabled` button and mark it as `Active`.
+- Click on the `Update` button.
+- You should now be able to send SMS notifications using **SNS** in Novu.
diff --git a/integrations/providers/sms/telnyx.mdx b/integrations/providers/sms/telnyx.mdx
new file mode 100644
index 000000000..cdd34c7df
--- /dev/null
+++ b/integrations/providers/sms/telnyx.mdx
@@ -0,0 +1,47 @@
+---
+title: "Telnyx"
+description: "Learn how to use the Telnyx provider to send sms notifications using Novu"
+---
+
+You can use the [Telnyx](https://telnyx.com/) provider to send transactional emails to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+# Getting Started
+
+To use the Telnyx provider in the SMS channel, you will need to create a Telnyx account and add your API key to the Telnyx integration on the Novu platform.
+
+# Finding the API Key
+
+To find your Telnyx API key:
+
+- Log into your Telnyx account.
+- Navigate to Account Setting.
+- Then go to [Keys & Credentials](https://portal.telnyx.com/#/app/api-keys).
+- You can copy the API key from there.
+- Alternatively, you can create an API key by tapping on the Create API Key button.
+
+Before copying it, make sure its status is showing active.
+
+# Finding the Message Profile ID
+
+To get your Message profile ID:
+
+- Navigate to [Messaging](https://portal.telnyx.com/#/app/messaging) to find the profiles.
+- Make sure you created a Telnyx Messaging Profile previously. Learn more [here](https://developers.telnyx.com/docs/v2/messaging/quickstarts/portal-setup).
+- Go to the active Messaging Profile.
+- Copy the profile ID.
+
+# Making sure that the From address is valid
+
+A valid from address must be a valid phone number in +E.164 format, a short code, or an alphanumeric sender ID associated with the sending messaging profile. Alphanumeric sender IDs must be between 1 and 11 characters long, and can only contain ASCII letters, numbers, and spaces. They must contain at least one letter.
+
+# Creating a Telnyx integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations) page on the Novu.
+- Click the "Add a provider" button.
+- Locate Telnyx and click on the **Connect** button.
+- Enter your Telnyx API Key.
+- Fill in the Message profile ID field.
+- Enter the Valid From address.
+- Click on the `Disabled` button and `mark it as Active`.
+- Click on the **Save** button.
+- You should now be able to send notifications using Telnyx in Novu.
diff --git a/integrations/providers/sms/termii.mdx b/integrations/providers/sms/termii.mdx
new file mode 100644
index 000000000..bd819aa43
--- /dev/null
+++ b/integrations/providers/sms/termii.mdx
@@ -0,0 +1,64 @@
+---
+title: "Termii"
+description: "Learn how to use the Termii provider to send sms notifications using Novu"
+---
+
+You can use the [Termii](https://termii.com/) provider to send SMS messages to your customers using the Novu Platform with a single API to create multi-channel experiences.
+
+## Getting Started
+
+To use the Termii provider in the SMS channel, the first step is to create a Termii account and add your API key and Sender ID to the Termii integration on the Novu platform.
+
+## Retrieving your API Key
+
+To find your Termii API key:
+
+- [Sign up](https://accounts.termii.com/#/register) or [Login](https://accounts.termii.com/#/login) to your Termii account.
+- Navigate to your [dashboard](https://accounts.termii.com/#/).
+- Then scroll to the bottom of the page to find your API key.
+
+
+ {" "}
+
+ Alternatively, you can find the API key on the Settings page.
+
+- Scroll to the bottom of the sidebar (on the left) and click on settings.
+- This will display a dropdown from which you can then click on `API Token` to view your API key.
+
+ {" "}
+
+
+## Getting your Sender's ID
+
+Sender IDs allow you to brand your messages as you send them to your customers.
+
+To get your Sender's ID:
+
+- On the sidebar (on the menu on your left), click on `Rental`. This will display a dropdown. Click on `SMS Sender IDs` from the dropdown options.
+- On the page that appears, you'll find a list of your Sender IDs
+
+
+ {" "}
+
+
+If you have not created one yet:
+
+- Click on the `Make a new request` button to request a Sender ID.
+- Fill in the form
+- Click on `Save`
+
+
+ {" "}
+
+
+## Creating a Termii integration with Novu
+
+- Visit the [Integrations](https://dashboard-v2.novu.co/integrations) page on Novu.
+- Click the "Add a provider" button.
+- Locate **Termii** under the SMS section and click on the **Connect** button.
+- Enter your Termii API Key.
+- Fill in the `From` field.
+- Click on the Disabled button and mark it as Active.
+- Click on the **Connect** button.
+
+Now it is possible to send SMS notifications using **Termii** in Novu.
diff --git a/integrations/providers/sms/twilio.mdx b/integrations/providers/sms/twilio.mdx
new file mode 100644
index 000000000..92c31b320
--- /dev/null
+++ b/integrations/providers/sms/twilio.mdx
@@ -0,0 +1,54 @@
+---
+title: "Twilio"
+description: "Learn how to use the Twilio provider to send sms notifications using Novu"
+---
+
+You can utilize the [Twilio](https://www.twilio.com/) API to communicate with your customers using SMS messaging. Letâs look at how you can do that:
+
+# Setting up Twilio
+
+1. First, go to [Twilio](https://www.twilio.com/) and create an account, probably starting with their free trial.
+2. Youâll be asked to verify your email and your phone number. Get them verified.
+3. Once youâre done with that, youâll get an option to âget a Twilio phone numberâ from your Twilio console.
+4. Click on it to get your Twilio phone number.
+
+When first using Twilio there should be an option to get a Twilio phone number in the main console. Otherwise, you may have to [Buy](https://console.twilio.com/us1/develop/phone-numbers/manage/search?frameUrl=%2Fconsole%2Fphone-numbers%2Fsearch%3Fx-target-region%3Dus1¤tFrameUrl=%2Fconsole%2Fphone-numbers%2Fsearch%3FisoCountry%3DUS%26searchTerm%3D%26searchFilter%3Dleft%26searchType%3Dnumber%26x-target-region%3Dus1%26__override_layout__%3Dembed%26bifrost%3Dtrue) a number from that link to begin using it. Assuming this is the first run though, utilize the free number given to us.
+
+Simply follow one of their many [Tutorials](https://www.twilio.com/docs/usage/requests-to-twilio) within their docs to understand every part of the process.
+
+Irrespective of the language you use, the process is the same:
+
+- Load the Account SID and Auth token into the code, using some sort of safe environment such as .env variables. Nobody should have access to this but you.
+- Create a client object from Twilio that take the SID and Token as variables then create a message with the client.
+- A message is an object that has three things:
+ - that free number from earlier,
+ - the number you would like to send to, and
+ - a body message that you want to send through SMS.
+
+# Creating a Twilio integration with Novu
+
+Creating a Twilio integration with Novu is quite simple. Just follow these steps:
+
+- Visit the [Integrations Store](https://dashboard-v2.novu.co/integrations) on Novu.
+- Click the "Add a provider" button.
+- Locate **Twilio** and click on the `Disabled` button and mark it as `Active`.
+- Click on the **Connect** button.
+- Go to your [Console](https://console.twilio.com/) on Twilio and access the Account Info section at the bottom of the page
+- Enter your `Account SID`, `Auth Token` and `Twilio Phone Number`.
+- Click on the **Save** button.
+- You should now be able to send SMS notifications using **Twilio** in Novu.
+
+## Sending an WhatsApp message with Twillio
+
+To send a WhatsApps message with Twillio integration prefix the phone number of the subscriber with `whatsapp:` as shown below.
+
+```ts
+await novu.trigger("", {
+ to: {
+ subscriberId: "",
+ phone: "whatsapp:555-4242",
+ },
+});
+```
+
+Read more about [sending a Message with the Twilio API for WhatsApp](https://www.twilio.com/docs/whatsapp/tutorial).
diff --git a/integrations/segment.mdx b/integrations/segment.mdx
new file mode 100644
index 000000000..c34b5255d
--- /dev/null
+++ b/integrations/segment.mdx
@@ -0,0 +1,288 @@
+---
+title: "How To Integrate Segment With Novu"
+sidebarTitle: "Integrate with Segment"
+---
+
+[Segment](https://segment.com/) is a customer data platform that helps businesses collect, manage, and analyze customer data from multiple sources. It streamlines data integration, ensures data quality, and aids in compliance with regulations. Segment's tools enable better understanding of customer behavior and facilitate personalized customer experiences. It's useful for marketing, analytics, and product teams in diverse industries.
+
+If this is your first time working with the tool, consider consulting the 'Get Started' guide in [Segment's official documentation](https://segment.com/docs/getting-started/).
+
+## Examples Use Case
+
+**Enhancing Customer Engagement and Conversion Rates**
+
+
+
+ - The e-commerce platform uses Segment to collect and unify customer data from various sources like website visits, purchase history, and customer interactions.
+ - Segment helps in creating a unified customer profile by consolidating data from different touchpoints â mobile app usage, website browsing patterns, and previous purchase behavior.
+
+
+
+
+
+ - The data collected is analyzed to understand customer preferences, buying patterns, and engagement levels.
+ - Customers are segmented into different groups based on their behavior, interests, and purchase history. For instance, one segment might include frequent shoppers, while another might focus on those who browse but rarely purchase.
+
+
+
+
+
+
+ - Novu is used to craft and send personalized notifications to these segmented groups.
+ - For frequent shoppers, notifications about new arrivals or exclusive deals might be sent. For those who browse but rarely buy, notifications could include special discount codes or reminders about items left in the cart.
+
+
+
+
+
+
+
+ - Notifications can also be triggered based on specific customer actions. For example, if a customer views a product but doesn't make a purchase, they might receive a notification later highlighting a special offer on that product.
+
+
+
+
+
+
+
+ - Customer responses to these notifications are fed back into Segment. This data is used to refine customer profiles and segmentation strategies continuously.
+ - The effectiveness of different types of notifications is analyzed to optimize future communication.
+
+
+
+**Outcome:**
+
+- Enhanced customer engagement through personalized and timely notifications.
+
+- Improved conversion rates by targeting customers with relevant offers based on their behavior and preferences.
+
+- Greater customer loyalty due to a tailored shopping experience.
+
+## Setting Novu as a Destination
+
+As of today Segment doesnât have a native Novu Destination integration **yet** .
+
+We will be using [Destination Functions](https://segment.com/docs/connections/functions/destination-functions/). Destination functions allow you to transform and annotate your Segment events and send them to any external tool or API without worrying about setting up or maintaining any infrastructure.
+
+### Create a destination function
+
+- From your workspace, go to `Connections > Catalog` and click the `Functions` tab.
+- Click `New Function`.
+- Select `Destination` as the function type and click `Build`.
+- After you click `Build`, a code editor appears. Use the editor to write the code for your function, configure settings, and test the functionâs behavior.
+
+
+ Want to see some example functions? Check out the templates available in the
+ Functions UI, or in the open-source Segment Functions Library.
+
+
+### Code the destination function
+
+Segment invokes a separate part of the function (called a âhandlerâ) for each event type that you send to your destination function.
+
+
+ {" "}
+ Your function isnât invoked for an event if youâve configured a destination filter,
+ and the event doesnât pass the filter.{" "}
+
+
+The default source code template includes handlers for all event types. You donât need to implement all of them - just use the ones you need, and skip the ones you donât.
+
+Destination functions can define handlers for each message type in the Segment spec:
+
+- onIdentify
+- onTrack
+- onPage
+- onScreen
+- onGroup
+- onAlias
+- onDelete
+- onBatch
+
+Each of the functions above accepts two arguments:
+
+`event` - Segment event object, where fields and values depend on the event type.
+For example, in âIdentifyâ events, Segment formats the object to match the Identify spec.
+
+`settings` - Set of settings for this function.
+The example below shows a destination function that listens for âTrackâ events, and sends some details about them to an external service.
+
+```javascript
+async function onTrack(event) {
+ await fetch("https://example-service.com/api", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ event_name: event.event,
+ event_properties: event.properties,
+ timestamp: event.timestamp,
+ }),
+ });
+}
+```
+
+To change which event type the handler listens to, you can rename it to the name of the message type.
+
+For example, if you rename this function `onIdentify`, it listens for âIdentifyâ events instead.
+
+
+ If you you need an example of Novu destination function, you can find it in
+ [here](https://github.com/novuhq/segment-novu-destination-scripts). Feel free
+ to submit your function examples as well!
+
+
+### Sending a payload to Novu
+
+Now let's learn how to send a payload to Novu based on the `onTrack` event function:
+
+To successfully send a payload to Novu, triggering the appropriate [workflow](/concepts/workflows) and delivering it to the correct customer, please ensure that you provide the following information:
+
+1. Novu's Workflow Identifier.
+2. Subscriber ID (Please ensure that the Subscriber ID is both unique and consistent across all of your databases).
+3. Your Novu API Key.
+4. [Novu's Event Trigger API Endpoint](https://api.novu.co/events/trigger)
+
+```javascript
+async function onTrack(event, settings) {
+ const eventProperties = event.properties;
+
+ if (!eventProperties.environment) {
+ throw new InvalidEventPayload("environment property is required");
+ }
+ if (!eventProperties.name) {
+ throw new InvalidEventPayload("Workflow name property is required");
+ }
+
+ console.log("environment:", eventProperties.environment);
+
+ const payload = {
+ name: eventProperties.name,
+ to: {
+ subscriberId: eventProperties.user.subscriberId,
+ email: eventProperties.user.email,
+ firstName: eventProperties.user.firstName,
+ lastName: eventProperties.user.lastName,
+ },
+ payload: { eventProperties },
+ };
+ const endpoint = settings.novuEndpoint;
+ console.log("endpoint:", endpoint);
+
+ const ApiKey = settings.novuApiKey; // Your NOVU API key
+ if (eventProperties.environment === settings.environment) {
+ let response;
+ try {
+ response = await fetch(endpoint, {
+ method: "POST",
+ headers: {
+ Authorization: `ApiKey ${ApiKey}`,
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(payload),
+ });
+ } catch (error) {
+ // Retry on connection error
+ throw new RetryError(error.message);
+ }
+ if (response.status >= 500 || response.status === 429) {
+ // Retry on 5xx (server errors) and 429s (rate limits)
+ throw new RetryError(`Failed with ${response.status}`);
+ }
+ }
+}
+```
+
+#### Create Settings and Secrets
+
+Segment's settings allow you to pass configurable variables to your function, which is the best way to pass sensitive information such as security tokens. For example, you might use settings as placeholders to use information such as an API endpoint and API key.
+You can learn more about it [here](https://segment.com/docs/connections/functions/destination-functions/#create-settings-and-secrets).
+
+
+
+
+
+Click `Add Setting` to add your new setting.
+
+
+
+
+
+Now, while configuring the function, Add these three variables to be then used in the code exposed in the settings function param.
+
+
+
+
+
+#### Test the destination function
+
+You can test your code directly from the editor in two ways:
+
+**1. Use sample events for testing**
+Click `Use Sample Event` and select the source to use events from.
+
+
+
+
+
+Click `Run` to test your function with the event you selected.
+
+**2. Test using manual input**
+You can also manually include your own JSON payload of a Segment event, instead of fetching a sample from one of your workspace sources.
+
+
+
+
+
+**Here is the the event example JSON we will use**
+
+```JSON
+{
+ "type": "track",
+ "event": "User Abandoned Cart",
+ "properties": {
+ "name": "abandoned-cart-recovery-workflow",
+ "user": {
+ "subscriberId": "63da8ee0c037e013fd790ffd",
+ "email": "hi@hi.com",
+ "firstName": "John",
+ "lastName": "Doe"
+ },
+ "environment": "development"
+ }
+}
+```
+
+We will now execute the function based on the manual event input we've provided. This function sends a trigger to Novu, prompting to take action and send the user an email to return and the purchase.
+
+
+
+
+
+Whether you chose the first or second option to test your Destination Function, you can also check if the function triggered your workflow and whether it was delivered through Novu's [Activity Feed](https://dashboard-v2.novu.co/activities?utm_campaign=docs-guides-segment).
+
+
+
+
+
+This guide was inspired by the following resources:
+
+- https://discord.com/channels/895029566685462578/1060308007658987571/1077377322547687475
+- https://segment.com/docs/getting-started/05-data-to-destinations/
+- https://aviyel.com/post/3381/how-to-integrate-novu-with-segment
diff --git a/introduction.mdx b/introduction.mdx
index 27f9d09b0..308879d56 100644
--- a/introduction.mdx
+++ b/introduction.mdx
@@ -1,6 +1,6 @@
---
title: Introduction
-description: 'Welcome to the home of novu documentation!'
+description: "Welcome to the home of novu documentation!"
---
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+Let's build and run our iOS application to see if everything works correctly.
+
+
+ {" "}
+
+
+Go to the Firebase documentation website, go to docs here, and select Cloud Messaging.
+We will follow this guide to set up cloud messaging inside the app.
+
+You can read more about how Firebase Cloud Messaging works by reading their [official documentation](https://firebase.google.com/docs/cloud-messaging/ios/client).
+
+
+ {" "}
+
+
+Go to iOS+ and click on the `Set up an Apple platforms client` section.
+
+
+ {" "}
+
+
+The first thing that we need to do is add Firebase to our iOS app.
+Let's create a new Firebase project inside of the console.
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+## Create a Firebase project
+
+Select a name for your project.
+
+
+ {" "}
+
+
+Then, add Google Analytics to the Firebase project.
+
+
+ {" "}
+
+
+Here, you can select your Google account.
+
+
+ {" "}
+
+
+ {" "}
+
+
+We will click on Add Firebase to your iOS app.
+
+
+ {" "}
+
+
+We first need to add the bundle name, so go to your iOS Xcode project and copy and paste the bundle name.
+
+
+ {" "}
+
+
+ {" "}
+
+
+Download the `.plist` file and put it in the root of your project.
+
+
+ {" "}
+
+
+ {" "}
+
+
+You can put it right under `info.plist` file.
+
+
+ {" "}
+
+
+We need to add the Firebase SDK using the Swift package manager.
+Copy this https://github.com/firebase/firebase-ios-sdk URL and then go to 'File`->`Add Package Dependencies...`.
+Paste that URL in the top right.
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+We must add the initialization code to the `AppDelegates.swift` file.
+
+Let's import the "FirebaseCore" dependency by adding `import FirebaseCore` to the beginning of the file.
+
+Then, we will copy `firebaseapp.configure()` and place it in `didFinishLaunchingWithOptions` method.
+
+
+ {" "}
+
+
+```Swift
+
+//
+// AppDelegate.swift
+// PushNotificationDemo
+//
+// Created by Emillien Pearce.
+//
+
+import UIKit
+import FirebaseCore //Here
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ // Override point for customization after application launch.
+ FirebaseApp.configure() //Here
+ FirebaseConfiguration.shared.setLoggerLevel(.min)
+ return true
+ }
+
+ // MARK: UISceneSession Lifecycle
+
+ func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+ // Called when a new scene session is being created.
+ // Use this method to select a configuration to create the new scene with.
+ return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+ }
+
+ func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
+ // Called when the user discards a scene session.
+ // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+ // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+ }
+
+
+}
+
+```
+
+Click 'Next' and continue to the console.
+
+
+ {" "}
+
+
+ {" "}
+
+
+Let's build and run our project and see if we get Firebase log messages in the console.
+
+
+ {" "}
+
+
+ {" "}
+
+
+## Create and upload our APNs authentication key
+
+We will create and upload our APNs authentication key to the Firebase project settings.
+
+
+ {" "}
+
+
+Navigate to [Apple Developer Member Center](https://developer.apple.com/account).
+
+Head to the "Keys" section under "Certificates, IDs & Profiles".
+
+
+ {" "}
+
+
+Create a new key.
+
+
+ {" "}
+
+
+Select "Apple Push Notification Service".
+
+
+ {" "}
+
+
+Click "Register".
+
+
+ {" "}
+
+
+We have to download this key and upload it into Firebase.
+
+
+ {" "}
+
+
+Head to "Project Settings".
+
+
+ {" "}
+
+
+Click on Cloud Messaging, then click "Upload APNs Authentication Key".
+
+
+ {" "}
+
+
+Now we can upload the dots p8 file.
+
+
+ {" "}
+
+
+You must enter your `Key ID` and `Team ID`, which you can find in the top right corner.
+
+
+ {" "}
+
+
+ {" "}
+
+
+## Register for Remote Notifications
+
+
+ {" "}
+
+
+1. Copy this code block and place it inside the `AppDelegate.swift` file using the `didFinishLaunchingWithOptions` method.
+ We paste this code block under `firebaseApp.configure()`.
+
+2. We need to conform to this delegate, so we will also create an `AppDelegate` extension at the bottom for `UNUserNotificationCenterDelegate`.
+
+3. Add `import FirebaseMessaging` to the file.
+
+```Swift
+
+//
+// AppDelegate.swift
+// PushNotificationDemo
+//
+// Created by Emillien Pearce.
+//
+
+import UIKit
+import FirebaseCore
+import FirebaseMessaging
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ // Override point for customization after application launch.
+ FirebaseApp.configure()
+
+ // Register for Remote Notitifcations
+
+ UNUserNotificationCenter.current().delegate = self
+
+ let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
+ UNUserNotificationCenter.current().requestAuthorization(
+ options: authOptions,
+ completionHandler: { _, _ in }
+ )
+
+ application.registerForRemoteNotifications()
+
+
+ return true
+ }
+
+ // MARK: UISceneSession Lifecycle
+
+ func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+ // Called when a new scene session is being created.
+ // Use this method to select a configuration to create the new scene with.
+ return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+ }
+
+ func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
+ // Called when the user discards a scene session.
+ // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+ // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+ }
+
+
+}
+
+extension AppDelegate: UNUserNotificationCenterDelegate {
+
+}
+
+```
+
+## Access the Registration Token
+
+To do this, we must first set the `Messaging.messaging().delegate = self` inside the `didFinishLaunchingWithOptions` method.
+
+
+ {" "}
+
+
+ {" "}
+
+
+We will now add a 'Messaging' delegate extension to `AppDelegate.swift` file.
+
+
+ {" "}
+
+
+```Swift
+
+//
+// AppDelegate.swift
+// PushNotificationDemo
+//
+// Created by Emillien Pearce on 13/01/2024.
+//
+
+import UIKit
+import FirebaseCore
+import FirebaseMessaging
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ // Override point for customization after application launch.
+ FirebaseApp.configure()
+ FirebaseConfiguration.shared.setLoggerLevel(.min)
+
+
+ // Register for Remote Notitifcations
+
+ UNUserNotificationCenter.current().delegate = self
+
+ let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
+ UNUserNotificationCenter.current().requestAuthorization(
+ options: authOptions,
+ completionHandler: { _, _ in }
+ )
+
+ application.registerForRemoteNotifications()
+
+ // Messaging Delegate
+
+ Messaging.messaging().delegate = self
+
+
+ return true
+ }
+
+ // MARK: UISceneSession Lifecycle
+
+ func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+ // Called when a new scene session is being created.
+ // Use this method to select a configuration to create the new scene with.
+ return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+ }
+
+ func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
+ // Called when the user discards a scene session.
+ // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+ // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+ }
+
+
+}
+
+extension AppDelegate: UNUserNotificationCenterDelegate {
+
+ // Receive displayed notifications for iOS 10 devices.
+ func userNotificationCenter(_ center: UNUserNotificationCenter,
+ willPresent notification: UNNotification) async
+ -> UNNotificationPresentationOptions {
+ let userInfo = notification.request.content.userInfo
+
+ // With swizzling disabled you must let Messaging know about the message, for Analytics
+ // Messaging.messaging().appDidReceiveMessage(userInfo)
+
+ // ...
+
+ // Print full message.
+ print(userInfo)
+
+ // Change this to your preferred presentation option
+ return [[.alert, .sound]]
+ }
+
+ func userNotificationCenter(_ center: UNUserNotificationCenter,
+ didReceive response: UNNotificationResponse) async {
+ let userInfo = response.notification.request.content.userInfo
+
+ // ...
+
+ // With swizzling disabled you must let Messaging know about the message, for Analytics
+ // Messaging.messaging().appDidReceiveMessage(userInfo)
+
+ // Print full message.
+ print(userInfo)
+ }
+ }
+
+
+
+extension AppDelegate: MessagingDelegate {
+
+ func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
+ print("Firebase registration token: \(String(describing: fcmToken))")
+
+ let dataDict: [String: String] = ["token": fcmToken ?? ""]
+ NotificationCenter.default.post(
+ name: Notification.Name("FCMToken"),
+ object: nil,
+ userInfo: dataDict
+ )
+ // TODO: If necessary send token to application server.
+ // Note: This callback is fired at each app startup and whenever a new token is generated.
+ }
+
+
+}
+
+```
+
+## Receive messages in an Apple App
+
+1. Copy this code block and place it in `UNUserNotificationCenterDelegate` extension.
+2. Add the `didReceiveRemoteNotification`.
+3. We must declare a `gcmMessageIDKey` inside of `AppDelegate`. We can define this as a `string` variable.
+
+
+ {" "}
+
+
+```Swift
+
+//
+// AppDelegate.swift
+// PushNotificationDemo
+//
+// Created by Emillien Pearce.
+//
+
+import UIKit
+import FirebaseCore
+import FirebaseMessaging
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+ let gcmMessageIDKey = "gcm.Message_ID"
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ // Override point for customization after application launch.
+ FirebaseApp.configure()
+ FirebaseConfiguration.shared.setLoggerLevel(.min)
+
+
+ // Register for Remote Notitifcations
+
+ UNUserNotificationCenter.current().delegate = self
+
+ let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
+ UNUserNotificationCenter.current().requestAuthorization(
+ options: authOptions,
+ completionHandler: { _, _ in }
+ )
+
+ application.registerForRemoteNotifications()
+
+ // Messaging Delegate
+
+ Messaging.messaging().delegate = self
+
+
+ return true
+ }
+
+ // MARK: UISceneSession Lifecycle
+
+ func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+ // Called when a new scene session is being created.
+ // Use this method to select a configuration to create the new scene with.
+ return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+ }
+
+ func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
+ // Called when the user discards a scene session.
+ // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+ // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+ }
+
+
+}
+
+extension AppDelegate: UNUserNotificationCenterDelegate {
+
+ // Receive displayed notifications for iOS 10 devices.
+ func userNotificationCenter(_ center: UNUserNotificationCenter,
+ willPresent notification: UNNotification) async
+ -> UNNotificationPresentationOptions {
+ let userInfo = notification.request.content.userInfo
+
+ // With swizzling disabled you must let Messaging know about the message, for Analytics
+ // Messaging.messaging().appDidReceiveMessage(userInfo)
+
+ // ...
+
+ // Print full message.
+ print(userInfo)
+
+ // Change this to your preferred presentation option
+ return [[.alert, .sound]]
+ }
+
+ func userNotificationCenter(_ center: UNUserNotificationCenter,
+ didReceive response: UNNotificationResponse) async {
+ let userInfo = response.notification.request.content.userInfo
+
+ // ...
+
+ // With swizzling disabled you must let Messaging know about the message, for Analytics
+ // Messaging.messaging().appDidReceiveMessage(userInfo)
+
+ // Print full message.
+ print(userInfo)
+ }
+
+ func application(_ application: UIApplication,
+ didReceiveRemoteNotification userInfo: [AnyHashable: Any]) async
+ -> UIBackgroundFetchResult {
+ // If you are receiving a notification message while your app is in the background,
+ // this callback will not be fired till the user taps on the notification launching the application.
+ // TODO: Handle data of notification
+
+ // With swizzling disabled you must let Messaging know about the message, for Analytics
+ // Messaging.messaging().appDidReceiveMessage(userInfo)
+
+ // Print message ID.
+ if let messageID = userInfo[gcmMessageIDKey] {
+ print("Message ID: \(messageID)")
+ }
+
+ // Print full message.
+ print(userInfo)
+
+ return UIBackgroundFetchResult.newData
+ }
+
+
+ }
+
+
+
+extension AppDelegate: MessagingDelegate {
+
+ func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
+ print("Firebase registration token: \(String(describing: fcmToken))")
+
+ let dataDict: [String: String] = ["token": fcmToken ?? ""]
+ NotificationCenter.default.post(
+ name: Notification.Name("FCMToken"),
+ object: nil,
+ userInfo: dataDict
+ )
+ // TODO: If necessary send token to application server.
+ // Note: This callback is fired at each app startup and whenever a new token is generated.
+ }
+
+
+}
+
+```
+
+## Adding app capabilities
+
+
+ {" "}
+
+
+Click on the plus sign (+) and select `Background Modes`.
+
+
+ {" "}
+
+
+**Select the following options:**
+
+- Background Fetch
+- Remote Notifications
+- Background Processing
+
+
+ {" "}
+
+
+Add `Push Notifications` capabilities.
+
+
+ {" "}
+
+
+## App Build
+
+
+ {" "}
+
+
+It will ask if you want to receive notifications, and we will allow it.
+
+
+ {" "}
+
+
+## Cloud Message Test
+
+In your Firebase project, navigate to 'engage' section and click on 'messaging'.
+
+
+ {" "}
+
+
+Click on "Send your first message".
+
+
+ {" "}
+
+
+ {" "}
+
+
+We're going to enter the `notification title` and the `notification text`, then we're going to send the test message.
+
+
+ {" "}
+
+
+We must copy and paste this FCM registration token to confirm our device (A physical or a simulator). You can find it in your Xcode console.
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+Click on 'Test'.
+
+
+ {" "}
+
+
+You should see the notification on your device!
+
+
+ {" "}
+
+
+## Novu account creation
+
+
+ {" "}
+
+
+You can immediately configure FCM as a Push channel provider or navigate to the Integration Store.
+
+
+ {" "}
+
+
+## Connecting FCM as a provider
+
+
+ {" "}
+
+
+ {" "}
+
+
+You only need to configure FCM with Novu with the Firebase Service Accounts private key.
+
+To acquire the account key JSON file for your service account, follow this instructions:
+
+1. Select your project. Click the gear icon on the top of the sidebar.
+2. Head to project settings.
+3. Navigate to the service account tab.
+4. Click "Generate New Private Key", then confirm by clicking "Generate Key".
+5. Clicking Generate Key will download the JSON file.
+6. Once the file is on your machine, paste the entire JSON file content in the Service Account field of the FCM provider in the integration store on Novuâs web dashboard.
+
+Make sure your service account key JSON content contains these fields:
+
+```JSON
+
+{
+ "type": "service_account",
+ "project_id": "PROJECT_ID",
+ "private_key_id": "PRIVATE_KEY_ID",
+ "private_key": "PRIVATE_KEY",
+ "client_email": "FIREBASE_ADMIN_SDK_EMAIL",
+ "client_id": "CLIENT_ID",
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+ "token_uri": "https://oauth2.googleapis.com/token",
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+ "client_x509_cert_url": "CLIENT_X509_CERT_URL"
+}
+
+```
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+## Creating a workflow
+
+In Novu, creating a workflow means establishing a blueprint for sending notifications within your app. This unified structure ties together email, in-app messages, SMS, push notifications, and chat into **one entity**.
+
+Each workflow has a unique name and identifier and includes customized content for various channels, using `{{handlebars}}` variables for personalization.
+
+This ensures consistent platform notifications and allows dynamic adjustments for individual subscribers, scenarios, and use cases.
+
+Workflow creation is for streamlining automated notifications, enabling teams to communicate effectively without extensive technical expertise.
+
+
+
+
+ {" "}
+
+
+ {" "}
+
+
+
+
+ {" "}
+
+
+
+
+ {" "}
+
+
+
+
+## Creating a subscriber
+
+Creating a subscriber in Novu refers to the process of establishing a subscriber entity within the Novu platform. A subscriber is essentially the recipient of the notifications sent through Novu's system. When you create a subscriber, you're setting up the necessary information for Novu to send targeted notifications to that individual.
+
+
+ {" "}
+
+
+
+
+
+
+ ```JSON
+
+ curl --location 'https://api.novu.co/v1/subscribers' \
+
+--header 'Content-Type: application/json' \
+ --header 'Accept: application/json' \
+ --header 'Authorization: ApiKey ' \
+ --data-raw '{
+"subscriberId": "12345678",
+"firstName": "Pawan",
+"lastName": "Jain",
+"email": "pawan.jain@domain.com",
+"phone": "+1234567890",
+"avatar": "avatar-url",
+"locale": "en-US",
+"data": {
+"isDeveloper": true,
+"customKey": "customValue"
+}
+}'
+
+```
+
+
+
+
+
+
+
+
+
+
+ Subscriber can have multiple device tokens
+
+ Here, you can locate the Provider_Identifier.
+
+
+
+```JSON
+
+ curl --request PUT \
+ --url https://api.novu.co/v1/subscribers/{subscriber_id}/credentials \
+--header 'Content-Type: application/json' \
+ --header 'Authorization: ApiKey ' \
+ --data '{
+ "credentials":{
+ "deviceTokens": ["token1", "token2"]
+},
+ "integrationIdentifier":"",
+ "providerId":"fcm"
+}'
+
+```
+
+
+
+
+
+## Sending a notification to iOS device with Novu
+
+To send a notification with Novu, you are actually triggering a notification workflow.
+You have the ability to test the trigger using the user interface or by calling Novu's API.
+
+**Trigger a workflow via the API**
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "untitled",
+ "to": {
+ "subscriberId": ""
+ },
+ "payload": {}
+ }'
+
+```
+
+
+ {" "}
+
+
+## Dynamic Content
+
+When we were creating the first workflow, we "Hardcoded" the content of the notification.
+
+Now, we will determine the content when calling the API.
+
+1. In the workflow, we should change the values of the `title` and the `body` to `{{title}}` and `{{body}}`.
+ That way, we could insert values through the payload of the API call.
+
+
+ {" "}
+
+
+2. Add a 'payload' object to the API call.
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "untitled",
+ "to": {
+ "subscriberId": "12345678"
+ },
+ "payload": {
+ "title": "This title was set via the Payload",
+ "body": "Payload notification body"
+ },
+ }'
+
+```
+
+
+ {" "}
+
+
+## Sound of a notification
+
+The name of a sound file in your app's main bundle or in the Library/Sounds folder of your app's container directory.
+Specify the string "default" to play the system sound.
+
+Use this key for regular notifications. For critical alerts, use the sound dictionary instead.
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "untitled",
+ "to": {
+ "subscriberId": "12345678"
+ },
+ "payload": {
+ "title": "Notification With Sound",
+ "body": "Hello World from Novu"
+ },
+ "overrides": {
+ "fcm": {
+ "apns": {
+ "payload": {
+ "aps": {
+ "sound": "default" // configure sound to the notification
+ }
+ }
+ }
+ }
+ }
+ }'
+
+```
+
+## Priority for notification
+
+If you omit this header, APNs set the notification priority to `10`.
+
+Specify `10` to send the notification immediately.
+
+Specify `5` to send the notification based on power considerations on the userâs device.
+
+Specify `1` to prioritize the deviceâs power considerations over all other factors for delivery and prevent awakening the device.
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "untitled",
+ "to": {
+ "subscriberId": "12345678"
+ },
+ "payload": {
+ "title": "apns-priority: 5",
+ "body": "Novu's API"
+ },
+ "overrides": {
+ "fcm": {
+ "apns": {
+ "headers": {
+ "apns-priority":"5" //priority for notifications
+ },
+ "payload": {
+ "aps": {}
+ },
+ "fcm_options": {}
+ }
+ }
+ }
+ }'
+
+```
+
+## Sending images
+
+Up to this point, your notifications have all contained only text. But if youâve received many notifications, you know that notifications can have rich content, such as images. Itâd be great if your notifications showed users a nice image related to their content. Once again, Firebase makes this super simple.
+
+To show an image in push notifications, youâll need to create a **_Notification Service Extension_**. This is a separate target in your app that runs in the background when your user receives a push notification. The service extension can receive a notification and change its contents before iOS shows the notification to the user.
+Youâll use Firebase to send an image URL inside a notification.
+Youâll then use a content extension to download the image and add it to the notificationâs content.
+
+In Xcode, go to File âž New âž TargetâŠ. Search for Notification Service Extension and select Next. Set a name and configure it to add to your main project.
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+Select **Finish**, and when prompted, select **Activate**.
+
+
+ {" "}
+
+
+When you added the Firebase package to your project, it was only added to the your "main" (In my case it's "PushNotificationDemo") target, so now you need to add the necessary dependency to your new extension.
+Open your appâs project settings and select the name you picked for the extention under Targets.
+
+Under Frameworks and Libraries, select the + button, and search for FirebaseMessaging. Then, select Add. Your project should reflect the image below:
+
+
+ {" "}
+
+
+Select the + button, and search for FirebaseMessaging. Then, select Add.
+
+
+ {" "}
+
+
+ {" "}
+
+
+Now, open `NotificationService.swift`. This file is where you can customize notifications before the user sees them.
+
+First, add the following import to the top of the file:
+`import FirebaseMessaging`
+
+Next, replace the contents of `didReceive(_:withContentHandler:)` with the following:
+
+```Swift
+
+self.contentHandler = contentHandler
+bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
+
+if let bestAttemptContent = bestAttemptContent {
+// Modify the notification content here...
+bestAttemptContent.title = "\(bestAttemptContent.title)"
+
+// Call FIRMessaging extension helper API.
+
+if let messagingContentHandler = self.contentHandler {
+Messaging.serviceExtension().populateNotificationContent(bestAttemptContent, withContentHandler: messagingContentHandler)
+ }
+}
+
+```
+
+Typically, youâd have to search the field containing the image URL, download the image, and finish the presentation with the picture as an attachment.
+Here, youâre using Firebaseâs `FIRMessagingExtensionHelper` to perform all that work automatically in a straightforward helper method call.
+
+Remember, iOS only allows you to download your attached image. If the extensionâs code takes too long to run, the system will call `serviceExtensionTimeWillExpire()`.
+This gives you a chance to gracefully finish up anything you are doing in the extension or to simply present the notification as is, which is the default implementation.
+
+This is the entire `NotificationService.swift` file.
+
+```Swift
+
+//
+// NotificationService.swift
+// Rich Notifications
+//
+// Created by Emillien Pearce.
+//
+
+import UserNotifications
+import FirebaseMessaging
+
+class NotificationService: UNNotificationServiceExtension {
+
+ var contentHandler: ((UNNotificationContent) -> Void)?
+ var bestAttemptContent: UNMutableNotificationContent?
+
+ override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
+
+ self.contentHandler = contentHandler
+ bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
+
+ if let bestAttemptContent = bestAttemptContent {
+ // Modify the notification content here...
+ bestAttemptContent.title = "\(bestAttemptContent.title)"
+
+ // Call FIRMessaging extension helper API.
+ if let messagingContentHandler = self.contentHandler {
+ Messaging.serviceExtension().populateNotificationContent(bestAttemptContent, withContentHandler: messagingContentHandler)
+ }
+ }
+ }
+
+ override func serviceExtensionTimeWillExpire() {
+ // Called just before the extension will be terminated by the system.
+ // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
+ if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
+ contentHandler(bestAttemptContent)
+ }
+ }
+
+}
+
+```
+
+Let's **rebuild** our app again!
+
+
+ {" "}
+
+
+When making the API call, we should include:
+
+- "mutable-content": 1 inside the "aps" object.
+- "image" in "fcm_options" object,
+- URL address of the image.
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "untitled",
+ "to": {
+ "subscriberId": "12345678"
+ },
+ "payload": {
+ "title": "This is a notification with an image",
+ "body": "Check this out"
+ },
+ "overrides": {
+ "fcm": {
+ "apns": {
+ "headers": {},
+ "payload": {
+ "aps": {
+ "mutable-content": 1
+ }
+ },
+ "fcm_options": {
+ "image": "https://www.planetware.com/wpimages/2020/02/france-in-pictures-beautiful-places-to-photograph-eiffel-tower.jpg"
+ }
+ }
+ }
+ }
+ }'
+
+```
+
+
+ {" "}
+
+
+ {" "}
+
+
+## Sending actionable notifications
+
+1. Define Notification Actions:
+
+In your `AppDelegate.swift` file, you should define the notification actions you want to add.
+You can do this by creating a `UNNotificationAction` for each action you want to include.
+For example, let's add two actions: "Accept" and "Reject".
+
+```Swift
+
+// Add these lines inside your AppDelegate class, preferably below the existing extensions.
+
+extension UNNotificationAction {
+ static let accept = UNNotificationAction(
+ identifier: "ACCEPT_ACTION",
+ title: "Accept",
+ options: [.foreground]
+ )
+
+ static let reject = UNNotificationAction(
+ identifier: "REJECT_ACTION",
+ title: "Reject",
+ options: [.destructive, .foreground]
+ )
+}
+
+```
+
+2. Register Notification Category:
+
+ You need to register the notification category with the actions you defined in your `didFinishLaunchingWithOptions` method:
+
+ ```
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ // ... (your existing code)
+
+ // Register notification category
+ let acceptAction = UNNotificationAction.accept
+ let rejectAction = UNNotificationAction.reject
+
+ let messageCategory = UNNotificationCategory(
+ identifier: "MESSAGE_CATEGORY",
+ actions: [acceptAction, rejectAction],
+ intentIdentifiers: [],
+ options: []
+ )
+
+ UNUserNotificationCenter.current().setNotificationCategories([messageCategory])
+
+ return true
+
+ }
+
+```
+
+3. Handle Action Taps:
+
+Now, you need to handle the action taps in the `userNotificationCenter(_:didReceive response:)` method of your `AppDelegate`.
+You can check which action was tapped by inspecting the `response.actionIdentifier` property:
+
+```Swift
+
+func userNotificationCenter(_ center: UNUserNotificationCenter,
+ didReceive response: UNNotificationResponse) async {
+ let userInfo = response.notification.request.content.userInfo
+
+ if response.actionIdentifier == UNNotificationAction.accept.identifier {
+ // Handle the "Accept" action
+ print("User tapped Accept")
+ // Perform the desired action for "Accept"
+ } else if response.actionIdentifier == UNNotificationAction.reject.identifier {
+ // Handle the "Reject" action
+ print("User tapped Reject")
+ // Perform the desired action for "Reject"
+ } else {
+ // Handle other actions or default behavior
+ print("User tapped an action with identifier: \(response.actionIdentifier)")
+ }
+}
+
+```
+
+Your full `AppDelegate.swift` file should look like this:
+
+```Swift
+
+//
+// AppDelegate.swift
+// PushNotificationDemo
+//
+// Created by Emillien Pearce.
+//
+
+import UIKit
+import FirebaseCore
+import FirebaseMessaging
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+ let gcmMessageIDKey = "gcm.Message_ID"
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ // Override point for customization after application launch.
+ FirebaseApp.configure()
+ FirebaseConfiguration.shared.setLoggerLevel(.min)
+
+
+ // Register for Remote Notitifcations
+
+ UNUserNotificationCenter.current().delegate = self
+
+ let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
+ UNUserNotificationCenter.current().requestAuthorization(
+ options: authOptions,
+ completionHandler: { _, _ in }
+ )
+
+ application.registerForRemoteNotifications()
+
+ // Register notification category
+ let acceptAction = UNNotificationAction.accept
+ let rejectAction = UNNotificationAction.reject
+
+ let messageCategory = UNNotificationCategory(
+ identifier: "MESSAGE_CATEGORY",
+ actions: [acceptAction, rejectAction],
+ intentIdentifiers: [],
+ options: []
+ )
+
+ UNUserNotificationCenter.current().setNotificationCategories([messageCategory])
+
+ // Messaging Delegate
+
+ Messaging.messaging().delegate = self
+
+
+ return true
+ }
+
+ // MARK: UISceneSession Lifecycle
+
+ func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+ // Called when a new scene session is being created.
+ // Use this method to select a configuration to create the new scene with.
+ return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+ }
+
+ func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
+ // Called when the user discards a scene session.
+ // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+ // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+ }
+
+
+}
+
+extension AppDelegate: UNUserNotificationCenterDelegate {
+
+ // Receive displayed notifications for iOS 10 devices.
+ func userNotificationCenter(_ center: UNUserNotificationCenter,
+ willPresent notification: UNNotification) async
+ -> UNNotificationPresentationOptions {
+ let userInfo = notification.request.content.userInfo
+
+ // With swizzling disabled you must let Messaging know about the message, for Analytics
+ // Messaging.messaging().appDidReceiveMessage(userInfo)
+
+ // ...
+
+ // Print full message.
+ print(userInfo)
+
+ // Change this to your preferred presentation option
+ return [[.alert, .sound]]
+ }
+
+ func userNotificationCenter(_ center: UNUserNotificationCenter,
+ didReceive response: UNNotificationResponse) async {
+ let userInfo = response.notification.request.content.userInfo
+
+ if response.actionIdentifier == UNNotificationAction.accept.identifier {
+ // Handle the "Accept" action
+ print("User tapped Accept")
+ // Perform the desired action for "Accept"
+ } else if response.actionIdentifier == UNNotificationAction.reject.identifier {
+ // Handle the "Reject" action
+ print("User tapped Reject")
+ // Perform the desired action for "Reject"
+ } else {
+ // Handle other actions or default behavior
+ print("User tapped an action with identifier: \(response.actionIdentifier)")
+ }
+
+ // ...
+
+ // With swizzling disabled you must let Messaging know about the message, for Analytics
+ // Messaging.messaging().appDidReceiveMessage(userInfo)
+
+ // Print full message.
+ print(userInfo)
+
+
+ }
+
+ func application(_ application: UIApplication,
+ didReceiveRemoteNotification userInfo: [AnyHashable: Any]) async
+ -> UIBackgroundFetchResult {
+ // If you are receiving a notification message while your app is in the background,
+ // this callback will not be fired till the user taps on the notification launching the application.
+ // TODO: Handle data of notification
+
+ // With swizzling disabled you must let Messaging know about the message, for Analytics
+ // Messaging.messaging().appDidReceiveMessage(userInfo)
+
+ // Print message ID.
+ if let messageID = userInfo[gcmMessageIDKey] {
+ print("Message ID: \(messageID)")
+ }
+
+ // Print full message.
+ print(userInfo)
+
+
+
+ return UIBackgroundFetchResult.newData
+ }
+
+
+ }
+
+
+
+extension AppDelegate: MessagingDelegate {
+
+ func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
+ print("Firebase registration token: \(String(describing: fcmToken))")
+
+ let dataDict: [String: String] = ["token": fcmToken ?? ""]
+ NotificationCenter.default.post(
+ name: Notification.Name("FCMToken"),
+ object: nil,
+ userInfo: dataDict
+ )
+ // TODO: If necessary send token to application server.
+ // Note: This callback is fired at each app startup and whenever a new token is generated.
+ }
+
+
+}
+
+extension UNNotificationAction {
+ static let accept = UNNotificationAction(
+ identifier: "ACCEPT_ACTION",
+ title: "Accept",
+ options: [.foreground]
+ )
+
+ static let reject = UNNotificationAction(
+ identifier: "REJECT_ACTION",
+ title: "Reject",
+ options: [.destructive, .foreground]
+ )
+}
+
+```
+
+Now, letâs trigger a notification with actionable buttons:
+
+```JSON
+
+curl --location --request POST "https://api.novu.co/v1/events/trigger" \
+ --header "Authorization: ApiKey 4de014990cfb201033014548be2db904" \
+ --header "Content-Type: application/json" \
+ --data-raw '{
+ "name": "untitled",
+ "to": {
+ "subscriberId": "12345678"
+ },
+ "payload": {
+ "title": "New Mission",
+ "body": "Your mission, should you choose to accept it,"
+ },
+ "overrides": {
+ "fcm": {
+ "apns": {
+ "payload": {
+ "aps": {
+ "category": "MESSAGE_CATEGORY"
+ }
+ }
+ }
+ }
+ }
+}'
+
+```
+
+
+ {" "}
+
+
+## Additional resources
+
+- [Generating a remote notification by Apple](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification)
+- [Sending notification requests to APNs](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns)
diff --git a/legacy-guides/add-digest-to-email-notifications.mdx b/legacy-guides/add-digest-to-email-notifications.mdx
new file mode 100644
index 000000000..5b9151746
--- /dev/null
+++ b/legacy-guides/add-digest-to-email-notifications.mdx
@@ -0,0 +1,280 @@
+---
+title: "How to Add Digest to Email Notifications"
+description: "Use the digest functionality to send email notifications"
+---
+
+# Introduction
+
+In this guide, youâll learn how to add digest functionality to email notifications. But before exploring the actual code, letâs understand what a digest notification is and how it works.
+
+You can find the entire code(frontend as well as backend) for this app [here](https://github.com/novuhq/digest-email-app).
+
+
+ If, instead, you want to add digest to in-app notifications, we have a guide for that as well. Take a look [here](/legacy-guides/add-digest-to-inapp-notifications).
+
+
+### What is a digest notification?
+
+Often when you associate notifications with user activity, the end user can be bombarded with messages because of the nature of the activity. Take for example the case of commenting in the context of a social media app. If you were to send a notification to a user for every comment they receive, and they happen to receive 100 comments, it could lead to user fatigue since you would have to send 100 messages.
+
+This is where digest notifications come into the picture!
+
+A digest notification is a notification that consolidates information from several notifications into one and delivers that notification to the end user instead of several separate messages.
+
+### How does digest notification work?
+
+Novu has a built-in digest engine that collects multiple trigger events, aggregates them into a single message, and delivers it to the subscriber. You can use the digest engine by adding a âdigest nodeâ to your workflow in the workflow editor in the [Novu dashboard](https://dashboard-v2.novu.co/workflows?utm_campaign=docs-digests). If you want to learn more about it, [this](/workflow/digest) is a great place to start.
+
+Letâs see it in action now!
+
+# Add digest notification to an application
+
+To get started with this, you need the following:
+
+- A Novu account. [Sign up for free](http://dashboard.novu.co/?utm_campaign=docs-gs-digests) if you donât have one yet.
+- A working React development environment.
+
+# Workflow setup in Novu
+
+Once, you have these, follow the steps below:
+
+1. Head over to the Novu Dashboard.
+2. Click **"Workflows"** on the left sidebar of your Novu dashboard.
+3. Click the **"Create Workflow"** button on the top right:
+
+ {" "}
+
+ Once you click the `create workflow` button, youâll see a dropdown. Select `blank
+ workflow` from the dropdown:
+
+ {" "}
+
+ Youâll now be taken to the workflow editor:
+
+ {" "}
+
+ Once here, you can add the channels you want to use for sending notifications
+ and configure them. For this guide, weâll use the `Email` channel. Youâll also
+ see the `Digest` action on the right sidebar.
+
+
+ Each node that is added below the digest node will only be triggered after the
+ specified time interval
+
+
+For example, in our case, say we want the email notification to be sent after every 6 hours. So, add the `digest` action below the `trigger node`, and add the `email` channel node below the `digest` node as shown below:
+
+
+ {" "}
+
+The `digest` node allows you to set a specific time interval for when notifications
+should be sent:
+
+ {" "}
+
+Once, youâve configured it. Go ahead and configure the `email` channel as per your
+need:
+
+ {" "}
+
+Hereâs a brief explanation of all the options:
+
+- **1-Preview:**Â This shows you a glimpse of what the email notification item will look like when delivered to the client.
+- **2-Sender Name:**Â Lets you set the sender name for emails that the client will receive.
+- **3-Subject:**Â This lets you define the subject line for the emails that the client will receive.
+- **4-Filter:**Â This feature allows you to configure the criteria for delivering notifications. For instance, you can apply a filter based on a subscriber's online status to send them an email if they were online within the last hour.
+- **5-Custom Code**Â - In custom code, you can write custom digest templates to show some/all parts of a message.
+- **6-Test**Â - This allows you to send a test email to test if everything is working as per your wish.
+
+You can write your own digest template in the 'custom code' section or just follow this guide as shown in the picture above. Once youâre done configuring this to your liking, click on the `update` button on the top right.
+
+Itâll automatically create a trigger code that you can use in your app. To get it, click on the `get snippet` button on the top right and copy it:
+
+
+ {" "}
+
+Now, letâs see how to add Novu to our app!
+
+# Add Novu to the Backend and Configure it
+
+In your backend, install the novu package using the following code:
+
+```bash
+npm install @novu/node
+
+```
+
+Now, create a route that you want to hit when called from the front end. In our demo app, this is the route:
+
+```jsx
+import express from "express";
+
+import { getEmailDigest } from "../controller/emaildigest.js";
+
+const router = express.Router();
+
+router.post("/sending-email-digest", getEmailDigest);
+
+export default router;
+```
+
+Now, we need to write a controller function that will handle the logic for what is to be sent in the trigger functionâs payload. In our case, this is the controller function:
+
+```jsx
+import { sendEmailDigest } from "../novu/novu.js";
+
+export const getEmailDigest = async (req, res) => {
+ const { notif, email } = req.body;
+ try {
+ await sendEmailDigest(notif, email);
+ res.status(201).json({ message: "success", notif: notif });
+ } catch (error) {
+ res.status(409).json({ message: error.message });
+ }
+};
+```
+
+To make it modular, weâll keep the trigger code in a separate function in a separate file (`novu.js`, in our case) and the trigger function is getting called in the controller function above by the name `getEmailDigest`.
+
+If youâre following the guide, youâve already copied the trigger function. But before we can add it to our app, we need one key thing - Subscribers.
+
+Subscribers are users to which the notifications are sent. You can see a list of subscribers in the [Novu dashboard](https://dashboard-v2.novu.co/subscribers?utm_campaign=docs-digests) as well.
+
+In our app, weâll create a subscriber in Node.js as weâre writing our backend in Node.js, but we also have backend [SDKs](/sdks/introduction) ([Node.js](https://github.com/novuhq/novu/tree/next/packages/node), [PHP](https://github.com/novuhq/novu-php), [.NET](https://github.com/novuhq/novu-dotnet), [Elixir](https://github.com/novuhq/novu-elixir), [Go](https://github.com/novuhq/go-novu), [Ruby](https://github.com/novuhq/novu-ruby), [Python](https://github.com/novuhq/novu-python), and [Kotlin](https://github.com/novuhq/novu-kotlin)) to choose from. The recommended way to create a subscriber in NodeJS is as follows:
+
+```jsx
+await novu.subscribers.identify("digestEmailSub", {
+ firstName: "digest email subscriber",
+ email: email,
+});
+```
+
+Here, weâre creating a subscriber with the `subscriberID` of `digestEmailSub.` In most real-world scenarios, the `subscriberId` should be an alphanumeric entity like `adfa67y87ad0`. You can read more about subscribers [here](https://docs.novu.co/platform/subscribers/).
+
+Back in our app, we can now add the trigger function:
+
+```jsx
+import { Novu } from "@novu/node";
+
+export const sendEmailDigest = async (notif, email) => {
+ const novu = new Novu(process.env.YOUR_NOVU_SECRET_KEY);
+ await novu.subscribers.identify("digestEmailSub", {
+ firstName: "digest email subscriber",
+ email: email,
+ });
+
+ novu.trigger("emaildigestworkflow", {
+ to: {
+ subscriberId: "digestEmailSub",
+ email: email,
+ },
+ payload: {
+ notif: notif,
+ },
+ });
+};
+```
+
+Now, we just need to hit the route defined above from the front end.
+
+# Hit the backend route from the front end
+
+From the front end, we just need to hit the route we had defined above. Below, I'm sharing the body component of the demo app I created to illustrate this:
+
+```jsx
+const Body = () => {
+ const [formInput, setFormInput] = useState({ notif: "", email: "" });
+ const [buttonClicked, setButtonClicked] = useState(false);
+
+ const onSubmitHandler = async (e) => {
+ e.preventDefault();
+ const response = await fetch(
+ "https://emaildigestbackend.onrender.com/api/v1/sending-email-digest",
+ {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(formInput),
+ }
+ );
+ console.log(response.data);
+ setFormInput({ notif: "" });
+ };
+
+ const handleClick = () => {
+ setButtonClicked(true);
+
+ // Reset the button feedback after a certain duration
+ setTimeout(() => {
+ setButtonClicked(false);
+ }, 100);
+ };
+
+ const onChangeHandler = (e) => {
+ const value =
+ e.target.name === "email" ? e.target.value.trim() : e.target.value;
+
+ setFormInput((prev) => ({
+ ...prev,
+ [e.target.name]: value,
+ }));
+ };
+ return (
+
+ );
+};
+```
+
+We're hitting the backend route we had created earlier. The backend has been deployed on render as can be seen in this code snippet above.
+
+Congratulations on following the guide up until this point. We can style our app a little using [some TailwindCSS](https://github.com/novuhq/digest-email-app/blob/main/frontend/src/app.css).
+
+If youâve done everything as recommended, youâll end up with an app that looks like this:
+
+
+ {" "}
+
+
+In this app, when we enter the email id, some text in the input box, and click send, the notification appears in the inbox after the delay specified above (when weâre creating the workflow).
+
+This is how we add digest to email notifications!
diff --git a/legacy-guides/add-digest-to-inapp-notifications.mdx b/legacy-guides/add-digest-to-inapp-notifications.mdx
new file mode 100644
index 000000000..b47a89ad5
--- /dev/null
+++ b/legacy-guides/add-digest-to-inapp-notifications.mdx
@@ -0,0 +1,323 @@
+---
+title: "How to Add Digest to In-App Notifications"
+description: "Leverage the digest functionality to send in-app notifications"
+---
+
+## Introduction
+
+In this guide, youâll learn how to add digest notifications to a React app. But before exploring the actual code, letâs understand what a digest notification is and how it works.
+
+You can find the entire code(frontend as well as backend) for this app [here](https://github.com/novuhq/digest-learning-app/tree/main).
+
+### What is a Digest Notification?
+
+Often times when you associate notifications with user activity, the end user can be bombarded with messages because of the nature of the activity. Take for example the case of commenting in the context of a social media app. If you were to send a notification to a user for every comment they receive, and they happen to receive 100 comments, it could lead to user fatigue since you would have to send 100 messages.
+
+This is where digest notifications come into the picture!
+
+A digest notification is a notification that consolidates information from several notifications into one and delivers that notification to the end user instead of several separate messages.
+
+### How does Digest Notification Work?
+
+Novu has a built-in digest engine that collects multiple trigger events, aggregates them into a single message and delivers it to the subscriber. You can use the digest engine by adding a `digest node` to your workflow in the workflow editor in the [Novu dashboard](https://dashboard-v2.novu.co/workflows?utm_campaign=docs-digestsinapp).
+
+Letâs see it in action now!
+
+## Add Digest Notification To An App
+
+To get started with this, you need the following:
+
+- A Novu account. [Sign up for free](http://dashboard.novu.co/?utm_campaign=docs-gs-digestsinapp) if you donât have one yet.
+- A working React development environment.
+
+## Workflow setup in Novu
+
+Once, you have these, follow the steps below:
+
+1. Head over to the Novu Dashboard.
+2. Click **"Workflows"** on the left sidebar of your Novu dashboard.
+3. Click the **"Create Workflow"** button on the top right:
+
+ {" "}
+
+ Once you click the `create workflow` button, youâll see a dropdown. Select `blank
+ workflow` from the dropdown:
+
+ {" "}
+
+ Youâll now be taken to the workflow editor:
+
+ {" "}
+
+ Once here, you can add the channels you want to use for sending notifications
+ and configure them. For this guide, weâll use the `In-App` channel. Youâll also
+ see the `Digest` action on the right sidebar.
+
+
+ Each node that is added below the digest node will only be triggered after the
+ specified time interval
+
+For example, in our case, say we want the In-App notification to be sent after every
+6 hours. Next, add the `digest` action below the `trigger node`, and add the `in-app`
+channel node below the `digest` node as shown below:
+
+ {" "}
+
+The `digest` node allows you to set a specific time interval for when notifications
+should be sent:
+
+ {" "}
+
+Once, youâve configured it. Go ahead and configure the `in-app` channel as per your
+need:
+
+ {" "}
+
+Hereâs a brief explanation of all the options:
+
+- **1-Preview**: This shows you a glimpse of what each notification item will look like in the Notification Center UI.
+- **2-Avatar:**Â If turned on, each notification item will show the avatar of the subscriber.
+- **3-Action:**Â With this, you can add a primary and secondary call to action button to each notification item.
+- **4-Notification Feeds:**Â This displays a stream of specific notifications. You can have multiple feeds to show specific notifications in multiple tabs.
+- **5-Redirect URL**Â - This is the URL to which a subscriber can be directed when they click on a notification item.
+- **6-Filter**Â - This feature allows you to configure the criteria for delivering notifications. For instance, you can apply a filter based on a subscriber's online status to send them an email if they were online within the last hour.
+
+In our case, weâre going to use the following:
+
+
+ {" "}
+
+Once youâre done configuring this to your liking, click on the `update` button on
+the top right. Itâll automatically create a trigger code that you can use in your
+app. To get it, click on the `get snippet` button on the top right and copy it:
+
+ {" "}
+
+Now, letâs see how to add Novu to our app!
+
+# Add Novu to the Backend and Configure it
+
+In your backend, install the novu package using the following code:
+
+```bash
+npm install @novu/node
+```
+
+Now, create a route which you want to hit when called from the front end. In our demo app, this is the route:
+
+```jsx
+import express from "express";
+import { getDigest } from "../controller/digest.js";
+
+const router = express.Router();
+
+router.post("/sending-digest", getDigest);
+
+export default router;
+```
+
+Now, we need to write a controller function that will handle the logic for what is to be sent in the trigger functionâs payload. In our case, this is the controller function:
+
+```jsx
+import { sendDigest } from "../novu/novu.js";
+
+export const getDigest = async (req, res) => {
+ const { name } = req.body;
+ try {
+ await sendDigest(name);
+ res.status(201).json({ message: "success", name: name });
+ } catch (error) {
+ res.status(409).json({ message: error.message });
+ }
+};
+```
+
+To make it modular, weâll keep the trigger code in a separate function in a separate file (`novu.js`, in our case) and the trigger function is getting called in the controller function above by the name `getDigest`.
+
+If youâre following the guide, youâve already copied the trigger function. But before we can add it to our app, we need one key thing - **Subscribers.**
+
+Subscribers are entities to which the notifications are sent. You can see a list of subscribers in the [Novu dashboard](https://dashboard-v2.novu.co/subscribers?utm_campaign=docs-digests-inapp) as well.
+
+In our app, weâll create a subscriber in Node.js as weâre writing our backend in Node.js, but we also have backend [SDKs](/sdks/introduction) (Node.js, PHP, .NET, Go, Ruby, Python and Kotlin) to choose from. The recommended way to create a subscriber in NodeJS is as follows:
+
+```jsx
+await novu.subscribers.identify("aa234u787", {
+ firstName: "digest subscriber",
+});
+```
+
+Here, weâre creating a subscriber with the `subscriberID` of `aa234u787.` You can read more about subscribers [here](/concepts/subscribers).
+
+Back in our app, we can now add the trigger function:
+
+```jsx
+import { Novu } from "@novu/node";
+
+export const sendDigest = async (name) => {
+ const novu = new Novu(process.env.NOVU_SECRET_KEY);
+
+ await novu.subscribers.identify("aa234u787", {
+ firstName: "digest subscriber",
+ });
+
+ await novu.trigger("digest-showcase", {
+ to: {
+ subscriberId: "aa234u787",
+ },
+ payload: {
+ name: name,
+ },
+ });
+};
+```
+
+Now, we just need to hit the route defined above from the front end and add Novu to it.
+
+# Add Novuâs Notification Center to the front end
+
+In the front end, install the Novu notification centre package using the following command:
+
+```bash
+npm install @novu/notification-center
+
+```
+
+Now, import and render the component in your app. The code to do so is as follows:
+
+```jsx
+import {
+ NovuProvider,
+ PopoverNotificationCenter,
+ NotificationBell,
+ IMessage,
+} from "@novu/notification-center";
+
+function Header() {
+ function onNotificationClick(message: IMessage) {
+ // your logic to handle the notification click
+ if (message?.cta?.data?.url) {
+ window.location.href = message.cta.data.url;
+ }
+ }
+
+ return (
+
+
+ {({ unseenCount }) => }
+
+
+ );
+}
+```
+
+You can, of course, modify things as you need. For example, in our app, this is what weâve done in the header:
+
+```jsx
+import {
+ NovuProvider,
+ PopoverNotificationCenter,
+ NotificationBell,
+} from "@novu/notification-center";
+import "../css/Header.css";
+
+const Header = () => {
+ function onNotificationClick(message) {
+ // your logic to handle the notification click
+ if (message?.cta?.data?.url) {
+ window.location.href = message.cta.data.url;
+ }
+ }
+ return (
+
+ );
+};
+
+export default Header;
+```
+
+Youâll also need to plug in your `applicationIdentifier`. You can get your `application id` from the settings menu in the Novu dashboard.
+
+Beyond this, we just need to call the API we had written above when the form is submitted with the data we want in the payload. The code to do so is as follows:
+
+```jsx
+import { useState } from "react";
+import axios from "axios";
+import "../css/Body.css";
+
+const Body = () => {
+ const [name, setName] = useState("");
+
+ const onSubmitHandler = async (e) => {
+ e.preventDefault();
+ const res = await axios.post(
+ "http://localhost:3000/api/v1/sending-digest",
+ { name }
+ );
+ setName("");
+ };
+ const onChangeHandler = (e) => {
+ setName(e.target.value);
+ };
+ return (
+
+ );
+};
+
+export default Body;
+```
+
+The app is done now!
+
+Congratulations for following the guide up until this point. We can style our app a little using [some CSS](https://github.com/novuhq/digest-learning-app/blob/main/frontend/src/App.css).
+
+If youâve done everything as recommended, youâll end up with an app that looks like this:
+
+
+ {" "}
+
+In this app, when we enter some text in the input box and click send, the notification
+appears in the bell icon after the delay specified above (when weâre creating the
+workflow).
+
+This is how we add digest to in-app notifications!
diff --git a/legacy-guides/cookbook/introduction.mdx b/legacy-guides/cookbook/introduction.mdx
new file mode 100644
index 000000000..a04ec2994
--- /dev/null
+++ b/legacy-guides/cookbook/introduction.mdx
@@ -0,0 +1,192 @@
+---
+title: "Recipes"
+---
+
+This cookbook contains recipes and code samples demonstrating how to accomplish everyday tasks with Novu in your application. Each code example uses our libraries and SDKs.
+
+
+
+
+
+## Fetch Subscriber Feed
+
+A subscriber feed is a list of all In-App messages for a single subscriber. It's a continuous stream of messages displayed in a list that subscribers can scroll through on the frontend via the Notification Center.
+
+It is a dynamic list with **seen** and **unseen** capabilities. Multiple feeds can exist for a subscriber.
+
+
+ **Subscriber Feed** is very different from **Activity Feed**. The former is
+ for In-App channels, while the latter is a list of every message and relevant
+ metadata across all channels shown in your dashboard.
+
+
+The code sample below fetches the list of all In-App messages sent to a specific subscriber:
+
+
+```javascript Node.js
+const { data: inAppMessages } = await novu.subscribers.getNotificationsFeed('subscriberId', {
+ page: 0,
+ limit: 10,
+
+// it is of type string. By default all feeds messages are fetched
+feedIdentifier: 'Marketing',
+
+// seen and read filter of type boolean
+seen: true,
+read: true
+});
+
+```
+
+
+## Fetch All Feeds
+
+In-App messages are grouped in Feeds. There can be one or multiple feeds.
+
+The code sample below fetches all the feeds that have been created and exist in the In-App steps:
+
+
+```javascript Node.js
+const { data: feedsData } = await novu.feeds.get();
+```
+
+
+
+## Delete a Message From a Feed
+
+A message is a content sent to a single subscriber over a single channel. Some messages are simple, like SMS, while others have more features and capabilities, such as Email, Chat, In-App.
+
+A single message can be deleted from a Feed. The code sample below shows how to do it:
+
+
+ ```javascript Node.js await novu.messages.deleteById('messageId'); ```
+
+
+## Fetch all Messages Sent To All Subscribers
+
+You can retrieve all messages sent to all subscribers. There are a couple of filters you can apply to fetch these messages.
+
+- channel: fetches all messages that were sent via a specific channel, e.g Email, Sms, Push, In-App
+- subscriberId: fetches all messages sent to a specific subscriber
+- transactionIds: fetches all messages via transaction ids.
+
+
+```javascript Node.js
+import { ChannelTypeEnum } from '@novu/node';
+
+// All fields are optional
+const listMessagesOptions = {
+// pagination options
+page: 0,
+limit: 20,
+
+/\*\*
+
+- Filter options
+ \*/
+ // use ChannelTypeEnum.PUSH for push, ChannelTypeEnum.IN_APP for in-app,
+ channel: ChannelTypeEnum.EMAIL, // only email type messages will be fetched
+ subscriberId: '6444105141ffb0919496dfcb',
+ transactionIds: ['644-41051-41ffb0-919496-dfcb'],
+ };
+
+const { data: messagesData } = await novu.messages.list(listMessagesOptions);
+
+```
+
+
+## Mark an In-App Message as Read/Seen
+
+You can mark an In-App message as read/seen. Messages from other channels: **Email**, **Push**, **Chat**, **Sms** can't be marked as read/seen.
+
+
+```javascript Node.js
+const { data: markMessageAsRead } = await novu.subscribers.markMessageRead(
+ 'subscriberId',
+ 'messageId'
+);
+
+const { data: markMessageAsSeen } = await novu.subscribers.markMessageSeen(
+ 'subscriberId',
+ 'messageId'
+);
+```
+
+
+
+## Mark an In-App Message as Read/Unread/Seen/Unseen
+
+You can mark an In-App message as read/unread/seen/unseen. Messages from other channels: **Email**, **Push**, **Chat**, **Sms** can't be marked as read/unread/seen/unseen.
+
+
+```javascript Node.js
+const { data: markMessageAs } = await novu.subscribers.markMessageAs(
+ 'subscriberId',
+ 'messageId',
+ { seen: true, read: false }
+);
+```
+
+
+## Mark all In-App Messages as Read/Unread/Seen/Unseen
+
+You can mark all In-App messages as read/unread/seen/unseen.
+
+Messages from other channels: **Email**, **Push**, **Chat**, **Sms** can't be marked as read/unread/seen/unseen.
+
+
+```javascript Node.js
+import { MarkMessagesAsEnum } from "@novu/node"
+
+const { data: markAllInAppMessages } = await novu.subscribers.markAllMessagesAs(
+'subscriberId',
+
+// can be filtered with feed identifiers
+feedIdentifier: ['Marketing', 'Product']
+
+// MarkMessageAsEnum.READ => It will mark all messages as read
+// MarkMessageAsEnum.SEEN => It will mark all messages as seen
+// MarkMessageAsEnum.UNREAD => It will mark all messages as unread
+// MarkMessageAsEnum.UNSEEN => It will mark all messages as unseen
+markAs: MarkMessageAsEnum.Read
+);
+
+```
+
+
+## Send Slack Notifications
+
+You can send notifications to Slack Channels via Novu like so:
+
+```javascript Node.js
+import {
+ Novu,
+ ChatProviderIdEnum
+} from '@novu/node';
+
+const novu = new Novu("");
+
+// Identify Subscriber
+await novu.subscribers.identify('', {
+ firstName: 'newSubForSlackChat',
+});
+
+// Set credentials for the Subscriber
+await novu.subscribers.setCredentials('', ChatProviderIdEnum.Slack, {
+ webhookUrl: "",
+});
+
+// Trigger slack notification
+await novu.trigger('slack', {
+ to: {
+ subscriberId: ''
+ },
+ payload: {
+ chatMsg: ''
+ }
+});
+```
+
+where `chatMsg` is a payload variable in the workflow editor.
+
+Follow the [full guide](/legacy-guides/slack-guide) on how to send Slack notifications using Novu.
diff --git a/legacy-guides/demos/introduction.mdx b/legacy-guides/demos/introduction.mdx
new file mode 100644
index 000000000..bb324d708
--- /dev/null
+++ b/legacy-guides/demos/introduction.mdx
@@ -0,0 +1,129 @@
+---
+title: "Demo apps"
+description: "Experience the power of Novu for triggering, digesting, and receiving notifications via different channels"
+---
+
+### 1. Email, In-App Notification & Authentication
+
+
+
+
+
+
+
+ Find the source code here!
+
+
+ Try it yourself first-hand!
+
+
+
+### 2. Headless Notification Center
+
+
+
+
+
+
+
+ Find the source code here!
+
+
+ Try it yourself first-hand!
+
+
+
+### 3. Notification Center
+
+
+
+
+
+
+
+ Find the source code here!
+
+
+ Try it yourself first-hand!
+
+
+
+### 4. Email Digest Engine
+
+
+
+
+
+
+
+ Find the source code here!
+
+
+ Try it yourself first-hand!
+
+
+
+### 5. InApp Digest Engine
+
+
+
+
+
+
+
+ Find the source code here!
+
+
+ Try it yourself first-hand!
+
+
diff --git a/legacy-guides/discord-guide.mdx b/legacy-guides/discord-guide.mdx
new file mode 100644
index 000000000..ebfbda987
--- /dev/null
+++ b/legacy-guides/discord-guide.mdx
@@ -0,0 +1,208 @@
+---
+title: "How to use Novu to send notifications to a channel in a Discord server"
+description: "Learn to send Discord notifications swiftly with Novu"
+---
+
+# Introduction
+
+In this guide, you'll learn how to use Novu to send notifications to any channel in a Discord server. But before coding anything up, we just need to go over a couple of setup steps.
+The corresponding docs for this guide are available on our [docs](https://docs.novu.co/channels-and-providers/chat/discord).
+
+
+ The entire code for this app is available on our
+ [GitHub](https://github.com/novuhq/discord-chat-app).
+
+
+So let's begin!
+
+# Set up Discord
+
+Setting up Discord is fairly straightforward. You just need the `webhook Url`. It is pretty simple and can be done in the following easy steps:
+
+1. Go to the channel you want to add the webhook to (you need to be an admin of the discord server).
+
+ {" "}
+
+2. Right-click the channel and select **âEdit Channelâ**.
+
+ {" "}
+
+3. Select Integrations -> Webhooks -> Create Webhook
+
+ {" "}
+
+4. Edit the Bot name to your liking, copy the webhook URL and store it somewhere. We'll need it in the future.
+
+ {" "}
+
+
+# Set up Novu
+
+In this part, we'll set up a workflow that will be triggered when we send a notification. Workflows are like blueprints and hold the entire flow of notifications. You can read more about them on our [docs](https://docs.novu.co/workflows/notification-workflows). To set up a notification workflow for our app, follow these steps:
+
+1. Make sure that you've set the Discord Integration as active from the [Novu Integrations Store](https://dashboard-v2.novu.co/integrations?utm_campaign=docs-discordnotifications).
+
+ {" "}
+
+2. Goto the [Novu Web Dashboard](https://dashboard-v2.novu.co/workflows?utm_campaign=docs-discordnotifications).
+3. Click on the **"Add a workflow"** button and select **"Blank workflow"** from the dropdown.
+
+ {" "}
+
+4. Once there, give your workflow a name and drag and drop the **"Chat"** option below the **"Workflow trigger"** step.
+
+ {" "}
+
+5. You can also add variables in the **Workflow Editor**. For example, here I've added 'chatMsg' as a variable as I'll be sending data using it.
+
+ {" "}
+
+ Whatever is placed inside double braces is a variable.
+6. Click the **"Get Snippet"** button, copy the trigger code and keep it somewhere. We'll need this to trigger this workflow.
+
+ {" "}
+
+ Now, we've completed all the setup required and can move to coding!
+
+# Create the backend
+
+The backend for this app is quite simple. Simply install the Novu package:
+
+```bash
+npm install @novu/node
+
+```
+
+Now, create a route that you'll hit when called from the front end. For our demo app, this is the route I've created:
+
+```jsx
+import express from "express";
+import { chatController } from "../controller/chat.js";
+
+const router = express.Router();
+
+router.post("/sendChat", chatController);
+
+export default router;
+```
+
+Now, we need a controller function to handle what is to be sent in the trigger's function payload. Here's the controller I wrote:
+
+```jsx
+import { chat } from "../novu/novu.js";
+
+export const chatController = async (req, res) => {
+ const { chatMsg } = req.body;
+ try {
+ await chat(chatMsg);
+ res.status(201).json({ message: "Message sent successfully" });
+ } catch (error) {
+ console.log("notifController error:", error);
+ res.status(500).json({ message: error.message });
+ }
+};
+```
+
+
+ Notice how we're expecting 'chatMsg' in our payload. This is why we added it
+ as a variable in the workflow created earlier.
+
+To make it modular, weâll keep the trigger code in a separate function in a separate
+file, `novu.js`, in our case, which is as follows: ```jsx import {
+ (Novu, ChatProviderIdEnum)
+} from '@novu/node';
+
+export const chat = async (chatMsg) => {
+ try {
+ const novu = new Novu(process.env.YOUR_NOVU_SECRET_KEY_HERE);
+
+ await novu.subscribers.identify(process.env.SUB_ID, {
+ firstName: 'newSubForDiscordChat',
+ });
+
+ await novu.subscribers.setCredentials(process.env.SUB_ID, ChatProviderIdEnum.Discord, {
+ webhookUrl: process.env.WEBHOOK_URL
+ });
+
+ } catch (error) {
+ console.log(error);
+ }
+
+}
+
+```
+Add the trigger code you'd copied earlier:
+```jsx
+import { Novu } from '@novu/node';
+
+const novu = new Novu('');
+
+novu.trigger('chat-with-discord', {
+ to: {
+ subscriberId: ''
+ },
+ payload: {
+ chatMsg: ''
+ }
+ });
+```
+
+Our final trigger code should look something like this:
+
+```jsx
+import { Novu, ChatProviderIdEnum } from "@novu/node";
+
+export const chat = async (chatMsg) => {
+ try {
+ const novu = new Novu(process.env.YOUR_NOVU_SECRET_KEY_HERE);
+
+ await novu.subscribers.identify(process.env.SUB_ID, {
+ firstName: "newSubForDiscordChat",
+ });
+
+ await novu.subscribers.setCredentials(
+ process.env.SUB_ID,
+ ChatProviderIdEnum.Discord,
+ {
+ webhookUrl: process.env.WEBHOOK_URL,
+ }
+ );
+
+ await novu.trigger("chat-with-discord", {
+ to: {
+ subscriberId: process.env.SUB_ID,
+ },
+ payload: {
+ chatMsg: chatMsg,
+ },
+ });
+ } catch (error) {
+ console.log(error);
+ }
+};
+```
+
+
+ We're keeping all the sensitive data in a `.env` file to avoid hardcoding as a
+ good practice
+
+
+In this code snippet above, we're first initializing a new instance of Novu, then using it to 'identify' or [create](https://docs.novu.co/subscribers/subscribers#create-a-subscriber) a [subscriber](https://docs.novu.co/subscribers/subscribers).
+
+
+ The 'identify' method tries to find a subscriber with the given info. If it
+ can't find any such subscriber, it creates a new subscriber with the supplied
+ info.
+
+After creating the subscriber, it runs the trigger code for the workflow we had created.
+
+# Front end set up
+
+For our demonstration purposes, the front-end is pretty basic. All we have to do is have an input field to take the notification text in and send the payload. The front-end code for this demo app is available on our [Github repo](https://github.com/novuhq/discord-chat-app/tree/main/frontend).
+And here's our app in all its glory!
+
+
+ {" "}
+
+
+This is how we send Discord notifications using Novu!
diff --git a/legacy-guides/fcm-flutter-novu/how-to-send-push-notifications-to-flutter-apps-with-fcm-using-Novu.mdx b/legacy-guides/fcm-flutter-novu/how-to-send-push-notifications-to-flutter-apps-with-fcm-using-Novu.mdx
new file mode 100644
index 000000000..ac23fe41f
--- /dev/null
+++ b/legacy-guides/fcm-flutter-novu/how-to-send-push-notifications-to-flutter-apps-with-fcm-using-Novu.mdx
@@ -0,0 +1,785 @@
+---
+title: "How to send push notifications to Flutter apps (Android & iOS) with FCM using Novu"
+description: "Learn how to integrate Firebase Cloud Messaging with Novu and send notifications to Flutter apps"
+---
+
+## Prerequisites
+
+To complete this guide, you will need the following:
+
+- [Apple Developer](https://developer.apple.com/)Â membership (to obtain the required permissions to send push notifications).
+- A machine running MacOS to work on building the Flutter app for iOS devices.
+- [Firebase](https://firebase.google.com/)Â account
+- [Novu](https://dashboard-v2.novu.co/?utm_campaign=docs-gs-legacy-guides-fcm-flutter)Â account.
+- [Android Studio](https://developer.android.com/studio/install) configured with Dart and Flutter plugins.
+- [Xcode](https://developer.apple.com/xcode/)Â installed on your machine.
+
+Check out the [Flutter app code for this guide on GitHub](https://github.com/novuhq/flutter-fcm-novu).
+
+## Set up and Create a Flutter App
+
+If you have an existing Flutter App, you can skip this step.
+
+If you are creating a brand new Flutter app, please follow this [guide](https://firebase.google.com/codelabs/firebase-fcm-flutter#0).
+
+## Set up Firebase and FlutterFire
+
+Please follow this [guide to set up a Firebase project and integrate Firebase Cloud Messaging in your Flutter app](https://firebase.google.com/codelabs/firebase-fcm-flutter#2).
+
+## Set Up Apple Integration
+
+Please follow this [guide to ensure that everything is set up on your iOS device](https://firebase.flutter.dev/docs/messaging/apple-integration) to receive messages.
+
+There is an optional section about allowing **Notification Images**. Follow the steps to install and activate the notification service extension. We'll need it later in this guide to display images as part of the push notifications from FCM.
+
+## Set Up FCM Notification Permission & Registration Token
+
+We'll add code to initialize Firebase and ask the user's permission to receive notifications.
+
+Open up the `lib/main.dart` file in your Flutter app and replace everything with the code below:
+
+```dart
+import 'package:flutter/foundation.dart';
+import 'package:firebase_core/firebase_core.dart';
+import 'package:flutter/material.dart';
+import 'firebase_options.dart';
+import 'package:firebase_messaging/firebase_messaging.dart'; // FlutterFire's Firebase Cloud Messaging plugin
+
+// Add Stream controller
+import 'package:rxdart/rxdart.dart';
+
+// for passing messages from event handler to the UI
+final _messageStreamController = BehaviorSubject();
+
+@pragma('vm:entry-point')
+Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
+ // If you're going to use other Firebase services in the background, such as Firestore,
+ // make sure you call `initializeApp` before using other Firebase services.
+ await Firebase.initializeApp();
+
+ print("Handling a background message: ${message.messageId}");
+ print('Message data: ${message.data}');
+ print('Message notification: ${message.notification?.title}');
+ print('Message notification: ${message.notification?.body}');
+
+}
+
+Future main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+ await Firebase.initializeApp(
+ options: DefaultFirebaseOptions.currentPlatform,
+ );
+
+ // Request permission
+ final messaging = FirebaseMessaging.instance;
+
+ // Web/iOS app users need to grant permission to receive messages
+ final settings = await messaging.requestPermission(
+ alert: true,
+ announcement: false,
+ badge: true,
+ carPlay: false,
+ criticalAlert: false,
+ provisional: false,
+ sound: true,
+ );
+
+ if (kDebugMode) {
+ print('Permission granted: ${settings.authorizationStatus}');
+ }
+
+ // Register with FCM
+ // It requests a registration token for sending messages to users from your App server or other trusted server environment.
+ String? token = await messaging.getToken();
+
+ if (kDebugMode) {
+ print('Registration Token=$token');
+ }
+
+ // Set up foreground message handler
+ FirebaseMessaging.onMessage.listen((RemoteMessage message) {
+ if (kDebugMode) {
+ print('Handling a foreground message: ${message.messageId}');
+ print('Message data: ${message.data}');
+ print('Message notification: ${message.notification?.title}');
+ print('Message notification: ${message.notification?.body}');
+ }
+
+ _messageStreamController.sink.add(message);
+ });
+
+ // Set up background message handler
+ FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
+
+ runApp(MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'Flutter Demo',
+ theme: ThemeData(
+ primarySwatch: Colors.blue,
+ ),
+ home: const MyHomePage(title: 'Flutter Demo Home Page'),
+ );
+ }
+}
+
+class MyHomePage extends StatefulWidget {
+ const MyHomePage({Key? key, required this.title}) : super(key: key);
+
+ final String title;
+
+ @override
+ State createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State {
+ String _lastMessage = "";
+
+ _MyHomePageState() {
+ _messageStreamController.listen((message) {
+ setState(() {
+ if (message.notification != null) {
+ _lastMessage = 'Received a notification message:'
+ '\nTitle=${message.notification?.title},'
+ '\nBody=${message.notification?.body},'
+ '\nData=${message.data}';
+ } else {
+ _lastMessage = 'Received a data message: ${message.data}';
+ }
+ });
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(widget.title),
+ ),
+ body: Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text('Last message from Firebase Messaging:',
+ style: Theme.of(context).textTheme.titleLarge),
+ Text(_lastMessage, style: Theme.of(context).textTheme.bodyLarge),
+ ],
+ ),
+ ),
+ );
+ }
+}
+```
+
+_lib/main.dart_
+
+There are 4 sections to pay attention to:
+
+
+
+ This shows the notification permission prompt to the user when the user interacts with the app for the first time. If the user allows it, then we can get a token.
+
+ ```dart
+ // Request permission
+ final messaging = FirebaseMessaging.instance;
+
+ // Web/iOS app users need to grant permission to receive messages
+ final settings = await messaging.requestPermission(
+ alert: true,
+ announcement: false,
+ badge: true,
+ carPlay: false,
+ criticalAlert: false,
+ provisional: false,
+ sound: true,
+ );
+ ```
+
+
+
+ A device's token is needed for the specific device to receive messages. The `getToken()` returns the registration token for the app instance on the device.
+
+ ```dart
+ String? token = await messaging.getToken();
+
+ if (kDebugMode) {
+ print('Registration Token=$token');
+ }
+ ```
+
+
+
+ This handler listens to when a push notification is sent from FCM to the device. If the app is in the foreground, then it prints out the notification title, body, messageId, and data properties to the console.
+
+ ```dart
+ FirebaseMessaging.onMessage.listen((RemoteMessage message) {
+ if (kDebugMode) {
+ print('Handling a foreground message: ${message.messageId}');
+ print('Message data: ${message.data}');
+ print('Message notification: ${message.notification?.title}');
+ print('Message notification: ${message.notification?.body}');
+ }
+
+ _messageStreamController.sink.add(message);
+ });
+ ```
+
+
+
+ This handler listens to when a push notification is sent from FCM to the device. If the app is in the background, then it prints out the notification title, body, messageId, and data properties to the console.
+
+ ```dart
+ ...
+ @pragma('vm:entry-point')
+ Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
+ // If you're going to use other Firebase services in the background, such as Firestore,
+ // make sure you call `initializeApp` before using other Firebase services.
+ await Firebase.initializeApp();
+
+ print("Handling a background message: ${message.messageId}");
+ print('Message data: ${message.data}');
+ print('Message notification: ${message.notification?.title}');
+ print('Message notification: ${message.notification?.body}');
+
+ }
+ ...
+
+
+ FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
+ ```
+
+
+
+
+Now, run the Flutter app. Your device should be connected to your machine to enable the app to run on it.
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Cloud Message Test
+
+In your Firebase project, navigate to `Engage` section and click on `Messaging`.
+
+
+ {" "}
+
+
+Click on `Create your first campaign` and select `Firebase Notification messages`.
+
+
+ {" "}
+
+
+ {" "}
+
+
+Enter the `Notification title` and the `Nabigateotification text`, and click on `Send test message`.
+
+
+ {" "}
+
+
+We must copy and paste this FCM registration token to confirm our device. You can find it logged as shown earlier in our editor.
+
+
+ {" "}
+
+
+ {" "}
+
+
+Click on 'Test'.
+
+
+ {" "}
+
+
+You should see the notification on your device!
+
+
+
+
+
+## Sign Up on Novu
+
+Let's use Novu to fire push notifications via FCM. First, sign up on [Novu Cloud](https://dashboard-v2.novu.co)?utm_campaign=docs-gs-legacy-guides-fc-flutter.
+
+
+ {" "}
+
+
+Next, immediately configure FCM as a Push channel provider.
+
+
+ {" "}
+
+
+You can also do this by heading straight to the `Integrations Store`. Click on `Add a provider`.
+
+## Connect FCM as a Push Channel provider
+
+
+ {" "}
+
+
+ {" "}
+
+
+You only need to configure FCM with Novu with the Firebase Service Accounts private key.
+
+To acquire the account key JSON file for your service account, follow this instructions:
+
+1. Select your project. Click the gear icon on the top of the sidebar.
+2. Head to project settings.
+3. Navigate to the `Service accounts` tab.
+4. Click `Generate new private key`, then confirm by clicking `Generate key`.
+5. Click `Generate key` to download the JSON file.
+6. Once the file is on your machine, paste the entire JSON file content in the `Service Account` field of the FCM provider in the Integration store on Novuâs web dashboard.
+
+Make sure your service account key JSON content contains these fields:
+
+```JSON
+
+{
+ "type": "service_account",
+ "project_id": "PROJECT_ID",
+ "private_key_id": "PRIVATE_KEY_ID",
+ "private_key": "PRIVATE_KEY",
+ "client_email": "FIREBASE_ADMIN_SDK_EMAIL",
+ "client_id": "CLIENT_ID",
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+ "token_uri": "https://oauth2.googleapis.com/token",
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+ "client_x509_cert_url": "CLIENT_X509_CERT_URL"
+}
+
+```
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+## Create a Notification Workflow
+
+In Novu, creating a workflow means establishing a blueprint for sending notifications within your app. This unified structure ties together email, in-app messages, SMS, push notifications, and chat into **one entity**.
+
+Each workflow has a unique name and identifier and includes customized content for various channels, using `{{handlebars}}` variables for personalization.
+
+This ensures consistent platform notifications and allows dynamic adjustments for individual subscribers, scenarios, and use cases.
+
+
+
+
+ {" "}
+
+
+ {" "}
+
+
+
+
+ {" "}
+
+
+
+
+ {" "}
+
+
+
+
+We need to fire notifications to subscribers. So, let's create a subscriber!
+
+## Create A Subscriber & Update Credentials
+
+A subscriber is essentially the recipient of the notifications sent through Novu's system. When you create a subscriber, you're setting up the necessary information for Novu to send targeted notifications to that individual.
+
+You can see the list of subscribers in the `Subscribers` section of the Novu dashboard.
+
+
+ {" "}
+
+
+
+
+
+
+ ```JSON
+
+ curl --location 'https://api.novu.co/v1/subscribers' \
+
+--header 'Content-Type: application/json' \
+ --header 'Accept: application/json' \
+ --header 'Authorization: ApiKey ' \
+ --data-raw '{
+"subscriberId": "584349343",
+"firstName": "Flutter",
+"lastName": "Boy",
+"email": "flutterboy@gmail.com",
+}'
+
+```
+
+
+
+
+
+
+
+
+
+
+ Subscriber can have multiple device tokens
+
+ Here, you can locate the Provider_Identifier.
+
+
+
+ ```JSON
+
+ curl --request PUT \
+ --url https://api.novu.co/v1/subscribers/{subscriber_id}/credentials \
+ --header 'Content-Type: application/json' \
+ --header 'Authorization: ApiKey ' \
+ --data '{
+ "credentials":{
+ "deviceTokens": [""]
+ },
+ "integrationIdentifier":"",
+ "providerId":"fcm"
+ }'
+
+```
+
+_Update the Subscriber Credentials by adding the device tokens to the subscriber_
+
+
+
+
+
+## Sending a Push Notification to a Device(Android/iOS) with Novu
+
+To send a notification with Novu, you are actually triggering a notification workflow.
+You have the ability to test the trigger using the Novu UI or by calling Novu's API.
+
+**Trigger a workflow via the API**
+
+Insert the `trigger identifier` as the name in the API request below:
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "novu-push-workflow-for-flutter",
+ "to": {
+ "subscriberId": ""
+ },
+ "payload": {}
+ }'
+
+```
+
+**Trigger a workflow via the Novu Dashboard**
+
+
+ {" "}
+
+
+ {" "}
+
+
+**Receive Triggered Push Workflow on Device**
+
+
+
+
+
+## Dynamic Content
+
+When we were creating the first workflow, we "Hardcoded" the content of the notification.
+
+Now, we will determine the content when calling the API.
+
+1. In the workflow, we should change the values of the `title` and the `body` to `{{title}}` and `{{body}}`.
+ That way, we could insert values through the payload of the API call.
+
+
+ {" "}
+
+
+2. Add a `payload` object to the API call.
+
+Insert the `trigger identifier` as the name in the API request below:
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "novu-push-workflow-for-flutter",
+ "to": {
+ "subscriberId": "584349343"
+ },
+ "payload": {
+ "title": "This title was set via the Payload",
+ "body": "This body was set via the Payload"
+ },
+ }'
+
+```
+
+
+ {" "}
+
+
+## Handling Data Type Messages
+
+With FCM, you can send `Notification` and `Data` messages. We have handled sending notification messages. Let's handle data messages.
+
+Data messages contain user-defined custom key-value pairs. The information is encapsulated in the `data` key. The app can do whatever it pleases with the data once it's received by the device.
+
+**Via the Trigger API call**
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "novu-push-workflow-for-flutter",
+ "to": {
+ "subscriberId": "584349343"
+ },
+ "payload": {
+ "title": "This title was set via the Payload",
+ "body": "This body was set via the Payload"
+ },
+ "overrides": {
+ "fcm": {
+ "data": {
+ "subscription_status": "active",
+ "renewed_by": "bisola"
+ }
+ }
+ }
+ }'
+
+```
+
+
+
+
+
+## Sound of a notification
+
+You can use the name of a sound file in your app's main bundle or in the Library/Sounds folder of your app's container directory.
+
+Specify the string "default" to play the system sound. Use it for regular notifications. For critical alerts, use the sound dictionary instead.
+
+The code below works for iOS devices:
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "novu-push-workflow-for-flutter",
+ "to": {
+ "subscriberId": "584349343"
+ },
+ "payload": {
+ "title": "Notification With Sound",
+ "body": "Hello World from Novu"
+ },
+ "overrides": {
+ "fcm": {
+ "apns": {
+ "payload": {
+ "aps": {
+ "sound": "default" // configure sound to the notification
+ }
+ }
+ }
+ }
+ }
+ }'
+
+```
+
+For Android devices, use the following:
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "novu-push-workflow-for-flutter",
+ "to": {
+ "subscriberId": "584349343"
+ },
+ "payload": {
+ "title": "Notification With Sound",
+ "body": "Hello World from Novu"
+ },
+ "overrides": {
+ "fcm": {
+ "android": {
+ "notification": {
+ "defaultSound": true // This uses the Android framework's default sound for the notification.
+ }
+ }
+ }
+ }
+ }'
+
+```
+
+## Priority for notification
+
+If you omit this header, APNs (iOS) set the notification priority to `10`.
+
+- Specify `10` to send the notification immediately.
+- Specify `5` to send the notification based on power considerations on the userâs device.
+- Specify `1` to prioritize the deviceâs power considerations over all other factors for delivery and prevent awakening the device.
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "novu-push-workflow-for-flutter",
+ "to": {
+ "subscriberId": "584349343"
+ },
+ "payload": {
+ "title": "apns-priority: 5",
+ "body": "Novu's API"
+ },
+ "overrides": {
+ "fcm": {
+ "apns": {
+ "headers": {
+ "apns-priority":"5" //priority for notifications
+ },
+ "payload": {
+ "aps": {}
+ },
+ "fcm_options": {}
+ }
+ }
+ }
+ }'
+
+```
+
+For Android devices, specify `high` or `normal` for the priority of the notification message.
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "novu-push-workflow-for-flutter",
+ "to": {
+ "subscriberId": "584349343"
+ },
+ "payload": {
+ "title": "priority",
+ "body": "Novu's API"
+ },
+ "overrides": {
+ "fcm": {
+ "android": {
+ "priority": "high"
+ }
+ }
+ }
+ }'
+
+```
+
+## Sending Push Notification With Image
+
+Up to this point, your notifications have all contained only text. But if youâve received many notifications, you know that notifications can have rich content, such as images. Itâd be great if your notifications showed users a nice image related to their content. Once again, Firebase makes this super simple.
+
+To show an image in push notifications, youâll need to create a **_Notification Service Extension_**. We handled it earlier in this guide during the Apple setup.
+
+For reiteration, follow [this guide](https://firebase.flutter.dev/docs/messaging/apple-integration#advanced-optional-allowing-notification-images) to ensure it is properly set up for iOS devices.
+
+When making the API call, we should include:
+
+- "mutable-content": 1 inside the âapsâ object.
+- "image" in "fcm_options" object,
+- URL address of the image.
+
+```JSON
+
+curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
+ --header 'Authorization: ApiKey ' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{
+ "name": "untitled",
+ "to": {
+ "subscriberId": "12345678"
+ },
+ "payload": {
+ "title": "This is a notification with an image",
+ "body": "Check this out"
+ },
+ "overrides": {
+ "fcm": {
+ "apns": {
+ "payload": {
+ "aps": {
+ "mutable-content": 1
+ }
+ },
+ "fcm_options": {
+ "image": "https://www.planetware.com/wpimages/2020/02/france-in-pictures-beautiful-places-to-photograph-eiffel-tower.jpg"
+ }
+ }
+ }
+ }
+ }'
+```
+
+## Additional resources
+
+- [Notifications Usage - Flutter Fire](https://firebase.flutter.dev/docs/messaging/notifications)
diff --git a/legacy-guides/framework-guides/digest.mdx b/legacy-guides/framework-guides/digest.mdx
new file mode 100644
index 000000000..299117016
--- /dev/null
+++ b/legacy-guides/framework-guides/digest.mdx
@@ -0,0 +1,202 @@
+---
+title: "How to batch product notifications via code"
+description: "Leverage Novu's Digest Engine to batch product notifications"
+---
+
+# Introduction
+
+Learn how to use Novuâs Digest engine to batch notifications. In this guide, youâll learn how to aggregate multiple messages and send them off as one notification. Follow these steps:
+
+## Getting started
+
+Integrating Novuâs code-first workflow with React.Email for your Next.js application can be done in three steps
+
+1. Create a fully-featured Novu NextJS app with the command below:
+
+```bash
+npx novu init
+```
+
+1. Once this installation is complete, simply `cd` into the directory and start your app using the `npm run dev` command.
+
+Now, weâre all set to send digested notifications but before we do, letâs look at what it is and how it works:
+
+## Digest engine and how it works
+
+Novuâs Digest Engine is designed to consolidate multiple trigger events into a single cohesive message before delivering it to the subscriber. This functionality is essential for managing notification overload and ensuring that users receive meaningful, aggregated updates rather than being bombarded with numerous individual notifications. Hereâs how it works:
+
+1. **Event Accumulation**: The digest engine collects multiple trigger events based on a unique `subscriberId` to be delivered as one message.
+2. **Batching Events**: The engine batches these events within a specified time interval. This interval can be configured in units of seconds, minutes, hours, days, weeks, or months.
+3. **Delivery**: After the accumulation period, the batched events are sent out as a single notification. This consolidated message reduces the frequency of notifications and provides the user with a summary of all relevant events.
+
+## How to digest in a code-first workflow:
+
+1. Write a workflow and add a digest node to it:
+
+```tsx
+import { Client } from "@novu/framework";
+
+export const client = new Client({
+ apiKey: "",
+ /**
+ * Enable this flag only during local development
+ */
+ strictAuthentication: process.env.NODE_ENV !== "development",
+});
+
+export const digestWorkflow = workflow(
+ "novu-digest",
+
+ async ({ step, payload }) => {
+ // Add Digest Node
+ const digestResult = await step.digest("email-digest", async () => ({
+ unit: "seconds",
+ amount: 30,
+ }));
+
+ // Send a welcome email
+ await step.email("send-email", () => {
+ const resObj = {
+ subject: `Welcome to Novu`,
+ body: digestResult.events.map((event) => event.payload.text).join("\n"),
+ };
+ return resObj;
+ });
+ },
+ {
+ payloadSchema: {
+ properties: {
+ email: { type: "string" },
+ text: { type: "string", default: "Sumit" },
+ },
+ required: ["text"],
+ },
+ }
+);
+```
+
+
+đĄ In the digest node above, you can change the digest duration by setting a value to the key `amount` and changing the value of `unit` to seconds, minutes, hours, days, weeks, or months
+
+
+
+2. Hereâs a simple client-side app with a handler function attached to the `submit` event:
+
+```tsx
+"use client";
+import React, { useState } from "react";
+
+export default function Home() {
+ const [email, setEmail] = useState("");
+ const [text, setText] = useState("");
+
+ const onClickHandler = async (e: React.FormEvent) => {
+ try {
+ e.preventDefault();
+ await fetch("/api/users", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ email: email,
+ text: text,
+ }),
+ });
+
+ // console.log('working fine');
+ } catch (error) {
+ console.error("Error:", error);
+ }
+ };
+ return (
+
+
+
+ );
+}
+```
+
+3. And the corresponding route that it hits once the event fires:
+
+```tsx
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+export async function POST(request: Request) {
+ const res = await request.json();
+
+ await novu.trigger("novu-digest", {
+ to: {
+ subscriberId: "novu-sub-digest",
+ },
+ payload: {
+ email: res.email,
+ text: res.text,
+ },
+ });
+
+ console.log("triggered");
+ return Response.json({ success: true });
+}
+```
+
+Thatâs it!
+
+Thatâs how simple it is to use Novuâs Digest Engine. Digesting notifications enhances the user experience by providing comprehensive summaries, making it easier for users to stay informed about important updates in a concise manner, without straining users with too many notifications. We have got a thorough guide on digesting notifications [in our docs](https://docs.novu.co/guides/add-digest-to-email-notifications) that you can check out as well.
diff --git a/legacy-guides/framework-guides/framework-mjml.mdx b/legacy-guides/framework-guides/framework-mjml.mdx
new file mode 100644
index 000000000..53501da8c
--- /dev/null
+++ b/legacy-guides/framework-guides/framework-mjml.mdx
@@ -0,0 +1,386 @@
+---
+title: "How to send notifications with Next.js and MJML"
+description: "Leverage MJML package to send email notifications"
+---
+
+# Introduction
+
+This guide will walk you through how to send notifications with MJML and Novu. You can check out the code for a [sample demo app](https://github.com/novuhq/framework-mjml).
+
+## Pre-requisites
+
+- A Novu account
+- Node installed on your machine
+- A working NextJS development environment
+
+## Get started with Novu Framework
+
+[Novu Framework](https://docs.novu.co/framework/quickstart) is a "notifications as code" approach that enables developers to define workflows as functions and integrate them with their preferred libraries for email, SMS, and chat generation.
+
+1. To get started with Novu Framework, just run this command in your terminal, itâll scaffold a new NextJS project with Novu Framework and weâll be ready to roll!
+
+```jsx
+npx novu init --secret-key=
+
+```
+
+2. Once you execute this command, youâll be asked to give your project a name. Iâll keep the default `my-novu-app` but you can choose your own.
+
+ {" "}
+
+3. Youâll then be asked if you want to use React-email or not. Since, weâll be using MJML, Iâm choosing the default 'No' option.
+
+ {" "}
+
+4. After this step, all the dependencies will be installed and you will be able to start using Novu Framework.
+
+ {" "}
+
+5. Once this installation is complete, simply cd into the directory and start your app using the `npm run dev` command, and your app will be served on `localhost:4000`
+
+Make sure that the port 4000 isnât already being used!
+
+Youâll now have a NextJS app running on `http://localhost:4000` and you can make changes to your app as you see fit. Letâs now move to the meaty stuff - using Novu Framework in a NextJS app and the magic of Dev Studio.
+
+## Echo Dev Studio
+
+The Echo Dev Studio is a companion app to the Echo Client SDK. Its goal is to provide a local environment that lives near your code.
+
+To launch the dev studio locally you can run: `npx novu-labs@latest echo`. The Dev Studio will be started by default on port `2022`, and accessible via: `http://localhost:2022`
+
+
+ {" "}
+
+
+Hereâs how the Dev Studio looks on the first run:
+
+
+ {" "}
+
+Youâll notice that it asks for an `Echo endpoint` at the bottom. Novu Echo requires
+a single HTTP endpoint (`/api/echo` or similar) to be exposed by your application.
+This endpoint is used to receive events from our Worker Engine. We have more on Novu
+endpoint [in our docs.](https://docs.novu.co/framework/concepts/endpoint)
+
+
+ You can view the Echo Endpoint as a webhook endpoint that Novu will call when
+ it needs to retrieve contextual information for a given subscriber and
+ notification.
+
+
+Just enter the full URL of your Echo Endpoint. In our case, it is `http://localhost:4000/api/echo`
+
+
+ {" "}
+
+Once you do, youâll see a green checkmark alongside the URL input box and a green
+`connected` highlight at the top right corner.
+
+## Installing and configuring MJML
+
+Integrating MJML with Novu in our NextJS app is quite straightforward, with just one small caveat. Following are the steps to get it installed and configured:
+
+1. Simply run the following command to install it like any other npm package:
+
+```bash
+npm i mjml
+```
+
+
+ Once installed, you need to keep in mind that, MJML doesnât play very nice
+ with newer web technologies such as Next.js that weâre using today. In order
+ to overcome some hurdles, we need to use the `require` statement when
+ importing MJML in our files, such as when defining the template.
+
+
+2. To write an email template, you can look over some of the examples in the MJML documentation to get inspiration from. In our case, this is the template:
+
+```jsx
+// notice the use of require statement here:
+const mjml2html = require("mjml");
+
+export const mjmlTemplate = (inputs: Inputs) => {
+ const { text, buttonText, imageUrl, buttonUrl } = inputs;
+ return mjml2html(`
+
+
+
+
+ ${text}
+
+
+ OnePage
+
+
+
+
+
+
+
+ HomeFeatures
+ Portfolio
+
+
+
+
+
+ More than an email template
Only on Mailjet template builder
+ ${buttonText}
+
+
+
+
+
+ Best audience
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eleifend sagittis nunc, et fermentum est ullamcorper dignissim.
+
+
+
+ Higher rates
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eleifend sagittis nunc, et fermentum est ullamcorper dignissim.
+
+
+
+ 24/7 Support
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eleifend sagittis nunc, et fermentum est ullamcorper dignissim.
+
+
+
+
+ Why choose us?
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris. Lorem ipsum dolor sit amet, consectetur adipiscing
+ elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
+
+
+
+
+
+
+
+ Great newsletter for the best company out there
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
+ aliqua. Ut enim ad minim veniam.
+ READ MORE
+
+
+
+
+
+
+ Please contact us if you have any questions.
+
+
+
+
+
+ `);
+};
+```
+
+3. And as final step, we need to define the workflow that uses the template defined above.
+
+```jsx
+import { Client, workflow } from "@novu/framework";
+import { mjmlTemplate } from "./mjml";
+
+export const client = new Client({
+ apiKey: process.env.NOVU_SECRET_KEY,
+ strictAuthentication: process.env.NODE_ENV !== "development",
+});
+
+export const emailWorkflow = workflow('mjml-email-workflow', async ({ payload, step }) => {
+ await step.email('send-email', async (inputs) => {
+ return {
+ subject: `Welcome to MJML with Novu Framework, ${payload.text}!`,
+ body: mjmlTemplate(inputs).html,
+ };
+ }, {
+ controlSchema: {
+ type: 'object',
+ properties: {
+ text: { type: 'string', default: 'Welcome to our service' },
+ imageUrl: { type: 'string', default: 'https://picsum.photos/id/11/2000/300' },
+ buttonText: { type: 'string', default: 'Sign up' },
+ buttonUrl: { type: 'string', default: 'https://novu.co' },
+ },
+ additionalProperties: false,
+ } as const
+ });
+}, {
+ payloadSchema: {
+ properties: {
+ text: { type: 'string', default: 'Sumit' },
+ },
+ additionalProperties: false,
+ }
+});
+```
+
+Once you do this, youâll see this workflow, the steps in the workflow, step inputs, payload variables and the rendered view of this workflow on the Echo Dev Studio:
+
+
+ {" "}
+
+Here, from the Dev Studio, you or your peers can change things like the text of a
+button, toggle visibility of a button, static text content etc and have it synced
+with the cloud with the `Sync to Cloud` button.
+
+### Payload vs Step Inputs
+
+Notice that in the Echo dev studio above, weâve used payload as well as step inputs. Hereâs how you can decide if you need either or both:
+| Payload | Step Inputs |
+| -------- | ------------------------------------- |
+| is used for dynamic content that changes from one notification to another based on events occurring in your system. | are used for static elements or predefined options that non-technical team members can modify without altering the codebase.|
+| is controlled by developers and passed dynamically through the novu.trigger method. | are defined by developers but aremeant to be utilized and modified by non-technical peers.|
+| Payload examples include User ID, Post ID, Comment, Order ID, 2FA token, etc., which are likely to change with each notification. | Step Inputs examples include the text of a button, whether a section should be shown, static text content, etc., which are generally static but configurable elements.|
+| Payload modifications are made in the code by developers at the time of triggering a notification. | Step Inputs can be modified directly in the UI, offering a no-code solution for non-technical team members to make changes.|
+| Payload data is passed during the novu.trigger method and is part of the dynamic data handling process within notification workflows.| Step Inputs are predefined in the workflow configuration and can be adjusted through the Echo Dev Studio, affecting how notifications are rendered without changing the workflow logic.|
+
+## Syncing with the cloud, with the click of a button
+
+Once done with the workflow, now we need to sync it to the cloud. Fortunately, Novu Framework makes it a breeze to sync changes from the local machine to the cloud and it all happens with a click of a button.
+
+To enable our cloud environment to talk to your local Bridge instance, you need to supply an [Bridge Endpoint](/concepts/endpoint) URL. This sets up a communication channel between our cloud environment and your local instance. To allow Novu to communicate with your local machine a tunnel will need to be generated.
+
+Running the `npm run dev` script in the project launches both the Bridge application and the tunnel solution. The tunnel URL shows up in the console output.
+
+You can also use a tool like `ngrok`:
+
+```bash
+// using ngrok
+ngrok http http://localhost:
+```
+
+In our case, the app is running on port 4000 so weâll use:
+
+```bash
+ngrok http http://localhost:4000
+```
+
+This will create a tunnel and youâll see something like this in the terminal:
+
+
+ {" "}
+
+Remember, the exact URL (`/api/novu` or similar) you expose in your application for
+handling Novu Framework requests is what you'd consider the `Bridge URL`.
+
+This URL would be the endpoint within your application's domain where Novu's Worker Engine sends requests to fetch notification content or subscriber details dynamically. In our case, it is this: https://faec-2409-40f2-3c-3b57-400e-a7f7-1fc0-1e5.ngrok-free.app/api/echo
+So, weâll enter this Bridge URL:
+
+
+ {" "}
+
+And create diff:
+
+ {" "}
+
+
+## Testing our workflow
+
+Once youâve synced your changes in the previous step, youâll see a notification that says âSync completeâ and you can now go to Novu Cloud using the âTest your workflowsâ link and trigger a notification.
+
+
+ {" "}
+
+Youâll see the workflow youâve created has a blue lightning bolt icon. That icon
+signifies that the corresponding workflow has been created with Novu Framework:
+
+ {" "}
+
+Simply open the workflow and you can send a test email from there.
+
+
+ Make sure that all the expected payload variables and step inputs are being
+ sent in their respective fields!
+
+
+ {" "}
+
+This is the workflow test email in my inbox:
+
+ {" "}
+
+Once tested, you can simply have this workflow triggered whenever you want. For
+instance, a typical use case is to have a workflow triggered when an event
+occurs. To replicate it, Iâve attached a handler function that triggers this
+workflow when the `submit` event fires:
+
+Hereâs a simple replication of the stipulated scenario:
+
+```jsx
+"use client";
+
+import { useState } from "react";
+
+export default function Home() {
+ const [loading, setLoading] = useState(false);
+ const [text, setText] = useState("");
+ const [email, setEmail] = useState("");
+
+ const triggerWorkflow = async () => {
+ setLoading(true);
+ const response = await fetch("/api/users", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ text: text,
+ email: email,
+ }),
+ });
+ const result = await response.json();
+ setLoading(false);
+ console.log(result);
+ };
+ return (
+
+ );
+}
+```
+
+And the corresponding route it hits:
+
+```jsx
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+export async function POST(request: Request) {
+ const res = await request.json();
+
+ await novu.trigger("mjml-email-workflow", {
+ to: {
+ subscriberId: "novu-sub-two",
+ email: res.email,
+ },
+ payload: {
+ text: res.text,
+ },
+ });
+
+ console.log("triggered");
+ return Response.json({ success: true });
+}
+```
+
+So there you go!
+
+This is how you create workflows using Novu Framework and deploy your changes seamlessly to the Novu cloud. You can check out the code for a [sample demo app](https://github.com/novuhq/framework-mjml).
+
+Once you've built the workflow, you might want read one of [our other guides](/legacy-guides/framework-guides/product) on how to empower product teams to manage notification workflows.
+
+Donât forget to share your workflows with us and as always, hit us up on Discord with any questions you might have!
diff --git a/legacy-guides/framework-guides/framework-nuxt-vuemail.mdx b/legacy-guides/framework-guides/framework-nuxt-vuemail.mdx
new file mode 100644
index 000000000..1b9ff27e1
--- /dev/null
+++ b/legacy-guides/framework-guides/framework-nuxt-vuemail.mdx
@@ -0,0 +1,496 @@
+---
+title: "How to send notifications with Nuxt.js and Vuemail"
+description: "Learn how to send email notifications with Nuxt.js, Vuemail and Novu"
+---
+
+This guide assumes you know what [a notification workflow](https://docs.novu.co/workflows/notification-workflows) is and why you need it. It also assumes you are aware of [Nuxt](https://nuxt.com/) and [VueEmail](https://vuemail.net/).
+Fantastic. Now that we are all on the same page letâs proceed.
+
+Novu recently released a new way of baking notification workflows into your apps via code, and itâs huge! Let me walk you through it.
+
+Itâs called Novu Framework and you can learn more about it by visiting the related [documentation](https://docs.novu.co/framework/quickstart). You might also benefit from reading this excellent [Code-First Approach to Managing Notification Workflows](https://novu.co/blog/a-code-first-approach-to-managing-notification-workflows/) article.
+
+If you prefer to clone the repository from GitHub and get your hands dirty, we arenât going to stop you. You can find it [here](https://github.com/novuhq/novu-framework-nuxt-vue-email-example).
+
+Still here? Good, I wrote this guide for you!
+
+## Getting Started
+
+## 1. Initialize **New Nuxt Project**
+
+We will follow the [official installation guide from Nuxt](https://nuxt.com/docs/getting-started/installation), open your terminal / IDE, and run the following command:
+
+```jsx
+npx nuxi@latest init
+```
+
+## 2. **Integrate Novu Framework Into Our App (Notification Workflow)**
+
+1. We will install the `@novu/framework` package in the root of our Nuxt app directory by running the following command:
+
+```jsx
+npm install @novu/framework
+```
+
+2. We must provide an API endpoint for the [Novu Dev Studio](https://docs.novu.co/framework/concepts/studio) to fetch our notification workflow. (Donât worry; we guide you through all the steps.) Navigate to your app's `app/server` directory and create a new directory named `api`.
+
+```jsx
+cd app/server
+
+mkdir api
+```
+
+Create a file within the `app/server/api` directory and name it `novu.ts`. Copy and paste the code snippet below:
+
+```jsx
+// app/server/api/novu.ts
+import { serve } from "@novu/framework/nuxt";
+import { client, myWorkflow } from "../novu/workflows";
+
+export default defineEventHandler(
+ serve({ client: client, workflows: [myWorkflow] })
+);
+```
+
+3. Now, let's create the instance where we will build and maintain our notification workflow:
+
+Navigate to your `app/server` directory and create another directory named `novu`.
+
+```jsx
+cd app/server
+
+mkdir novu
+```
+
+Create a file within the `app/server/novu` directory and name it `workflows.ts`. Copy and paste the code snippet below:
+
+```jsx
+// app/server/novu/workflows.ts
+// This workflow already renders vue email template.
+
+import { config } from '@vue-email/compiler'
+import { Client, workflow } from '@novu/framework';
+
+const vueEmail = config('templates', {
+ verbose: false,
+ options: {
+ },
+})
+
+export const client = new Client({
+ /**
+ * Disable this flag only during local development
+ * For production this should be true
+ */
+ strictAuthentication: process.env.NODE_ENV !== "development"
+});
+
+export const myWorkflow = workflow('hello-world', async ({ step, payload }) => {
+ await step.email(
+ 'send-email',
+ async () => {
+ const template = await vueEmail.render('sample-email.vue', {
+ props: payload,
+ });
+ return {
+ subject: `You have a new invitation from: ${payload.username}.`,
+ body: template.html,
+ }
+ });
+},
+ {
+ payloadSchema: {
+ // Always `object`
+ type: 'object',
+ // Specify the properties to validate. Supports deep nesting.
+ properties: {
+ username: { type: "string" },
+ invitedByEmail: { type: "string" },
+ inviteLink: { type: "string" },
+ inviteFromIp: { type: "string" },
+ inviteFromLocation: { type: "string" }
+ },
+ // Used to enforce full type strictness, with no rogue properties.
+ additionalProperties: false,
+ // The `as const` is important to let Typescript know that this
+ // type won't change, enabling strong typing on `inputs` via type
+ // inference of the provided JSON Schema.
+ } as const,
+ },
+);
+```
+
+We havenât finished the guide yet but have everything to build a notification workflow.
+
+Below, We can see a âplainâ Client instance and shaping your desired workflow.
+
+```jsx
+// app/server/novu/workflows.ts
+// This is Client instance concept - not a working instance!
+
+import { Client, workflow } from "@novu/framework";
+
+export const client = new Client({
+ /**
+ * Disable this flag only during local development
+ * For production this should be true
+ */
+ strictAuthentication: process.env.NODE_ENV !== "development",
+});
+
+export const myWorkflow = workflow(
+ "", // The Workflow name. Must be unique across your Bridge application.
+ // Workflow resolver, the entry-point for your Workflow steps
+ async ({
+ // Helper function to declare your Workflow Steps.
+ step,
+ // Workflow Trigger payload
+ payload,
+ }) => {
+ // ...your Workflow Steps
+ },
+ {
+ // JSON Schema for validation and type-safety. Zod, and others coming soon.
+ // https://json-schema.org/draft-07/json-schema-release-notes
+
+ // The schema for the Workflow payload passed dynamically via Novu Trigger API
+ // Defaults to an empty schema.
+ payloadSchema: { properties: { name: { type: "string" } } },
+ // The schema for the Workflow inputs passed statically via Novu Web
+ // Defaults to an empty schema.
+ controlSchema: { properties: { brandColor: { type: "string" } } },
+ }
+);
+```
+
+We can:
+
+- Select a name for our workflow.
+- Declare [Workflow Steps](https://docs.novu.co/framework/steps/introduction) as we see fit for our use case
+- Configure what could be passed in the payload of the Workflow Trigger ([payloadSchema](https://docs.novu.co/framework/concepts/inputs))
+- Configure what inputs could be passed statically via Novu Web ([controlSchema](https://docs.novu.co/framework/concepts/inputs))
+
+Note: You can create and manage as many workflows as you wish within `app/server/novu/workflows.ts`; make sure to provide each workflow with a unique name.
+
+## 3. Adding Vuemail in our notification workflow
+
+1. We will install the `vue-email` package in the root of our Nuxt app directory by running the following command:
+
+```jsx
+npm install vue-email
+```
+
+2. We will create one more directory in the root of our directory and name it `templates`. That is where our vue-email templates will be stored.
+
+```c
+mkdir templates
+```
+
+3. In the `app/templates` directory, we will create a file for our first vue-email template and name it `sample-email.vue`.
+
+[You can find examples of Vue email templates here.](https://vuemail.net/playground)
+
+```jsx
+// app/templates/sample-email.vue
+
+
+
+
+
+
+
+ {{ previewText }}
+
+
+
+ Accept
+ Hello {{ username }},
+
+
+
+
+
+
+
+ New Project {{ teamName }} available
+
+ Hello {{ username }},
+
+ {{invitedByUsername}} (
+
+ {{ invitedByEmail }}
+
+ ) has invited you to the {{ teamName }} project on Acme.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Accept
+ Decline
+
+
+
+ or copy and paste this URL into your browser:
+
+ {{ inviteLink }}
+
+
+
+
+
+ This invitation was intended for
+ {{ username }} .This invite was sent from {{ inviteFromIp }} located in
+ {{ inviteFromLocation }}. If you were not expecting this invitation, you can ignore this email. If you are concerned about your account's safety, please reply to this email to get in touch
+ with us.
+
+
+
+
+
+
+
+```
+
+## 4. Launching The Dev Studio
+
+Now that we have everything in our notification workflow configured along with the vue-email template we will use, itâs time to see a visual representation of what we have built.
+
+1. If you havenât run the development environment for your Nuxt app, now is the time.
+
+ ```jsx
+ npm run dev
+ ```
+
+2. Do you remember that we exposed an Bridge API endpoint in our app for Dev Studio to catch? This is where it happens.
+
+ Run the following command in a separate terminal:
+
+ ```jsx
+ npx novu-labs@latest echo
+ ```
+
+ If youâve followed this guide, you should see this:
+
+
+
+
+
+ Here is where our exact API endpoint goes. If our application runs on a different port, we should change the URL manually to point Dev Studio in the right direction.
+
+
+
+
+
+ Also, if we have configured everything correctly, we should see that Dev Studio sees our workflow identifier (Workflow unique name).
+
+
+
+
+
+3. Click the âView Workflowâ button in the Dev Studio to see the workflow.
+
+ We should see the following:
+
+
+
+
+
+Click on the workflow step node called `send-email`. We should see a preview of our email template and the `Step Input` and `Payload` variables we have configured in the workflow schemas.
+
+
+
+
+
+4. This is the time to adjust the email template, step input schema, or define the properties we anticipate in the payload. We have a live representation of everything. You can add more steps like In-App, SMS, and chat.
+
+## 5. Syncing our workflow to Novu Cloud
+
+Having completed crafting, designing, and modifying our notification workflow to suit our requirements, we're ready to push it to Novu Cloud. There, it will handle the heavy lifting and seamlessly execute all the steps we've configured whenever we trigger the workflow.
+
+1. Click on the `Sync to Cloud` button on the top right.
+
+
+
+
+
+2. We will need to create a local tunnel that the Novu Cloud environment can reach for local experimentation purposes.
+
+
+
+
+
+ On a separate terminal, run the following command:
+
+ ```jsx
+ // Change to the port where the app is currently running
+
+ npx localtunnel --port 3000
+ ```
+
+ We should get something like:
+
+ ```jsx
+ your url is: https://famous-pumas-clap.loca.lt
+ ```
+
+
+
+
+
+3. Click the `Create Diff` button. To push (merge) the workflow code to the cloud, an API Key from our Novu account should be added to our Framework Client instance.
+
+
+
+
+
+ Letâs navigate to `../app/server/novu/workflows.ts` file and add our Novu API Key.
+
+```jsx
+// app/server/novu/workflows.ts
+// This workflow already renders vue email template.
+
+import { config } from '@vue-email/compiler'
+import { Client, workflow } from '@novu/framework';
+
+const vueEmail = config('templates', {
+ verbose: false,
+ options: {
+ },
+})
+
+export const client = new Client({
+ apiKey: process.env.NOVU_SECRET_KEY, // <<-- Your Novu API KEY
+ /**
+ * Disable this flag only during local development
+ * For production this should be true
+ */
+ strictAuthentication: process.env.NODE_ENV !== "development"
+});
+
+export const myWorkflow = workflow('hello-world', async ({ step, payload }) => {
+ await step.email(
+ 'send-email',
+ async () => {
+ const template = await vueEmail.render('sample-email.vue', {
+ props: payload,
+ });
+ return {
+ subject: `You have a new invitation from: ${payload.username}.`,
+ body: template.html,
+ }
+ });
+},
+ {
+ payloadSchema: {
+ // Always `object`
+ type: 'object',
+ // Specify the properties to validate. Supports deep nesting.
+ properties: {
+ username: { type: "string" },
+ invitedByEmail: { type: "string" },
+ inviteLink: { type: "string" },
+ inviteFromIp: { type: "string" },
+ inviteFromLocation: { type: "string" }
+ },
+ // Used to enforce full type strictness, with no rogue properties.
+ additionalProperties: false,
+ // The `as const` is important to let Typescript know that this
+ // type won't change, enabling strong typing on `inputs` via type
+ // inference of the provided JSON Schema.
+ } as const,
+ },
+);
+```
+
+ We will now click the `Create Diff` button again.
+
+
+
+ This is where you can review all the changes made to the workflow. Once you have verified that everything is in order, go ahead and click the `Deploy Changes` button.
+
+
+
+ ## 6. Testing Our Notification Workflow
+
+ There are many ways to test and [trigger our workflow](https://docs.novu.co/api-reference/events/trigger-event), but we'll make a `cURL` API call to Novu Cloud from our terminal in this guide.
+
+ If we don't have any subscribers or users in our database or within our Novu Cloud organization, we'll send the test to ourselves for simplicity.
+
+ - In the `subscriberId` key, input a random number or even our email address (as long as we do not try to assign the same ID key to another subscriber, we should be good).
+ - For the `email` key, we will need to insert a valid email address so we can actually receive the email.
+
+
+ **Note:** Learn more about the structure of [subscriber properties](https://docs.novu.co/subscribers/subscribers).
+
+ We can leave the payload empty or add properties aligned with the `payloadSchema` we established in the workflow definition.
+
+ ```jsx
+
+ curl -X POST https://api.novu.co/v1/events/trigger \
+ -H "Authorization: ApiKey " \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "hello-world",
+ "to": {
+ "subscriberId": "",
+ "email": "john@doemail.com",
+ },
+ "payload": {
+ "username": "Jane Doe",
+ "invitedByEmail": "Jane@doemail.com",
+ "inviteLink": "https://acme.com/projects/accept/foo",
+ "inviteFromIp": "172.0.0.1",
+ "inviteFromLocation": "New York, DC"
+ }
+ }'
+
+ ```
+
+ Now, letâs check our email inbox.
+
+ - No longer limited by UI notification steps and rigidity.
+ - No longer limited by notification content editors and systems. The more, the merrier!
+ - Now an IFTTT (If-This-Then-That) pro engineer!
+
+ Once you've built the workflow, you might want read one of [our other guides](/legacy-guides/framework-guides/product) on how to empower product teams to manage notification workflows. Have fun, and share your use case on Discord with us!
diff --git a/legacy-guides/framework-guides/framework-react-email.mdx b/legacy-guides/framework-guides/framework-react-email.mdx
new file mode 100644
index 000000000..48000b678
--- /dev/null
+++ b/legacy-guides/framework-guides/framework-react-email.mdx
@@ -0,0 +1,555 @@
+---
+title: "How to send notifications with Next.js and React email"
+description: "Leverage the React email package to send email notifications"
+---
+
+# Introduction
+
+In this guide, youâll learn how to send email notifications using the React email package. But before we jump into it, let's first take a look at the prerequisites!
+
+## Pre-requisites
+
+- A Novu account
+- Node installed on your machine
+- A working NextJS development environment
+
+## Get started with Novu Framework
+
+[Novu Framework](https://docs.novu.co/framework/quickstart) is a "notifications as code" approach that enables developers to define workflows as functions and integrate them with their preferred libraries for email, SMS, and chat generation.
+
+1. To get started with Novu Framework, just run this command in your terminal, itâll scaffold a new NextJS project with Novu Framework and weâll be ready to roll!
+
+```jsx
+npx novu init --secret-key=
+```
+
+2. Once you execute this command, youâll be asked to give your project a name. Iâll keep the default `my-novu-app` but you can choose your own.
+
+ {" "}
+
+3. Youâll then be asked if you want to use React-email or not. You can choose to install it at this step itself or proceed with No and then install it later. Iâm choosing the default No option.
+
+ {" "}
+
+4. After this step, all the dependencies will be installed and you will be able to start using Novu Framework.
+
+ {" "}
+
+5. Once this installation is complete, simply cd into the directory and start your app using the `npm run dev` command, and your app will be served on `localhost:4000`
+
+Make sure that the port 4000 isnât already being used!
+
+Youâll now have a NextJS app running on `http://localhost:4000` and you can make changes to your app as you see fit. Letâs now move to the meaty stuff - using Novu Framework in a NextJS app and the magic of Dev Studio.
+
+## Echo Dev Studio
+
+The Echo Dev Studio is a companion app to the Echo Client SDK. Its goal is to provide a local environment that lives near your code.
+
+To launch the dev studio locally you can run: `npx novu-labs@latest echo`. The Dev Studio will be started by default on port `2022`, and accessible via: `http://localhost:2022`
+
+
+ {" "}
+
+
+Hereâs how the Dev Studio looks on the first run:
+
+
+ {" "}
+
+Youâll notice that it asks for an `[Bridge Endpoint](/concepts/endpoint)` at the bottom. Novu Framework
+requires a single HTTP endpoint (`/api/novu` or similar) to be exposed by your application.
+This endpoint is used to receive events from our Worker Engine. We have more on Bridge
+endpoint [in our docs.](https://docs.novu.co/framework/concepts/endpoint)
+
+
+You can view the [Bridge Endpoint](/concepts/endpoint) as a webhook endpoint that Novu will call when it needs to retrieve contextual information for a given subscriber and notification.
+
+
+
+Just enter the full URL of your [Bridge Endpoint](/concepts/endpoint). In our case, it is `http://localhost:4000/api/echo`
+
+
+ {" "}
+
+Once you do, youâll see a green checkmark alongside the URL input box and a green
+`connected` highlight at the top right corner.
+
+## Installing and configuring React Email
+
+
+ If you opted for installing React Email in our CLI set-up process, you can
+ skip installing it again.
+
+
+Integrating React Email with Novu in our NextJS app is quite straightforward. Following are the steps to get it installed and configured:
+
+1. Simply run the following command to install it like any other npm package:
+
+```jsx
+ npm i @react-email/components react-email
+```
+
+Once installed, proceed to write an email template in the next step
+
+2. To write an email template, you can look over some of the examples in the [React Email documentation](https://react.email/examples) to get inspiration. In our case, this is the template:
+
+```jsx
+import {
+ Body,
+ Button,
+ Container,
+ Column,
+ Head,
+ Hr,
+ Html,
+ Img,
+ Link,
+ render,
+ Row,
+ Section,
+ Text,
+ Tailwind,
+} from "@react-email/components";
+import * as React from "react";
+
+interface VercelInviteUserEmailProps {
+ username?: string;
+ userImage?: string;
+ invitedByUsername?: string;
+ invitedByEmail?: string;
+ teamName?: string;
+ teamImage?: string;
+ inviteLink?: string;
+ inviteFromIp?: string;
+ showJoinButton?: boolean;
+ inviteFromLocation?: string;
+ buttonText?: string
+}
+
+const baseUrl = process.env.VERCEL_URL
+ ? `https://${process.env.VERCEL_URL}`
+ : "";
+
+export const VercelInviteUserEmail = ({
+ username,
+ userImage,
+ invitedByUsername,
+ invitedByEmail,
+ teamName,
+ teamImage,
+ inviteLink,
+ inviteFromIp,
+ inviteFromLocation,
+ showJoinButton,
+ buttonText
+}: VercelInviteUserEmailProps) => {
+
+ return (
+
+
+
+
+
+
+
+
+
+ Hello {username},
+
+
+ {invitedByUsername} (
+
+ {invitedByEmail}
+
+ ) has invited you to the {teamName} team on{" "}
+ Vercel.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {showJoinButton && (
+
+
+
+ )}
+
+ or copy and paste this URL into your browser:{" "}
+
+ {inviteLink}
+
+
+
+
+ This invitation was intended for{" "}
+ {username}. This invite was
+ sent from {inviteFromIp}{" "}
+ located in{" "}
+ {inviteFromLocation}. If you
+ were not expecting this invitation, you can ignore this email. If
+ you are concerned about your account's safety, please reply to
+ this email to get in touch with us.
+
+
+
+
+
+ );
+};
+
+VercelInviteUserEmail.PreviewProps = {
+ username: "alanturing",
+ userImage: `${baseUrl}/static/vercel-user.png`,
+ invitedByUsername: "Alan",
+ invitedByEmail: "alan.turing@example.com",
+ teamName: "Enigma",
+ teamImage: `${baseUrl}/static/vercel-team.png`,
+ inviteLink: "https://vercel.com/teams/invite/foo",
+ inviteFromIp: "204.13.186.218",
+ inviteFromLocation: "SĂŁo Paulo, Brazil",
+} as VercelInviteUserEmailProps;
+
+export default VercelInviteUserEmail;
+
+export function renderReactEmail(input: any, payload: any) {
+ return render();
+
+}
+```
+
+3. And as final step, we need to define the workflow that uses the template defined above.
+
+```jsx
+export const newSignup = workflow(
+ "new-signup",
+ async ({ step, payload }) => {
+ // Send a welcome email
+ await step.email(
+ "send-email",
+ async (inputs) => {
+ return {
+ subject: `Welcome to Novu, ${payload.username}`,
+ body: renderReactEmail(inputs, payload),
+ };
+ },
+ {
+ controlSchema: {
+ type: "object",
+ properties: {
+ showJoinButton: { type: "boolean", default: true },
+ buttonText: { type: "string", default: "Join the team" },
+ userImage: {
+ type: "string",
+ default:
+ "https://react-email-demo-bdj5iju9r-resend.vercel.app/static/vercel-user.png",
+ format: "uri",
+ },
+ invitedByUsername: { type: "string", default: "Alan" },
+ invitedByEmail: {
+ type: "string",
+ default: "alan.turing@example.com",
+ format: "email",
+ },
+ teamName: { type: "string", default: "Team Awesome" },
+ teamImage: {
+ type: "string",
+ default:
+ "https://react-email-demo-bdj5iju9r-resend.vercel.app/static/vercel-team.png",
+ format: "uri",
+ },
+ inviteLink: {
+ type: "string",
+ default: "https://vercel.com/teams/invite/foo",
+ format: "uri",
+ },
+ inviteFromIp: { type: "string", default: "204.13.186.218" },
+ inviteFromLocation: {
+ type: "string",
+ default: "SĂŁo Paulo, Brazil",
+ },
+ },
+ },
+ }
+ );
+ // JSON Schema for validation and type-safety. Zod, and others coming soon.
+ },
+ { payloadSchema: { properties: { text: { type: "string" } } } }
+);
+```
+
+Once you do this, youâll see this workflow, the steps in the workflow, step inputs, payload variables and, the rendered view of this workflow on the Echo Dev Studio:
+
+
+ {" "}
+
+Here, from the Dev Studio, you or your peers can change things like the text of a
+button, toggle visibility of a button, static text content, etc, and have it synced
+with the cloud with the `Sync to Cloud` button.
+
+### Payload vs Step Inputs
+
+Notice that in the Echo dev studio above, weâve used payload as well as step inputs. Hereâs how you can decide if you need either or both:
+
+- Payload is used for dynamic content that changes from one notification to another based on events occurring in your system.
+- Step Inputs are for static elements or predefined options that non-technical team members can modify without altering the codebase.
+- Payload is controlled by developers and passed dynamically through the novu.trigger method.
+- Step Inputs are defined by developers but are meant to be utilized and modified by non-technical peers.
+- Payload examples include User ID, Post ID, Comment, Order ID, 2FA token, etc., which are likely to change with each notification.
+- Step Inputs examples include the text of a button, whether a section should be shown, static text content, etc., which are generally static but configurable elements.
+- Payload modifications are made in the code by developers at the time of triggering a notification.
+- Step Inputs can be modified directly in the UI, offering a no-code solution for non-technical team members to make changes.
+- Payload data is passed during the novu.trigger method and is part of the dynamic data handling process within notification workflows.
+- Step Inputs are predefined in the workflow configuration and can be adjusted through the Echo Dev Studio, affecting how notifications are rendered without changing the workflow logic.
+
+## Syncing with the cloud, with the click of a button
+
+Once done with the workflow, now we need to sync it to the cloud. Fortunately, Novu Framework makes it a breeze to sync changes from the local machine to the cloud and it all happens with a click of a button.
+
+To enable our cloud environment to talk to your local Echo instance, you need to supply an Echo endpoint URL. This sets up a communication channel between our cloud environment and your local instance. To allow Novu to communicate with your local machine a tunnel will need to be generated.
+
+Running the `npm run dev` script in the project launches both the Bridge application and the tunnel solution. The tunnel URL shows up in the console output.
+
+You can also use a tool like `ngrok`:
+
+```bash
+// using ngrok
+ngrok http http://localhost:
+```
+
+In our case, the app is running on port 4000 so weâll use:
+
+```bash
+ngrok http http://localhost:4000
+```
+
+This will create a tunnel and youâll see something like this in the terminal:
+
+
+ {" "}
+
+Remember, the exact URL (`/api/novu` or similar) you expose in your application for
+handling Novu Framework requests is what you'd consider the `Bridge URL`.
+
+This URL would be the endpoint within your application's domain where Novu's Worker Engine sends requests to fetch notification content or subscriber details dynamically. In our case, it is this: `https://0536-2409-40f2-1039-43e1-3053-d98e-c276-ee5.ngrok-free.app/api/echo`
+
+So, weâll enter this Bridge URL:
+
+
+ {" "}
+
+And create diff:
+
+ {" "}
+
+
+## Testing our workflow
+
+Once youâve synced your changes in the previous step, youâll see a notification that says âSync completeâ and you can now go to Novu Cloud using the âTest your workflowsâ link and trigger a notification.
+
+
+ {" "}
+
+Youâll see the workflow youâve created has a blue lightning bolt icon. That icon
+signifies that the corresponding workflow has been created with Novu Framework:
+
+ {" "}
+
+Simply open the workflow and you can send a test email from there.
+
+
+ Make sure that all the expected payload variables and step inputs are being
+ sent in their respective fields!
+
+
+ {" "}
+
+This is the workflow test email in my inbox:
+
+ {" "}
+
+Once tested, you can simply have this workflow triggered whenever you want. For
+instance, a typical use case is to have a workflow triggered when an event
+occurs. To replicate it, Iâve attached a handler function that triggers this
+workflow when the `submit` event fires:
+
+Hereâs a simple replication of the stipulated scenario:
+
+```jsx
+"use client";
+import Image from "next/image";
+import styles from "./page.module.css";
+import React, { useState } from "react";
+import axios from "axios";
+
+export default function Home() {
+ const [email, setEmail] = useState("");
+ const [username, setUsername] = useState("");
+
+ const onClickHandler = async (e: React.FormEvent) => {
+ try {
+ e.preventDefault();
+ await fetch("/api/users", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ email: email,
+ username: username,
+ }),
+ });
+
+ // console.log('working fine');
+ } catch (error) {
+ console.error("Error:", error);
+ }
+ };
+ return (
+
+
+
+ );
+}
+```
+
+And the corresponding route it hits:
+
+```jsx
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+export async function POST(request: Request) {
+ const res = await request.json();
+
+ await novu.trigger("", {
+ to: {
+ subscriberId: "",
+ },
+ payload: {
+ email: res.email,
+ username: res.username,
+ },
+ });
+
+ console.log("triggered");
+ return Response.json({ success: true });
+}
+```
+
+## More workflow examples
+
+Creating workflows with Novu Framework is a breeze. Here are a couple of other examples from React email docs created with Novu Framework:
+
+1. AWS Email verification example
+
+ {" "}
+
+2. Apple invoice email example
+
+ {" "}
+
+
+## Conclusion
+
+So there you go!
+
+This is how you create workflows using Novu Framework and deploy your changes seamlessly to the Novu cloud. You can check out the code for a [sample demo app](https://github.com/novuhq/novu-framework-nextjs-react-email-example).
+Once you've built the workflow, you might want read one of [our other guides](/legacy-guides/framework-guides/product) on how to empower product teams to manage notification workflows.
+
+
+Donât forget to share your workflows with us and as always, hit us up on Discord
+with any questions you might have!
diff --git a/legacy-guides/framework-guides/framework-remix.mdx b/legacy-guides/framework-guides/framework-remix.mdx
new file mode 100644
index 000000000..ba26a774a
--- /dev/null
+++ b/legacy-guides/framework-guides/framework-remix.mdx
@@ -0,0 +1,335 @@
+---
+title: "How to send notifications with Remix and React email"
+description: "Learn how to send email notifications with Remix, React email and Novu"
+---
+
+# Introduction
+
+Learn how to send notifications with Remix, React email and Novu. You can check out the complete code for a [working app](https://github.com/novuhq/novu-framework-remix-example).
+
+## Prerequisites
+
+- A Novu account
+- Node installed on your machine
+- A working Remix app
+
+## Follow these Steps
+
+### 1. Install all dependencies including react email components
+
+```jsx
+ npm install @novu/framework @react-email/components react-email
+```
+
+### 2. Integrate Novu with Remix
+
+Within the `app/routes` directory, create an `api.novu.tsx` file.
+
+```jsx
+// app/routes/api.novu.tsx
+
+import { serve } from "@novu/framework/remix";
+import { client, signUpWorkflow } from "~/novu/workflows";
+
+const handler = serve({
+ client: client,
+ workflows: [signUpWorkflow],
+});
+
+export { handler as action, handler as loader };
+```
+
+### 3. Create an email template in your Remix app
+
+Within the `app` directory, create an `emails` folder and add an email template file to it.
+
+In this scenario, create a `vercel-invite-user.tsx` file and the code below to it:
+
+```ts
+// app/emails/vercel-invite-user.tsx
+
+import {
+ Body,
+ Button,
+ Container,
+ Column,
+ Head,
+ Heading,
+ Hr,
+ Html,
+ Img,
+ Link,
+ render,
+ Row,
+ Section,
+ Text,
+ Tailwind,
+} from "@react-email/components";
+
+interface VercelInviteUserEmailProps {
+ username?: string;
+ userImage?: string;
+ invitedByUsername?: string;
+ invitedByEmail?: string;
+ teamName?: string;
+ teamImage?: string;
+ inviteLink?: string;
+ inviteFromIp?: string;
+ showJoinButton?: boolean;
+ inviteFromLocation?: string;
+ buttonText?: string;
+}
+
+const baseUrl = process.env.VERCEL_URL
+ ? `https://${process.env.VERCEL_URL}`
+ : "";
+
+export const VercelInviteUserEmail = ({
+ username,
+ userImage,
+ invitedByUsername,
+ invitedByEmail,
+ teamName,
+ teamImage,
+ inviteLink,
+ inviteFromIp,
+ inviteFromLocation,
+ showJoinButton,
+ buttonText,
+}: VercelInviteUserEmailProps) => {
+ return (
+
+
+
+
+
+
+
+
+
+ Join {teamName} on Vercel
+
+
+ Hello {username},
+
+
+ {invitedByUsername} (
+
+ {invitedByEmail}
+
+ ) has invited you to the {teamName} team on
+ Vercel
+ .
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {showJoinButton && (
+
+
+
+ )}
+
+ or copy and paste this URL into your browser:{" "}
+
+ {inviteLink}
+
+
+
+
+ This invitation was intended for{" "}
+ {username}. This invite was
+ sent from {inviteFromIp}{" "}
+ located in{" "}
+ {inviteFromLocation}. If you
+ were not expecting this invitation, you can ignore this email. If
+ you are concerned about your account's safety, please reply to
+ this email to get in touch with us.
+
+
+
+
+
+ );
+};
+
+VercelInviteUserEmail.PreviewProps = {
+ username: "alanturing",
+ userImage: `${baseUrl}/static/vercel-user.png`,
+ invitedByUsername: "Alan",
+ invitedByEmail: "alan.turing@example.com",
+ teamName: "Enigma",
+ teamImage: `${baseUrl}/static/vercel-team.png`,
+ inviteLink: "https://vercel.com/teams/invite/foo",
+ inviteFromIp: "204.13.186.218",
+ inviteFromLocation: "SĂŁo Paulo, Brazil",
+} as VercelInviteUserEmailProps;
+
+export default VercelInviteUserEmail;
+
+export function renderEmail(input: any, payload: any) {
+ return render();
+}
+```
+
+### 4. Create a Novu Workflow
+
+Next, create a Novu workflow with an email step. This code-first notification workflow approach makes it easy for product teams to modify notification content.
+
+Within the `app` directory, create an `novu` folder and add a `workflows.ts` file to it. Copy/paste the code below to the recently created file.
+
+```jsx
+// app/novu/workflows.ts
+
+import { Client, workflow } from "@novu/framework";
+import { renderEmail } from "~/emails/vercel-invite-user";
+
+export const client = new Client({
+ apiKey: process.env.NOVU_SECRET_KEY,
+ /**
+ * Disable this flag only during local development
+ * For production this should be true
+ */
+ strictAuthentication: process.env.NODE_ENV !== "development",
+});
+
+export const signUpWorkflow = workflow(
+ "new-signup",
+ async ({ step, payload }) => {
+ // Send a welcome email
+ await step.email(
+ "send-email",
+ async (inputs) => {
+ return {
+ subject: `Welcome to sending emails with Novu & Remix`,
+ body: renderEmail(inputs, payload),
+ };
+ },
+ {
+ controlSchema: {
+ type: "object",
+ properties: {
+ showJoinButton: { type: "boolean", default: true },
+ buttonText: { type: "string", default: "Join the team" },
+ userImage: {
+ type: "string",
+ default:
+ "https://react-email-demo-bdj5iju9r-resend.vercel.app/static/vercel-user.png",
+ format: "uri",
+ },
+ invitedByUsername: { type: "string", default: "Alan" },
+ invitedByEmail: {
+ type: "string",
+ default: "alan.turing@example.com",
+ format: "email",
+ },
+ teamName: { type: "string", default: "Team Awesome" },
+ teamImage: {
+ type: "string",
+ default:
+ "https://react-email-demo-bdj5iju9r-resend.vercel.app/static/vercel-team.png",
+ format: "uri",
+ },
+ inviteLink: {
+ type: "string",
+ default: "https://vercel.com/teams/invite/foo",
+ format: "uri",
+ },
+ inviteFromIp: { type: "string", default: "204.13.186.218" },
+ inviteFromLocation: {
+ type: "string",
+ default: "SĂŁo Paulo, Brazil",
+ },
+ },
+ },
+ }
+ );
+ // JSON Schema for validation and type-safety. Zod, and others coming soon.
+ },
+ { payloadSchema: { properties: { text: { type: "string" } } } }
+);
+```
+
+### 5. Preview Email Workflow & Sync to Novu Cloud
+
+Open Novu Dev Studio to preview and make changes to the email workflow as needed via the command below:
+
+```jsx
+npx novu-labs@latest echo
+```
+
+1. Run the Studio
+
+ {" "}
+
+
+**Note:** Use the port on which your Remix app is running for the [Bridge Endpoint](/concepts/endpoint) so that the Novu Dev Studio can connect to your API route as highlighted in the image above.
+
+2. Check out the signup email workflow and test
+
+
+ {" "}
+
+
+3. Deploy to Novu Cloud when you're done.
+
+On the top right(as seen in the image above) of the Novu Dev Studio, you can sync to Novu Cloud when you're done working locally.
+
+**Note:** You'll need to create a local tunnel that the Novu Cloud environment can reach for local experimentation purposes. Ngrok is a good tunnel.
+
+### 6. Send a Notification
+
+Trigger a notification using the recently deployed workflow either via your [Novu Cloud dashboard](https://dashboard-v2.novu.co).
+
+```js
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+novu.trigger("new-signup", {
+ to: {
+ subscriberId: "789",
+ },
+});
+```
+
+Once you've built the workflow, you might want read one of [our other guides](/legacy-guides/framework-guides/product) on how to empower product teams to manage notification workflows.
diff --git a/legacy-guides/framework-guides/framework-svelte.mdx b/legacy-guides/framework-guides/framework-svelte.mdx
new file mode 100644
index 000000000..38f8a826c
--- /dev/null
+++ b/legacy-guides/framework-guides/framework-svelte.mdx
@@ -0,0 +1,319 @@
+---
+title: "How to send notifications with Svelte and Svelte email"
+description: "Learn how to send email notifications with Svelte, Svelte email and Novu"
+---
+
+# Introduction
+
+Learn how to send notifications with Svelte, Svelte email and Novu. You can check out the complete code for a [working app](https://github.com/novuhq/novu-svelte-email).
+
+## Prerequisites
+
+- A Novu account
+- Node installed on your machine
+- A working SvelteKit app
+
+## Follow these Steps
+
+### 1. Install all dependencies
+
+```jsx
+ npm install @novu/framework svelte-email
+```
+
+### 2. Integrate Novu with SvelteKit
+
+Within the `src/routes` directory, create an `api/novu` folder and add a `+server.ts` file to it.
+
+```jsx
+// src/routes/api/novu/+server.ts
+
+import { svelteWorkflow, client } from "$lib/novu/workflows";
+import { serve } from "@novu/framework/sveltekit";
+
+export const { GET, POST, PUT } = serve({
+ client: client,
+ workflows: [svelteWorkflow],
+});
+```
+
+### 3. Create an email template in Svelte
+
+Within the `src/lib` directory, create an `emails` folder and add an email template in a `.svelte` file to it.
+
+For example, `airbnb-review.svelte`:
+
+```ts
+// src/lib/emails/airbnb-review.svelte
+
+
+
+
+
+
+
+
+ {#if showLogoImage}
+
+ {/if}
+
+
+
+ Here's what {authorName} wrote
+ {reviewText}
+
+ Now that the review period is over, weâve posted {authorName}âs review to your Airbnb
+ profile.
+
+
+ While itâs too late to write a review of your own, you can send your feedback to {authorName}
+ using your Airbnb message thread.
+
+
+ {#if showFeedbackButton}
+
+ {/if}
+
+
+ Common questions
+
+ How do reviews work?
+
+
+
+ How do star ratings work?
+
+
+
+
+ Can I leave a review after 14 days?
+
+
+
+ {bottomAddress}
+ Report unsafe behavior
+
+
+
+```
+
+### 4. Create a Novu Workflow
+
+Next, create a Novu workflow with an email step. This code-first notification workflow approach makes it easy for product teams to modify notification content.
+
+```jsx
+// src/lib/novu/workflows.ts
+
+import { Client, workflow } from "@novu/framework";
+import { render } from "svelte-email";
+import AirbnbReview from "$lib/emails/airbnb-review.svelte";
+
+export const client = new Client({
+ /**
+ * The Novu API key is needed for when you
+ * need to sync to Novu Cloud
+ */
+ apiKey: process.env.NOVU_SECRET_KEY,
+ /**
+ * Disable this flag only during local development
+ * For production this should be true
+ */
+ strictAuthentication: process.env.NODE_ENV !== "development",
+});
+
+export const svelteWorkflow = workflow(
+ "airbnb-review",
+ async ({ step, payload }) => {
+ await step.email(
+ "send-email",
+ async (inputs) => {
+ const html = render({
+ template: AirbnbReview,
+ props: {
+ authorName: inputs.authorName,
+ showFeedbackButton: inputs.showFeedbackButton,
+ showLogoImage: inputs.showLogoImage,
+ feedbackButtonText: inputs.feedbackButtonText,
+ bottomAddress: inputs.bottomAddress,
+ authorImage: inputs.authorImage,
+ logoImage: inputs.logoImage,
+ },
+ });
+ return {
+ subject: `Here's Your Host Feedback`,
+ body: html,
+ };
+ },
+ {
+ controlSchema: {
+ type: "object",
+ properties: {
+ showFeedbackButton: { type: "boolean", default: true },
+ showLogoImage: { type: "boolean", default: true },
+ authorName: { type: "string", default: "Alex" },
+ feedbackButtonText: { type: "string", default: "Send My Feedback" },
+ authorImage: {
+ type: "string",
+ default:
+ "https://react-email-demo-bdj5iju9r-resend.vercel.app/static/vercel-user.png",
+ format: "uri",
+ },
+ logoImage: {
+ type: "string",
+ default:
+ "https://svelte-email-rjaapma15-konzeptfabrik.vercel.app/airbnb-logo.png",
+ format: "uri",
+ },
+ bottomAddress: {
+ type: "string",
+ default: "Airbnb, Inc., 888 Brannan St, San Francisco, CA 94103",
+ },
+ },
+ },
+ }
+ );
+ }
+);
+```
+
+### 5. Preview Email Workflow & Sync to Novu Cloud
+
+Open Dev Studio to preview and make changes to the email workflow as needed via the command below:
+
+```jsx
+npx novu-labs@latest echo
+```
+
+1. Run the Studio
+
+ {" "}
+
+
+**Note:** Use the port on which your Svelte app is running for the Bridge endpoint so that the Novu Dev Studio can connect to your API route.
+
+2. Check out the email workflow and test
+
+
+ {" "}
+
+
+3. Deploy to Novu Cloud when you're done.
+
+On the top right of the Novu Dev Studio, you can sync to Novu Cloud when you're done working locally.
+
+**Note:** You'll need to create a local tunnel that the Novu Cloud environment can reach for local experimentation purposes. Ngrok is a good tunnel.
+
+### 6. Send a Notification
+
+Trigger a notification using the recently deployed workflow either via your [Novu Cloud dashboard](https://dashboard-v2.novu.co) or [code](/inbox/react/get-started).
+
+Once you've built the workflow, you might want read one of [our other guides](/legacy-guides/framework-guides/product) on how to empower product teams to manage notification workflows.
diff --git a/legacy-guides/framework-guides/otp.mdx b/legacy-guides/framework-guides/otp.mdx
new file mode 100644
index 000000000..7fd01ee9f
--- /dev/null
+++ b/legacy-guides/framework-guides/otp.mdx
@@ -0,0 +1,330 @@
+---
+title: "How to send OTP verification email notifications with React-email"
+description: "Learn how to send OTP verification email notifications with React-email in your NextJS app"
+---
+
+## Introduction
+
+In this guide, youâll learn how to send OTP verification email notifications using the React-email package. Follow these steps:
+
+## Getting started
+
+Integrating Novuâs code-first workflow with React.Email for your Next.js application can be done in a few steps:
+
+1. Create a NextJS app and wait for the installation:
+
+```bash
+npx novu init@latest --secret-key=
+
+// The command will ask you if you want to include react-email into your new project.
+```
+
+2. Once this installation is complete, simply `cd` into the directory and start your app using the `npm run dev` command.
+
+## Using a code-first workflow
+
+1. Write an email template - To write an email template, you can look over some of the examples in the [React Email](https://react.email/examples) documentation to get inspiration. In our case, this is the template:
+
+```ts
+import {
+ Body,
+ Button,
+ Container,
+ Head,
+ Heading,
+ Hr,
+ Html,
+ Img,
+ Link,
+ Preview,
+ Section,
+ Text,
+ render,
+} from "@react-email/components";
+import * as React from "react";
+
+interface LinearLoginCodeEmailProps {
+ validationCode?: string;
+ showJoinButton?: boolean;
+ buttonText?: string;
+ inviteLink?: string;
+ logoURL?: string;
+ inviteFromLocation?: string;
+ inviteFromIp?: string;
+ supportEmail?: string;
+}
+
+export const LinearLoginCodeEmail = ({
+ validationCode,
+ showJoinButton,
+ buttonText,
+ inviteLink,
+ logoURL,
+ inviteFromIp,
+ inviteFromLocation,
+ supportEmail,
+}: LinearLoginCodeEmailProps) => (
+
+
+ Your login code for Linear
+
+
+
+ Your login code for Linear
+
+ {showJoinButton && (
+
+
+
+ )}
+
+
+ This link and code will only be valid for the next 5 minutes. If the
+ link does not work, you can use the login verification code directly:
+
+
+ {validationCode}110658
+
+
+ Not expecting this email?
+
+ This invite was sent from{" "}
+ {inviteFromIp} located in{" "}
+ {inviteFromLocation}.
+
+
+ Please contact{" "}
+
+ {supportEmail}
+ {" "}
+ if you did not request this code.
+
+
+
+
+);
+
+LinearLoginCodeEmail.PreviewProps = {
+ validationCode: "tt226-5398x",
+} as LinearLoginCodeEmailProps;
+
+export default LinearLoginCodeEmail;
+
+const logo = {
+ borderRadius: 21,
+ width: 42,
+ height: 42,
+};
+
+const main = {
+ backgroundColor: "#ffffff",
+ fontFamily:
+ '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif',
+};
+
+const container = {
+ margin: "0 auto",
+ padding: "20px 0 48px",
+ maxWidth: "560px",
+};
+
+const secondary = {
+ color: "#000",
+ display: "inline-block",
+ fontFamily: "HelveticaNeue-Medium,Helvetica,Arial,sans-serif",
+ fontSize: "20px",
+ fontWeight: 500,
+ lineHeight: "24px",
+ marginBottom: "0",
+ marginTop: "2rem",
+ textAlign: "center" as const,
+};
+
+const paragraphSupportText = {
+ fontSize: "15px",
+ fontWeight: "700",
+};
+
+const paragraph = {
+ margin: "0 0 15px",
+ fontSize: "15px",
+ lineHeight: "1.4",
+ color: "#3c4149",
+};
+
+const buttonContainer = {
+ padding: "27px 0 27px",
+};
+
+const button = {
+ backgroundColor: "#5e6ad2",
+ borderRadius: "3px",
+ fontWeight: "600",
+ color: "#fff",
+ fontSize: "15px",
+ textDecoration: "none",
+ textAlign: "center" as const,
+ display: "block",
+ padding: "11px 23px",
+};
+
+const hr = {
+ borderColor: "#dfe1e4",
+ margin: "42px 0 26px",
+};
+
+const code = {
+ color: "#000",
+ display: "inline-block",
+ fontFamily: "HelveticaNeue-Bold",
+ fontSize: "16px",
+ fontWeight: 700,
+ letterSpacing: "6px",
+ lineHeight: "40px",
+ paddingBottom: "8px",
+ paddingTop: "8px",
+ margin: "0 auto",
+ width: "100%",
+ textAlign: "center" as const,
+};
+
+const paragraphSupport = {
+ color: "#444",
+ fontSize: "15px",
+ fontFamily: "HelveticaNeue,Helvetica,Arial,sans-serif",
+ letterSpacing: "0",
+ lineHeight: "23px",
+ padding: "0 40px",
+ margin: "0",
+ textAlign: "center" as const,
+};
+
+const link = {
+ color: "#444",
+ textDecoration: "underline",
+};
+
+const codeContainer = {
+ background: "rgba(0,0,0,.05)",
+ borderRadius: "4px",
+ margin: "16px auto 14px",
+ verticalAlign: "middle",
+ width: "280px",
+};
+
+export function renderOTPEmail(payload: any) {
+ return render();
+}
+```
+
+2. Launch Dev Studio - Novuâs code-first approach lets you see how the template would look when rendered, right when defining it, using the Dev Studio. To launch the dev studio locally you can run `npx novu-labs@latest echo`. The Dev Studio will be started by default on port 2022, and accessible via: http://localhost:2022
+
+
+ {" "}
+
+
+3. Define a workflow that uses that template to send notifications - In this step, we need to define a workflow that uses the template we wrote above to render the email notification:
+
+```ts
+import { Client, workflow } from "@novu/framework";
+import { renderOTPEmail } from "./otp";
+
+export const client = new Client({
+ apiKey: process.env.NOVU_SECRET_KEY,
+ /**
+ * Disable this flag only during local development
+ */
+ strictAuthentication: process.env.NODE_ENV !== "development",
+});
+
+export const otpFlow = workflow(
+ "otp-flow",
+ async ({ step, payload }) => {
+ // Send a welcome email
+ await step.email(
+ "send-email",
+ async (inputs) => {
+ return {
+ subject: `Here's your verification code, Sumit!`,
+ body: renderOTPEmail(inputs, payload),
+ };
+ },
+ {
+ controlSchema: {
+ type: "object",
+ properties: {
+ showJoinButton: { type: "boolean", default: true },
+ buttonText: { type: "string", default: "Login to Linear" },
+ logoURL: {
+ type: "string",
+ default:
+ "https://react-email-demo-7qy8spwep-resend.vercel.app/static/linear-logo.png",
+ format: "uri",
+ },
+ supportEmail: { type: "string", default: "support@linear.co" },
+ validationCode: { type: "string", default: "tt226-5398x" },
+ inviteLink: {
+ type: "string",
+ default: "https://linear.app",
+ format: "uri",
+ },
+ inviteFromIp: { type: "string", default: "204.13.186.218" },
+ inviteFromLocation: {
+ type: "string",
+ default: "SĂŁo Paulo, Brazil",
+ },
+ },
+ },
+ }
+ );
+ // JSON Schema for validation and type-safety. Zod, and others coming soon.
+ },
+ { payloadSchema: { properties: { text: { type: "string" } } } }
+);
+```
+
+4. Triggering the workflow - Lastly, we need to trigger the workflow we created above. Hereâs how to trigger it:
+
+```ts
+import { Novu } from "@novu/node";
+
+const novu = new Novu("");
+
+export async function POST(request: Request) {
+ const res = await request.json();
+
+ await novu.trigger("otp-flow", {
+ to: {
+ subscriberId: "new-user",
+ },
+ payload: {
+ email: res.email,
+ username: res.username,
+ },
+ });
+
+ console.log("triggered");
+ return Response.json({ success: true });
+}
+```
+
+When we trigger this workflow, hereâs the email received on the client-side:
+
+
+ {" "}
+
+Thatâs it!
+
+Thatâs how you create and use an OTP workflow. You can check out [our docs](https://docs.novu.co/guides/framework-guides/framework-react-email) for a hands on guide with more in-depth instructions.
+
+Once you've built the workflow, you might want read one of [our other guides](/legacy-guides/framework-guides/product) on how to empower product teams to manage notification workflows.
+
+Donât forget to share your workflows with us and as always, hit us up on Discord with any questions you might have!
diff --git a/legacy-guides/framework-guides/product.mdx b/legacy-guides/framework-guides/product.mdx
new file mode 100644
index 000000000..295738fdd
--- /dev/null
+++ b/legacy-guides/framework-guides/product.mdx
@@ -0,0 +1,55 @@
+---
+title: "Empowering Product Teams to Manage Notification Workflows"
+description: "Enabling product teams to independently manage and optimize notification workflows for improved efficiency and user experience"
+---
+
+# Introduction
+
+Novuâs code-first workflow empowers product teams to manage notification for end-users independently once the engineering teams have built and delivered the notification platform for the product.
+
+Letâs see how product teams can leverage it:
+
+1. **Engineering Team sets things up:** Engineering teams integrate Novuâs code-first workflows into their application. This involves setting up the structure of notification workflows in the codebase, defining events, steps, inputs, payload, etc. These workflows are functions that execute business logic and need to be set only once.
+2. **Empowering Non-Technical Teams:** Once the foundational workflows are established, product teams can take over! Code-first workflows allow non-technical users to modify workflows safely without breaking critical integrations. Through an exposed Inputs interface, product teams can adjust notification content and behaviour, tailoring the user experience without needing to dive into the code at all. This helps both teams win - product teams are empowered to manage and optimize notifications independently, creating a dynamic and user-centric notification system without constant reliance on engineering teams.
+3. **Insights and Optimization**: Further, with Novuâs Web Dashboard, Product teams gain valuable insights into last-mile delivery from the activity monitor. This enables them to refine notification strategies and optimize for better user satisfaction.
+
+This collaborative approach between the Engineering and Product teams allows both teams to focus on their strengths, resulting in a more efficient and effective notification strategy, without constant interruptions in each otherâs flow.
+
+## Customising the workflow
+
+To demonstrate the customizability, weâll assume that the Engineering team has successfully delivered the basic setup as outlined in [one of our guides.](https://docs.novu.co/guides/framework-guides/framework-react-email)
+
+1. To start things off, you only need to visit the workflow section in our [Web Dashboard](https://dashboard-v2.novu.co/).
+
+ {" "}
+
+
+- Youâll see the blue lightning bolt icon right next to the workflow name symbolising that it is a code-first workflow.
+- Now, simply click on the workflow to open it and make your desired changes.
+- The green `Sync` indicator on the top right corner means that your app is successfully connected with Novu.
+
+2. Once you open a workflow, youâll see all the steps of the workflow:
+
+ {" "}
+
+3. Simply, select a node to see the rendered view. This is what will get sent to the end user.
+
+ {" "}
+
+4. To start making changes, simply click on either of the two buttons highlighted below:
+
+ {" "}
+
+5. Once you click on it, youâll be taken to the edit view where youâll see real-time preview of the workflow. You can make changes to the step inputs on the right-hand side and the rendered view will update in real-time to reflect those changes
+
+ {" "}
+
+6. Let's take a look at what payload and step inputs are:
+7. In almost all the scenarios, youâll be tweaking and modifying step inputs and the workflow editor makes it blazing fast and effortlessly simple. Simply change the text of the respective field or button or toggle any button on or off till the rendered view becomes what you want your end users to receive. Hereâs how you can tweak it:
+
+ {" "}
+
+
+## Conclusion
+
+The collaboration resulting from Novuâs code-first workflow increases agility, enabling rapid iterations and quick adjustments based on user feedback. It fosters effective collaboration between product and engineering teams, resulting in a more efficient workflow and improved user notifications.
diff --git a/legacy-guides/headless-notification-center-guide.mdx b/legacy-guides/headless-notification-center-guide.mdx
new file mode 100644
index 000000000..b90ede2e6
--- /dev/null
+++ b/legacy-guides/headless-notification-center-guide.mdx
@@ -0,0 +1,463 @@
+---
+title: "How to use Headless Notification Center"
+description: "Use the headless version of the notification center"
+---
+
+## Introduction
+
+In this guide, you'll learn about how to use the headless version of our notification center. The headless version is useful for scenarios in which a lightweight solution for integrating notification functionality into a web app that is completely unstyled (so that you can style it as per your wish) is required.
+
+
+You can find the entire code ( front-end as well as back-end ) of this app [here.](https://github.com/novuhq/novu-headless-demo-app)
+
+## What is the headless notification center
+
+The headless version of Novu's notification library package provides users with a lightweight solution for integrating notification functionality into their web applications.
+
+
+With just the essential API methods, users can easily incorporate our notification
+system into any framework or vanilla JavaScript project, without being constrained
+by our default UI or dependencies.
+
+This gives the users of the headless notification center greater flexibility and control over what the end-users of a product see and experience.
+
+## How to use the headless notification center
+
+To get started with this you need:
+
+1. A Novu account. [Sign up for free](http://dashboard.novu.co/?utm_campaign=docs-gs-guides-headless) if you donât have one yet.
+2. A working dev environment in the framework of your choice (or vanilla JS). Here, we'll use a React environment
+
+## Workflow set up in Novu
+
+Once, you have signed up for Novu and have a dev environment, follow the steps below:
+
+1. Head over to the Novu Dashboard.
+2. Click **"Workflows"** on the left sidebar of your Novu dashboard.
+3. Click the **"Create Workflow"** button on the top right:
+
+ {" "}
+
+ Once you click the **"Create Workflow"** button, youâll see a dropdown. Select `blank
+ workflow` from the dropdown:
+
+ {" "}
+
+ Youâll now be taken to the workflow editor:
+
+ {" "}
+
+ Once here, you can add the channels you want to use for sending notifications
+ and configure them. For this guide, weâll use the `In-App` channel.
+
+ {" "}
+
+ The in-app node allows you to further customize the notifications that will
+ get sent, as per your need. In our case, it is a simple `description`, which will
+ contain the text that will be entered from the front end. Here's the `in-app`
+ node for your reference:
+
+
+ {" "}
+
+
+Here's a brief overview of all the options:
+
+- **1-Preview**: This shows you a glimpse of what each notification item will look like in the Notification Center UI.
+- **2-Avatar:**: If turned on, each notification item will show the avatar of the subscriber.
+- **3-Action:**: With this, you can add a primary and secondary call to action button to each notification item.
+- **4-Notification Feeds:**: This displays a stream of specific notifications. You can have multiple feeds to show specific notifications in multiple tabs.
+- **5-Redirect URL**: This is the URL to which a subscriber can be directed when they click on a notification item.
+- **6-Filter**: This feature allows you to configure the criteria for delivering notifications. For instance, you can apply a filter based on a subscriber's online status to send them an email if they were online within the last hour.
+
+Once youâre done configuring this to your liking, click on the `update` button on the top right. It'll automatically create a trigger code that you can use in your app. To get it, click on the `get snippet` button on the top right and copy it:
+
+
+ {" "}
+
+
+Let's now see how to add it to our app!
+
+## Pre-requisites:
+
+To be able to use the headless notification center, you'll first need the following:
+
+1. `applicationIdentifier`: You can find this from the `settings` menu in the [Novu web dashboard.](https://dashboard-v2.novu.co/settings?utm_campaign=docs-guides-headless)
+2. `subscriberID`: In most real-world apps, you'll get this from a database. It is used to uniquely identify the entity to whom a notification will be delivered. In our case, we're assuming the `subscriberID` to be `12345`.
+
+## Setting up the back end:
+
+For our demo app, we're setting up the back end as follows:
+
+1. Install the Novu package. Open your terminal and run the following command:
+
+```bash
+npm install @novu/node
+```
+
+Once installed, you can import Novu into your app and initialize it using your Novu account credentials. This step establishes a connection between your app and the Novu notification service.
+
+```bash
+import { Novu } from '@novu/node';
+const novu = new Novu('');
+```
+
+
+Replace the `` value with the authentic key from the API Key section of your [Novu Dashboard.](http://dashboard.novu.co/?utm_campaign=docs-guides-headless)
+
+
+đ Please do not hardcode your credentials in a file in production. Use environment variables instead.
+
+
+Using the above info, we'll write a function that will help us interact with Novu's notification system:
+
+```javascript
+import { Novu } from "@novu/node";
+
+export const notification = async (description) => {
+ const novu = new Novu("");
+ await novu.subscribers.identify(process.env.SUSBSCRIBER_ID, {
+ firstName: "newSubForHeadless",
+ });
+
+ // code snippet copied when creating the workflow
+ await novu.trigger("headless-demo", {
+ to: {
+ subscriberId: process.env.SUSBSCRIBER_ID,
+ },
+ payload: {
+ description: description,
+ },
+ });
+};
+```
+
+After this, we'll set up a simple controller function for handling notifications:
+
+```javascript
+import { notification } from "../novu/novu.js";
+
+export const notifController = async (req, res) => {
+ const { description } = req.body;
+ try {
+ await notification(description);
+ res.status(201).json({ message: "Subscriber created successfully" });
+ } catch (error) {
+ console.log("notifController error:", error);
+ res.status(500).json({ message: error.message });
+ }
+};
+```
+
+And finally, we'll need to establish routes that we'll hit from the front end:
+
+```javascript
+import express from "express";
+import { notifController } from "../controller/notif.js";
+
+const router = express.Router();
+
+router.post("/create-sub", notifController);
+
+export default router;
+```
+
+Now, we'll move to the front end because that's where all the magic happens!
+
+## Setting up the front end:
+
+In the front end, install the headless package:
+
+```bash
+npm install @novu/headless
+```
+
+Then, import it and initialize the headless service:
+
+```javascript
+import { HeadlessService, FetchResult, ISession } from "@novu/headless";
+
+useEffect(() => {
+ const headlessService = new HeadlessService({
+ applicationIdentifier: "SWMw97ec1ZNA",
+ subscriberId: "12345",
+ });
+
+ headlessService.initializeSession({
+ listener: (res) => {},
+ onSuccess: (session) => {
+ headlessServiceRef.current = headlessService;
+ fetchNotifications();
+ },
+ onError: (error) => {
+ console.log("headlessSice error:", error);
+ },
+ });
+}, [fetchNotifications]);
+```
+
+We've added the `fetchNotifications` function inside a useEffect because we want the effect to run whenever the `fetchNotifications` executes. Here's the `fetchNotifications` function for reference:
+
+```javascript
+const fetchNotifications = useCallback(() => {
+ const headlessService = headlessServiceRef.current;
+ if (headlessService) {
+ headlessService.fetchNotifications({
+ listener: ({ data, error, isError, isFetching, isLoading, status }) => {
+ // Handle the state of the fetching process and errors here.
+ },
+ onSuccess: (response) => {
+ // Handle the fetched notifications here.
+ setNotifications(response.data); // Store notifications in the state
+ },
+ page: pageNum, // page number to be fetched
+ });
+ }
+}, [pageNum]);
+```
+
+Here, we've memoized the `fetchNotifications` to optimize performance and passed `pageNum` in a dependency array so that it reruns when the page number changes.
+
+
+You can refer to the entire context [here](https://github.com/novuhq/novu-headless-demo-app/blob/main/frontend/src/context/NotificationContext.js)
+for a better understanding.
+
+We've also used several methods related to the Headless Notification Center package. You can find the complete list [here.](/inbox/headless/get-started)
+
+The methods that we've used in our app are `markNotificationsAsRead`, `deleteNotification`, and `markAllMessagesAsRead`. They are as follows:
+
+```javascript
+const markNotificationsAsRead = (messageIds) => {
+ if (!Array.isArray(messageIds)) {
+ messageIds = [messageIds];
+ }
+
+ const headlessService = headlessServiceRef.current;
+
+ if (headlessService) {
+ headlessService.markNotificationsAsRead({
+ messageId: messageIds,
+ listener: (result) => {},
+ onError: (error) => {
+ console.error("Error marking notifications as read:", error);
+ },
+ });
+ }
+};
+
+const deleteNotification = (messageId) => {
+ const headlessService = headlessServiceRef.current;
+ if (headlessService) {
+ headlessService.removeNotification({
+ messageId: messageId,
+ listener: function (result) {},
+ onSuccess: function (message) {},
+ onError: function (error) {
+ console.error(error);
+ },
+ messageIds: "messageOne",
+ });
+ }
+};
+
+const markAllMessagesAsRead = (feedId) => {
+ const headlessService = headlessServiceRef.current;
+
+ headlessService.markAllMessagesAsRead({
+ listener: (result) => {
+ console.log(result);
+ // Handle the result of marking all messages as read
+ // You can update the state or perform other actions here
+ },
+ onError: (error) => {
+ console.error("Error marking all messages as read:", error);
+ // Implement error handling if needed
+ },
+ feedId: feedId, // Pass the feed ID here, it can be an array or a single ID
+ });
+};
+```
+
+
+ You can view the entire API reference
+ [here](/inbox/headless/get-started) and pick up the
+ methods that you'd like to use for your specific requirements.
+
+
+### Coding the UI up:
+
+On the UI front, we have a simple form with a submit handler function and a couple of components:
+
+```javascript
+const Body = () => {
+ const [description, setDescription] = useState("");
+ const { active, setActive } = useNotification();
+ const onSubmitHandler = async (e) => {
+ e.preventDefault();
+ await axios.post(
+ "https://headless-backend-qx89.onrender.com/api/v1/create-sub",
+ { description }
+ );
+
+ setDescription("");
+ setActive(true);
+ };
+ const onChangeHandler = (e) => {
+ setDescription(e.target.value);
+ };
+ return (
+
+
Enter notification text
+
+
+ );
+};
+```
+
+The first component is the `appBar` component which includes a bell icon, which can show notifications in a modal when clicked. The modal is displayed when showModal is true, and the modal can be closed by clicking outside of it. The component interacts with the notification-related functionalities provided by the useNotification hook:
+
+```javascript
+const AppBar = () => {
+ const [showModal, setShowModal] = useState(false);
+ const modalRef = useRef(null);
+
+ const { fetchNotifications, setActive, active } = useNotification();
+
+ const handleShowNotification = async (e) => {
+ e.stopPropagation();
+ setShowModal((prev) => !prev);
+ await fetchNotifications();
+ setActive(false);
+ };
+ const handleCloseModal = () => {
+ setShowModal(false);
+ };
+ useEffect(() => {
+ const handleDocumentClick = (e) => {
+ if (modalRef.current && !modalRef.current.contains(e.target)) {
+ handleCloseModal();
+ }
+ };
+ if (showModal) {
+ document.addEventListener("click", handleDocumentClick);
+ }
+ return () => {
+ document.removeEventListener("click", handleDocumentClick);
+ };
+ }, [showModal]);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ {showModal && }
+
+
+ );
+};
+
+export default AppBar;
+```
+
+And the second component is the `NotificationModal` which is what gets displayed when the user clicks on the bell icon.
+
+
+The beauty of using the headless version of the notification center is that you can customise exactly how it looks and which functionalities you need in it.
+
+Our `NotificationModal` component is as follows:
+```javascript
+const NotificationModal = () => {
+
+ const { notifications, markNotificationsAsRead, markAllMessagesAsRead, deleteNotification, setPageNum, pageNum, fetchNotifications } = useNotification();
+
+ const handleNotificationRead = (notificationId) => {
+ markNotificationsAsRead(notificationId);
+ }
+
+ const handleNotificationDelete = (notificationId) => {
+ let newClass = document.getElementById(`${notificationId}`);
+ newClass.style.display = 'none';
+ deleteNotification(notificationId);
+ }
+
+ const handleMarkAllAsRead = () => {
+ markAllMessagesAsRead();
+ }
+ const onPrvHandler = () => {
+ setPageNum((prv) => prv - 1)
+
+ }
+ const onNxtHandler = () => {
+ setPageNum((prv) => prv + 1)
+
+ }
+
+
+ useEffect(() => {
+ fetchNotifications();
+ }, [pageNum, fetchNotifications])
+ return (
+
+
+ )
+}
\ No newline at end of file
diff --git a/snippets/contact-support.mdx b/snippets/contact-support.mdx
new file mode 100644
index 000000000..9582bae0a
--- /dev/null
+++ b/snippets/contact-support.mdx
@@ -0,0 +1,4 @@
+
+ If your question is not answered here, feel free to reach out us at
+ support@novu.co
+
diff --git a/snippets/framework-terminal.mdx b/snippets/framework-terminal.mdx
new file mode 100644
index 000000000..222d29e36
--- /dev/null
+++ b/snippets/framework-terminal.mdx
@@ -0,0 +1,13 @@
+export const FrameworkTerminal = () => {
+ if (typeof document === "undefined") {
+ return null;
+ } else {
+ const clientComponent = document.getElementById("nv-framework-terminal-snippet");
+ if (clientComponent) {
+ clientComponent.innerHTML = '';
+ }
+
+ return
+
+}
+}
diff --git a/snippets/hooks/use-counts-content.mdx b/snippets/hooks/use-counts-content.mdx
new file mode 100644
index 000000000..4284257da
--- /dev/null
+++ b/snippets/hooks/use-counts-content.mdx
@@ -0,0 +1,44 @@
+The `useCounts` hook is used to fetch the notification counts based on the provided filters.
+You can use this hook to fetch the total count of unread, archived notifications or any other custom count based on the filters you provide.
+
+The hook listens for changes in notification counts and will automatically refetch the counts whenever they are updated, for example, when a new notification is received.
+
+### `useCounts` props
+
+
+ Filters to be applied to notifications when calculating counts, allowing you
+ to filter notifications based on workflow tags, read status, and archived
+ status.
+
+
+ Callback function that will be called when the notification counts are
+ successfully fetched. In the callback argument, you will receive the fetched
+ counts.
+
+
+ Callback function that will be called when there is an error fetching the
+ notification counts. In the callback argument, you will receive the error
+ object.
+
+
+### `useCounts` returns
+
+
+ An array of notification counts fetched by the hook. If there are no
+ notification counts fetched yet, it will be `undefined`.
+
+
+ A boolean value indicating the first fetch for notification counts is
+ in-flight.
+
+
+ A boolean value indicating whether the hook is fetching more notification
+ counts.
+
+
+ An error object that will be populated if there is an error fetching the
+ notification counts.
+
+
+ A function that can be called to refetch the notification counts.
+
\ No newline at end of file
diff --git a/snippets/hooks/use-notifications-content.mdx b/snippets/hooks/use-notifications-content.mdx
new file mode 100644
index 000000000..d7ea4cdf2
--- /dev/null
+++ b/snippets/hooks/use-notifications-content.mdx
@@ -0,0 +1,77 @@
+The `useNotifications` hook is a convenient way to fetch the list of notifications.
+By default, it fetches both unread and read notifications, but you can apply [filters](/inbox/react/hooks/use-notifications#usenotifications-props) to retrieve only the relevant notifications for your specific use case.
+
+The notifications fetched are paginated, and the hook provides a `fetchMore` function to load more notifications.
+The fetched notifications are stored in the notifications array and are appended to the existing notifications as more are loaded.
+
+Any action performed on a notification instance, like marking it as read, will optimistically update the notification, triggering a re-render in the hook and updating the notifications list accordingly, so you don't need to refetch and manually update your UI.
+
+### `useNotifications` props
+
+
+ Workflow tags can be used to filter notifications, and organize them into
+ different groups. Read more about how can you define [workflow
+ tags](/workflow/overview#tags).
+
+
+ Filter notifications based on their read status. If not provided, all
+ read/unread notifications will be returned.
+
+
+ Filter notifications based on their archived status. Archived notifications
+ are also read at the same time. If not provided, all archived/unarchived
+ notifications will be returned.
+
+
+ Limit the number of notifications to be fetched. It can take any number
+ between 1 and 100. Default is 10.
+
+
+ Callback function that will be called when the notifications are successfully
+ fetched. In the callback argument, you will receive the fetched notifications.
+
+
+ Callback function that will be called when there is an error fetching the
+ notifications. In the callback argument, you will receive the error object.
+
+
+### `useNotifications` returns
+
+
+ An array of notifications fetched by the hook. If there are no notifications
+ fetched yet, it will be `undefined`.
+
+
+ A boolean value indicating the first fetch for notifications is in-flight.
+
+
+ A boolean value indicating whether the hook is fetching more notifications.
+
+
+ An error object that will be populated if there is an error fetching the
+ notifications.
+
+
+ A boolean value indicating whether there are more notifications available to
+ fetch.
+
+
+ A function that can be called to fetch more notifications. It will fetch the
+ next page of notifications and append them to the existing notifications.
+
+
+ A function that can be called to refetch the notifications. It will clear the
+ existing notifications and fetch the first page of notifications.
+
+
+ A function that can be called to mark all notifications as read, including
+ those that have not been fetched.
+
+
+ A function that can be called to archive all notifications, including those
+ that have not been fetched.
+
+
+ A function that can be called to archive all read notifications, including
+ those that have not been fetched.
+
\ No newline at end of file
diff --git a/snippets/hooks/use-novu-content.mdx b/snippets/hooks/use-novu-content.mdx
new file mode 100644
index 000000000..f2e870fd6
--- /dev/null
+++ b/snippets/hooks/use-novu-content.mdx
@@ -0,0 +1,8 @@
+
+The `useNovu` hook is used to obtain the [Novu instance](/inbox/headless/api-reference#novu), which allows you to interact with the headless SDK interface.
+
+The hook returns the [Novu](/inbox/headless/api-reference#novu) class instance with multiple methods to interact with the Novu API.
+
+## Example usage
+
+The below example demonstrates how to use the `useNovu` hook to listen for new notifications and show a toast notification.
\ No newline at end of file
diff --git a/snippets/hooks/use-preferences-content.mdx b/snippets/hooks/use-preferences-content.mdx
new file mode 100644
index 000000000..7d373f95e
--- /dev/null
+++ b/snippets/hooks/use-preferences-content.mdx
@@ -0,0 +1,42 @@
+
+The `usePreferences` hook is used to retrieve the subscriber preferences. The first item in the list will represent the subscriber global preferences,
+while the remaining items will correspond to the preferences for each workflow.
+
+The hook returns both critical and non-critical preferences. Critical preferences are those that are required for the subscriber to receive notifications,
+while non-critical preferences are those that are optional and could be controlled by the subscriber. You can learn more about the preferences [here](/concepts/preferences).
+
+By default the preferences are cached, but you can use the `refetch` function to fetch the latest preferences.
+
+### `usePreferences` props
+
+
+ Callback function that will be called when the subscriber preferences are
+ successfully fetched. In the callback argument, you will receive the fetched
+ preferences.
+
+
+ Callback function that will be called when there is an error fetching the
+ subscriber preferences. In the callback argument, you will receive the error
+ object.
+
+
+### `usePreferences` returns
+
+
+ An array of subscriber preferences fetched by the hook. If there are no
+ preferences fetched yet, it will be `undefined`.
+
+
+ A boolean value indicating the first fetch for preferences is in-flight.
+
+
+ A boolean value indicating whether the hook is fetching more preferences.
+
+
+ An error object that will be populated if there is an error fetching the
+ preferences.
+
+
+ A function that can be called to refetch the preferences.
+
+
diff --git a/snippets/icons/expressjs.mdx b/snippets/icons/expressjs.mdx
new file mode 100644
index 000000000..e08cae2f2
--- /dev/null
+++ b/snippets/icons/expressjs.mdx
@@ -0,0 +1 @@
+export const ExpressjsIcon = () => ()
diff --git a/snippets/icons/h3.mdx b/snippets/icons/h3.mdx
new file mode 100644
index 000000000..bc640771a
--- /dev/null
+++ b/snippets/icons/h3.mdx
@@ -0,0 +1 @@
+export const H3Icon = () => ()
diff --git a/snippets/icons/lambda.mdx b/snippets/icons/lambda.mdx
new file mode 100644
index 000000000..6257767f2
--- /dev/null
+++ b/snippets/icons/lambda.mdx
@@ -0,0 +1 @@
+export const LambdaIcon = () => ()
diff --git a/snippets/icons/nestjs.mdx b/snippets/icons/nestjs.mdx
new file mode 100644
index 000000000..66cf51bc8
--- /dev/null
+++ b/snippets/icons/nestjs.mdx
@@ -0,0 +1 @@
+export const NestjsIcon = () => ()
diff --git a/snippets/icons/nextjs.mdx b/snippets/icons/nextjs.mdx
new file mode 100644
index 000000000..60c19fa8f
--- /dev/null
+++ b/snippets/icons/nextjs.mdx
@@ -0,0 +1 @@
+export const NextjsIcon = () => ()
diff --git a/snippets/icons/nuxt.mdx b/snippets/icons/nuxt.mdx
new file mode 100644
index 000000000..8ef152b55
--- /dev/null
+++ b/snippets/icons/nuxt.mdx
@@ -0,0 +1 @@
+export const NuxtIcon = () => ()
diff --git a/snippets/icons/remix.mdx b/snippets/icons/remix.mdx
new file mode 100644
index 000000000..25151b12d
--- /dev/null
+++ b/snippets/icons/remix.mdx
@@ -0,0 +1 @@
+export const RemixIcon = () => ()
diff --git a/snippets/icons/svelte.mdx b/snippets/icons/svelte.mdx
new file mode 100644
index 000000000..e69d28d97
--- /dev/null
+++ b/snippets/icons/svelte.mdx
@@ -0,0 +1 @@
+export const SvelteIcon = () => ()
diff --git a/snippets/inbox/headless/api-reference/function-params.mdx b/snippets/inbox/headless/api-reference/function-params.mdx
new file mode 100644
index 000000000..abe19863c
--- /dev/null
+++ b/snippets/inbox/headless/api-reference/function-params.mdx
@@ -0,0 +1,9 @@
+#### Params
+
+
+ Notification ID is a unique identifier for the notification. It can be taken
+ from the [notification object](/inbox/headless/api-reference#notification-interface).
+
+
+ Notification object represents the message sent to the subscriber.
+
diff --git a/snippets/inbox/headless/api-reference/novu-params.mdx b/snippets/inbox/headless/api-reference/novu-params.mdx
new file mode 100644
index 000000000..fb1708710
--- /dev/null
+++ b/snippets/inbox/headless/api-reference/novu-params.mdx
@@ -0,0 +1,30 @@
+
+ `applicationIdentifier` is a unique identifier for the application. This is is
+ public credential that is used to authenticate the application with the Novu
+ API. `applicationIdentifier` can be copied from [API
+ Keys](https://dashboard-v2.novu.co/api-keys) page.
+
+
+
+ `subscriberId` is a unique identifier for the subscriber. Read more about
+ [subscribers](/concepts/subscribers).
+
+
+
+ `subscriberHash` is a unique identifier for the subscriber. It is used for
+ HMAC encryption. Read more about [HMAC
+ Encryption](/inbox/react/production#hmac-encryption).
+
+
+
+ Use `https://eu.api.novu.co` value for EU region.
+
+
+
+ Use `https://eu.ws.novu.co` value for EU region.
+
+
+
+ The field is used to enable/disable the cache for the notifications and
+ preferences. By default, the cache is enabled.
+
diff --git a/snippets/inbox/react/novu-provider-example.mdx b/snippets/inbox/react/novu-provider-example.mdx
new file mode 100644
index 000000000..75658e74d
--- /dev/null
+++ b/snippets/inbox/react/novu-provider-example.mdx
@@ -0,0 +1,15 @@
+```tsx
+import { NovuProvider } from '@novu/react/hooks';
+
+function App() {
+ return (
+
+ {/* Your app components where you want to use the hooks */}
+
+
+ );
+}
+```
diff --git a/snippets/inbox/react/use-notifications-example.mdx b/snippets/inbox/react/use-notifications-example.mdx
new file mode 100644
index 000000000..332943caa
--- /dev/null
+++ b/snippets/inbox/react/use-notifications-example.mdx
@@ -0,0 +1,32 @@
+```tsx
+import { useNotifications } from '@novu/react/hooks';
+
+const NotificationsList = () => {
+ const { notifications, isLoading, fetchMore, hasMore } = useNotifications();
+
+ return (
+ }>
+ 0}
+ fallback={}
+ >
+ }
+ >
+ {notifications?.map((notification) => {
+ return (
+
+ );
+ })}
+
+
+
+ );
+};
+```
diff --git a/snippets/inbox/react/use-unread-count-example.mdx b/snippets/inbox/react/use-unread-count-example.mdx
new file mode 100644
index 000000000..2770b370c
--- /dev/null
+++ b/snippets/inbox/react/use-unread-count-example.mdx
@@ -0,0 +1,14 @@
+```tsx
+import { useCounts } from '@novu/react/hooks';
+
+const BellButton = () => {
+ const { counts } = useCounts({ filters: [{ read: false }] });
+
+ return (
+
+ );
+};
+```
diff --git a/snippets/missing-provider.mdx b/snippets/missing-provider.mdx
new file mode 100644
index 000000000..2495236e1
--- /dev/null
+++ b/snippets/missing-provider.mdx
@@ -0,0 +1,14 @@
+export const MissingProvider = ({ channelName }) => (
+
+ Are we missing a provider you'd like to use for{" "}
+ {channelName ? channelName : "this"} channel? Please consider adding a new
+ feature request on{" "}
+
+ github
+ {" "}
+ or help us upvoting the existing ones on our public{" "}
+ roadmap
+
+);
+
+;
diff --git a/snippets/provider-implementation.mdx b/snippets/provider-implementation.mdx
new file mode 100644
index 000000000..9c744b1e3
--- /dev/null
+++ b/snippets/provider-implementation.mdx
@@ -0,0 +1,5 @@
+
+ If you are looking to use {provider} provider in different way or your usecase
+ is not covered by this documentation, you can always reach out to our team at
+ support@novu.co or via [Discord](https://discord.novu.co)
+
diff --git a/snippets/quickstart/deploy.mdx b/snippets/quickstart/deploy.mdx
new file mode 100644
index 000000000..c2e87de54
--- /dev/null
+++ b/snippets/quickstart/deploy.mdx
@@ -0,0 +1,6 @@
+
+ Once you have finished refining your first workflow, itâs time to sync your local changes to Novu Cloud. Novu recommends deploying your workflows similarly to how you will deploy the features that generate those notifications using your CI/CD pipeline or our CLI command.
+
+ Read more about [syncing your changes to the cloud](/framework/deployment/production).
+
+
diff --git a/snippets/quickstart/next-steps.mdx b/snippets/quickstart/next-steps.mdx
new file mode 100644
index 000000000..245741f89
--- /dev/null
+++ b/snippets/quickstart/next-steps.mdx
@@ -0,0 +1,19 @@
+## Next Steps
+
+
+
+ Learn how to build workflows with the Novu Framework.
+
+
+ Learn more about the Novu Framework SDK
+
+
+ Add the Inbox component to your application with our front-end SDK.
+
+
+ Deploy your workflows to Development and Production
+
+
diff --git a/snippets/quickstart/packages.mdx b/snippets/quickstart/packages.mdx
new file mode 100644
index 000000000..b733adcf1
--- /dev/null
+++ b/snippets/quickstart/packages.mdx
@@ -0,0 +1,12 @@
+
+
+```bash
+npm install @novu/framework zod zod-to-json-schema
+```
+
+This will install the following packages
+
+- **`@novu/framework`** SDK Package
+- **Zod** (Recommended) - For end-to-end type safety for your Payload and Step Controls
+
+
diff --git a/snippets/quickstart/remix-workflow.mdx b/snippets/quickstart/remix-workflow.mdx
new file mode 100644
index 000000000..4db97337c
--- /dev/null
+++ b/snippets/quickstart/remix-workflow.mdx
@@ -0,0 +1,22 @@
+```tsx app/novu/workflows.ts
+import { workflow } from '@novu/framework';
+import { z } from 'zod';
+
+export const testWorkflow = workflow('test-workflow', async ({ step, payload }) => {
+ await step.email('send-email', async (controls) => {
+ return {
+ subject: controls.subject,
+ body: 'This is your first Novu Email ' + payload.userName,
+ };
+ },
+ {
+ controlSchema: z.object({
+ subject: z.string().default('A Successful Test on Novu from {{userName}}'),
+ }),
+ });
+ }, {
+ payloadSchema: z.object({
+ userName: z.string().default('John Doe'),
+ }),
+});
+```
diff --git a/snippets/quickstart/secret.mdx b/snippets/quickstart/secret.mdx
new file mode 100644
index 000000000..86cc1dabf
--- /dev/null
+++ b/snippets/quickstart/secret.mdx
@@ -0,0 +1,8 @@
+
+ Add `NOVU_SECRET_KEY` environment variable to your `.env`
+
+ ```env
+ NOVU_SECRET_KEY=
+ ```
+
+
diff --git a/snippets/quickstart/start-studio.mdx b/snippets/quickstart/start-studio.mdx
new file mode 100644
index 000000000..c250bd6b9
--- /dev/null
+++ b/snippets/quickstart/start-studio.mdx
@@ -0,0 +1,22 @@
+
+ The [Local Studio](/framework/studio) is where you will build your notification workflows and craft the controls that will be
+ exposed for your non-technical peers to maintain after your workflow is pushed to your Development or Production
+ environments.
+
+
+
+ ```bash
+ npx novu@latest dev
+ ```
+
+
+ ```bash
+ npx novu@latest dev -d https://eu.dashboard.novu.co
+ ```
+
+
+
+ The `dev` command is your go-to command whenever you want to build and preview your changes before syncing to cloud. By default, it will start a secure tunnel that our durable cloud workflow engine will
+ be able to communicate with, and the [Local Studio](/framework/studio) web service listening on `http://localhost:2022`
+
+
diff --git a/snippets/quickstart/test.mdx b/snippets/quickstart/test.mdx
new file mode 100644
index 000000000..c5f3d0833
--- /dev/null
+++ b/snippets/quickstart/test.mdx
@@ -0,0 +1,6 @@
+
+ After your {framework} application is up and running, visit the [Local Studio](/framework/studio) interface that was started on `http://localhost:2022` by running the `npx novu dev` command on the first step.
+
+ The onboarding guide will guide you to send the newly created sample workflow to your e-mail address.
+
+
diff --git a/snippets/quickstart/workflow.mdx b/snippets/quickstart/workflow.mdx
new file mode 100644
index 000000000..03c3d1088
--- /dev/null
+++ b/snippets/quickstart/workflow.mdx
@@ -0,0 +1,22 @@
+```tsx
+import { workflow } from '@novu/framework';
+import { z } from 'zod';
+
+export const testWorkflow = workflow('test-workflow', async ({ step, payload }) => {
+ await step.email('send-email', async (controls) => {
+ return {
+ subject: controls.subject,
+ body: 'This is your first Novu Email ' + payload.userName,
+ };
+ },
+ {
+ controlSchema: z.object({
+ subject: z.string().default('A Successful Test on Novu from {{userName}}'),
+ }),
+ });
+}, {
+ payloadSchema: z.object({
+ userName: z.string().default('John Doe'),
+ }),
+});
+```
diff --git a/snippets/self-host-only-api.mdx b/snippets/self-host-only-api.mdx
new file mode 100644
index 000000000..a43547435
--- /dev/null
+++ b/snippets/self-host-only-api.mdx
@@ -0,0 +1,3 @@
+
+This API is available only in V1 self-hosted docker images. Novu Cloud uses [Clerk](https://clerk.com) to manage users and organizations. For more information contact support@novu.co.
+
diff --git a/snippets/supported-channels.mdx b/snippets/supported-channels.mdx
new file mode 100644
index 000000000..5bc27c7f9
--- /dev/null
+++ b/snippets/supported-channels.mdx
@@ -0,0 +1,8 @@
+| Channel
| Content Style
| Custom Variables `{{handlebars}}` format |
+| ----------------- | ----------------------- | :------------------------------------------: |
+| **Email** | HTML | â |
+| | Visual Editor | â |
+| **SMS** | Text | â |
+| **Chat** | Text | â |
+| **In-App** | Text | â |
+| **Push** | Text | â |
diff --git a/style.css b/style.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/workflow/channel-steps.mdx b/workflow/channel-steps.mdx
new file mode 100644
index 000000000..0effb65df
--- /dev/null
+++ b/workflow/channel-steps.mdx
@@ -0,0 +1,46 @@
+---
+title: "Channel Steps"
+---
+
+A **channel step** within a workflow is the core building block for creating and delivering notifications to subscribers (End users). Each channel step is linked to a specific notification template and represents a notification to be sent through a single channel type (e.g., email, push, SMS, in-app, etc.).
+
+### Channel Step Execution
+
+When a channel step is executed, Novu performs the following actions:
+
+1. **Evaluates Step Conditions:**
+ Novu checks any conditions defined for the step to determine if it should be executed. This allows for dynamic notification workflows.
+
+2. **Verifies Subscriber's Information:**
+ Novu ensures the subscriber has the required information to receive notifications via this channel.
+
+ For example:
+ - For email, the recipient must have a valid email address.
+ - For push notifications, the required channel data (device token) must be configured.
+
+3. **Checks Subscriber's Preferences:**
+ Novu respects the recipient's notification preferences, verifying whether theyâve opted out of receiving notifications from this channel or workflow.
+
+### Rendering and Delivering Notifications
+
+If the step is valid and all conditions are met, Novu renders the associated template for the step and queues the message for delivery. The message is then sent to the selected provider using the credentials configured for the channel.
+
+### Available Channels
+
+
+
+ The most reliable way to reach users directly in their inbox for newsletters, updates, and transactional communications
+
+
+ Deliver notifications directly within your app or website, keeping users informed while they interact with your product
+
+
+ Instant alerts sent to users' mobile or desktop devices, even when theyâre not actively using your app
+
+
+ Quick and direct text messages to usersâ phones for urgent alerts, confirmations, or updates
+
+
+ Real-time messages delivered through popular chat platforms and messaging apps
+
+
\ No newline at end of file
diff --git a/workflow/content/content-basics.mdx b/workflow/content/content-basics.mdx
new file mode 100644
index 000000000..727b82d64
--- /dev/null
+++ b/workflow/content/content-basics.mdx
@@ -0,0 +1,52 @@
+---
+title: "Content Basics"
+sidebarTitle: "Content Basics"
+description: "Learn how to manage your notification workflow and allow no-code users to modify it."
+---
+
+Our philosophy is to allow developers to build and manage advanced components and customized views with modern technologies, and expose No-Code controls for non-technical users to modify and maintain.
+
+## Notification content management is hard
+
+One of the main challenges with transactional notifications and existing off-the-shelve solutions is that in a lot of cases they are built with either: A very technical developer oriented user in mind, or a complete no-code WYSIWYG solution.
+
+Both paths lead to frustration.
+
+### Code Based Editors
+
+This path allow developers to craft tailored experiences that are consistent with the company brand, but often this leads to require engineers time for any modification needed.
+
+With a lot of UI based notification platforms, you will be bound and limited by their choice of templating language (Liquid, handlebars, etc...) which will force engineers to do some really complex manipulations to build the usecase they need.
+
+Which leads to un-maintainable notification content that will require engineer for every change.
+
+### No-Code Editors
+
+Those platforms give a lot of control and flexibility to a non-technical user with a great looking WYSIWIG interface, but most often this can lead to:
+
+- The loss of confidence in the end result, as a critical notification workflow can be easily broken.
+- A lot of limits on the implementation, that usually requires engineer intervention and using HTML directly. Which again, losses the whole point of a no-code editor.
+
+## The Novu Way
+
+History have shown us that catering to an individual persona can lead to a lot of frustration, which in the end generated a non-consistent end-user experience.
+
+We strongly believe that for a truly amazing notificaton experience, both functions need to work in harmony.
+
+### Your notification design-system
+
+Instead of building isolated emails, messages and workflows, we recommend thinking about your notification strategy as carefully crafted Design System Components.
+
+This will allow you to build a consistent and maintainable notification experience that can be easily consumed by your internal teams.
+
+### Abstract complex logic
+
+Step Controls are the `props` in your design system components. They are the knobs and dials that allow you to modify the content and behavior of notification template.
+
+There might a lot of complex logic that goes into a notification template, and for mission-critical notifications like your `Password reset` email,
+you might want to expose controls for the static content before and after the password reset link, but to not accidentally to delete the dynamic `{{resetLinkUrl}}` button.
+
+### Use modern frameworks
+
+With Novu we recommend using a modern content framework SDK such as: MJML, React Email, Vue Email, Maizzle and etc...
+Using a technical stack that is close to your front-end stack will allow reusing a lot of existing application logic and design tokens as part of your workflows.
diff --git a/workflow/content/editor.mdx b/workflow/content/editor.mdx
new file mode 100644
index 000000000..e69de29bb
diff --git a/workflow/content/handlebars-and-helpers.mdx b/workflow/content/handlebars-and-helpers.mdx
new file mode 100644
index 000000000..e69de29bb
diff --git a/workflow/content/variables.mdx b/workflow/content/variables.mdx
new file mode 100644
index 000000000..e69de29bb
diff --git a/workflow/delay.mdx b/workflow/delay.mdx
new file mode 100644
index 000000000..cab6edd22
--- /dev/null
+++ b/workflow/delay.mdx
@@ -0,0 +1,21 @@
+---
+title: "Delay Steps in Workflows"
+sidebarTitle: "Delay Action"
+description: "Learn how to use delay steps to control timing and pacing in your notification workflows."
+---
+
+The delay action awaits a specified amount of time before moving on to trigger the following steps of the workflow.
+
+## Common usecases
+
+- Waiting for X amount of time before sending the message
+- Wait for a short period of time before sending a push message in case the user seen the notification in the Inbox Component
+- Allow the user some time to cancel an action that generated a notification
+
+## Adding a delay step
+
+Delay steps can be inserted at any stage of your workflow execution, they can happen after or before any action. The workflow execution will be halted for the given amount of time and then resumed to the next step in the flow.
+
+The action can also be skipped using the `skip` parameter conditionally to allow more complex usecases of when to wait and when to send an email immediately.
+
+Changing the step content after triggering the workflow with delay step will not affect the existing pending delayed notification content.
\ No newline at end of file
diff --git a/workflow/digest.mdx b/workflow/digest.mdx
new file mode 100644
index 000000000..d7e6bd7b4
--- /dev/null
+++ b/workflow/digest.mdx
@@ -0,0 +1,83 @@
+---
+title: "Collect Multiple Events to a Single Message with the Digest Engine"
+sidebarTitle: "Digest action"
+---
+
+The digest engine collects multiple trigger events, aggregates them into a single message, and delivers that new payload to the next workflow step.
+This becomes useful when a user would otherwise receive a large number of notifications, and you want to avoid over-notifying. When you use a Digest action step, Novu automatically batches the incoming trigger events based on the `subscriberId` and an **optional** `digestKey` that can be added to control the digest logic of the events.
+
+## Digest action step
+
+After adding a digest step to a workflow, each node that will be below the digest node will be only triggered once in the specified digest interval.
+You can decide to send messages before adding a digest node and they will be triggered in real-time.
+
+
+
+## Digest configuration
+
+### Digest key
+
+If specified, the digest engine will group the events based on the `digestKey` and `subscriberId`, otherwise the digest engine will group the events based only on the subscriberId.
+
+The digest key might come useful when you want a particular subscriber to get events grouped on a custom field. For example when an actor likes the user's post, you might want to digest based on the `post_id` key.
+
+### Time interval
+
+The time interval determines how long the digest engine will wait before sending the message once created. You can specify the amount and the unit that best suits your needs.
+
+Here, in the image below, `5` is the interval amount, and `mins` is the interval unit. Interval units can be `sec(s)`, `min(s)`, `hour(s)`, or `day(s)`.
+
+## Digest strategy types
+
+The strategy which Novu should use to handle the digest step. More details on available strategies below.
+
+Novu allows you to define different digest strategies depending on the actual use-case you are trying to achieve. At this point we allow you to select from 2 strategies:
+
+- Regular
+- Look-back
+- Scheduled
+
+Let's explore them in detail:
+
+### Regular strategy
+
+In regular strategy, a digest will always be created for the specified window time. Which means that from the first event trigger, if no active digest exists for this subscriber, one will be created and the user will receive the message only when the digest window time is reached.
+
+### Look-back strategy
+
+In the Look-Back strategy, before creating a digest, Novu will check if a message was sent to the user in the Look-back period. If a message was sent, a digest will be created. Otherwise, a message will be sent directly to the user and the digest creation will be skipped.
+
+Look-back digest has two intervals, `digest interval` and `look-back window`. First, it checks if any event is triggered within the past look-back window, only then a digest is created for the digest interval. If not, the event is considered non-digest and workflow execution continues to the next step.
+
+#### Example
+
+Let's set the digest interval as 20 minutes and the look-back interval as 15 minutes.
+
+If we trigger the first event. Since it is the first event and there was no event triggered in the past 15 minutes (look-back interval), this event will send a message immediately (without digest).
+Now, if we trigger a second event within 15 minutes range, then a new digest will be created with this second event. From now on, for the next 20 minutes (digest interval), all triggers will be digested, and after 20 minutes, the workflow will carry forward to the next step with digested events as a payload.
+
+### Scheduled digest
+
+All digest times are in UTC time
+
+Digest incoming events for the specified time. Once that time threshold since the first event has passed, proceed to the next workflow step.
+
+Available timeframes:
+- Minutes
+- Hours
+- Daily
+- Weekly
+
+## Frequently Asked Questions
+
+
+
+ If scheduled digest is sent for 9:00 daily, then novu will collect all events triggered between 9:00 AM today till 9:00 AM tomorrow and send the digest at 9:00 AM tomorrow. This process is repeated daily. If there is no any event triggered between 9:00 AM today and 9:00 AM tomorrow, then no digest will be sent.
+
+
+
+ Both digests are same in this case.
+
+
+
+
diff --git a/workflow/how-to/build-a-workflow.mdx b/workflow/how-to/build-a-workflow.mdx
new file mode 100644
index 000000000..267db5be3
--- /dev/null
+++ b/workflow/how-to/build-a-workflow.mdx
@@ -0,0 +1,93 @@
+---
+title: "Build a Workflow"
+sidebarTitle: "Build a workflow"
+description: "Learn how to build a Novu Workflow"
+---
+
+
+
+ This is where you can find and manage your existing workflows.
+
+
+ This will open the initial workflow creation screen.
+ Here you define:
+ - Name of the workflow
+ - This is also referred to as the workflow `Identifier`
+ - Tags (optional)
+ - Description of the workflow (optional)
+
+ Once you've filled in the required fields, click on the **"Create Workflow"** button.
+
+
+ This is where you can start adding steps to your workflow. **The first step will always be the **"Workflow Trigger"**.
+
+ You can add the following steps by clicking on the **"Add Step"** (+) button:
+
+ **Channels**
+ - Email
+ - In-app
+ - Push
+ - Web push
+ - Mobile push
+ - Chat
+ - Enterprise messaging platforms (e.g. Slack, Microsoft Teams, etc.)
+ - Consumer messaging tools (e.g. WhatsApp, Telegram, Discord, etc.)
+ - SMS
+
+ If a channel step you've added is not configured in your Novu account, you'll see an Error.
+
+
+ **Actions**
+ - Digest
+ - Delay
+ - Custom (Coming soon, currently only available in the [Novu Framework](/framework/custom))
+
+
+ Each step in the workflow requires a template that defines the notification or message content and payload. The editor enables you to preview the rendered output of your content.
+
+ **Content creation and templates**
+
+ - Each channel step has its own template configuration options, tailored to the limitations and requirements of the specific channel.
+ - The editor provides a live preview to show how the final message will appear.
+ - You can use system variables for personalization, including:
+ - Subscriber variables: firstName, lastName, email, phone, avatar.
+ - Actor variables: for details about the event initiator.
+ - Step variables: for data specific to the workflow execution.
+ - Brand variables: for aligning with your organization's visual identity.
+ - Tenant variables: for organization-specific data.
+
+**Dynamic content**
+
+ - Inject dynamic data into your templates using payload variables.
+ - These variables can be utilized in message content, subjects, and sender names for enhanced personalization.
+
+**Important:** When using dynamic content with payload variables, ensure that the required payload is passed when triggering the workflow.
+
+ Once youâve finished configuring your template, donât forget to click the `Save step` button to apply your changes.
+
+
+
+
+ There are three main ways to trigger a workflow:
+
+ - **Via the Novu Dashboard**
+ This method is ideal for conducting quick tests directly from the Dashboard. Itâs a simple and convenient way to verify basic functionality.
+
+ - **Using the trigger code snippet**
+ Copy the code snippet and execute it in your local environment or an online sandbox. This approach allows for more thorough testing, enabling you to integrate the trigger with your application logic and live data for a realistic evaluation.
+
+ - **Integrating the trigger in your application**
+ Once all tests are complete, you can implement the trigger method directly in your application. This allows you to test the workflow in a real-world scenario, ensuring it functions seamlessly with your app's actual environment and users.
+
+
+Novu operates in a multi environment setup, with the currently available environments:
+
+- **Development**: Acts as a staging and test environment, where your non-technical peers can view and modify controls.
+- **Production**: For triggering workflows to your customers.
+
+After you've tested your workflow in the **Development** environment, you can promote it to **Production**.
+
+[Learn more about promoting workflows to production](/framework/deployment/production)
+
+
+
diff --git a/workflow/media-assets/digest-engine.png b/workflow/media-assets/digest-engine.png
new file mode 100644
index 000000000..e3fc9af17
Binary files /dev/null and b/workflow/media-assets/digest-engine.png differ
diff --git a/workflow/media-assets/how-it-works.png b/workflow/media-assets/how-it-works.png
new file mode 100644
index 000000000..cba34ef05
Binary files /dev/null and b/workflow/media-assets/how-it-works.png differ
diff --git a/workflow/media-assets/step-conditions.png b/workflow/media-assets/step-conditions.png
new file mode 100644
index 000000000..81553646d
Binary files /dev/null and b/workflow/media-assets/step-conditions.png differ
diff --git a/workflow/media-assets/step-conditions1.png b/workflow/media-assets/step-conditions1.png
new file mode 100644
index 000000000..3d83fa02f
Binary files /dev/null and b/workflow/media-assets/step-conditions1.png differ
diff --git a/workflow/media-assets/workflow-editor.png b/workflow/media-assets/workflow-editor.png
new file mode 100644
index 000000000..232e1dd45
Binary files /dev/null and b/workflow/media-assets/workflow-editor.png differ
diff --git a/workflow/overview.mdx b/workflow/overview.mdx
new file mode 100644
index 000000000..816081472
--- /dev/null
+++ b/workflow/overview.mdx
@@ -0,0 +1,51 @@
+---
+title: "Workflow Editor Overview"
+sidebarTitle: "Overview"
+description: "The workflow Editor combines no-code simplicity and code-based flexibility, enabling users to design and manage advanced notification workflows tailored to their needs."
+---
+
+The workflow Editor is a robust visual tool that empowers both no-code users and developers to design advanced notification workflows.
+It seamlessly combines the intuitive simplicity of no-code building blocks with the adaptability and precision of code-based customization.
+### What is a workflow?
+
+A workflow in Novu is a container for all notification/message logic and templates within your system.
+
+Each workflow:
+
+- Has a unique identifier (key)
+- Executes for one subscriber at a time (e.g. end user, recipient, customer, etc.)
+- Contains complete notification/message logic and templates
+- Supports subscriber preference management
+- Can be triggered via API calls, events, or scheduled operations
+
+
+Learn what workflows are and how they work in Novu
+
+
+## Different types of Novu Workflows
+
+### Visual workflow editor (No-Code)
+
+**Best suited for:**
+
+- Straightforward use cases without complex logic
+- Building emails using Novu's Email WYSIWYG Editor
+- Modifying existing workflows
+- Quick prototyping, testing, and iteration
+- Collaboration with non-technical stakeholders
+
+### Framework SDK (Code-Based)
+
+**Best suited for:**
+
+- Complex workflow logic implementation
+- External API integration
+- Custom data transformation
+- Advanced routing rules
+- Type safe workflow payloads
+- Specialized business logic
+- Complex conditional branches
+- Custom email templates (React Email, Vue Email, MJML etc.)
+- Workflow versioning
+
+[Learn more about Novu Framework](/framework/overview)
\ No newline at end of file
diff --git a/workflow/step-conditions.mdx b/workflow/step-conditions.mdx
new file mode 100644
index 000000000..9b09695c3
--- /dev/null
+++ b/workflow/step-conditions.mdx
@@ -0,0 +1,180 @@
+---
+title: "Step Conditions"
+sidebarTitle: "Step Conditions"
+description: "Create dynamic notification workflows using rule-based conditions. Control message delivery based on subscriber data, payload information, and workflow outcomes."
+---
+
+The Step Condition feature in Novu enables you to define conditional logic for each workflow step (node), ensuring a precise and tailored notification experience. This feature adds flexibility and control by allowing you to determine whether a step should execute based on subscriber data, payload data, or conditions stemming from previous workflow steps.
+
+---
+
+## What Are Workflow Step Conditions?
+
+When adding a workflow step (node) in Novu, it can either be:
+
+1. **Channel Step**: In-App, Email, SMS, Push, or Chat.
+2. **Action Step**: Digest or Delay.
+
+Each step includes the ability to configure **step conditions** that define whether the step is executed. The conditions can combine multiple logical rules using **AND** and **OR** operators.
+
+---
+
+## Areas for Configuring Step Conditions
+
+### 1. **Subscriber Variables**
+
+Conditions can leverage subscriber-related fields to tailor notifications based on user-specific data. Examples of subscriber variables include:
+
+- `subscriber.firstName`
+- `subscriber.lastName`
+- `subscriber.email`
+- `subscriber.phone`
+- `subscriber.avatar`
+- `subscriber.locale`
+- `subscriber.data`
+- `subscriber.subscriberId`
+- `subscriber.isOnline`
+- `subscriber.lastOnlineAt`
+
+
+
+For instance, you might want to send an SMS only to users whose `subscriber.isOnline` is `false`.
+
+
+
+---
+
+### 2. **Payload Data**
+
+Conditions can also depend on custom payload data passed during the workflow trigger call to the Novu API. This allows you to define dynamic rules based on the data unique to each workflow execution.
+
+Example payload data:
+
+```json
+{
+ "orderId": "12345",
+ "totalAmount": 150,
+ "orderStatus": "completed"
+}
+```
+
+You can configure conditions such as:
+
+- `payload.orderStatus = "completed"`
+- `payload.totalAmount > 100`
+
+This makes it possible to create dynamic notifications based on context-specific information.
+
+---
+
+### 3. **Previous Step Conditions**
+
+For workflows involving sequential steps, conditions can also depend on the **outcome of a previous step**. For example, if the prior step was an **In-App Notification**, the condition could check:
+
+- `steps.in-app-step.seen`
+- `steps.in-app-step.read`
+- `steps.in-app-step.lastSeenDate`
+- `steps.in-app-step.lastReadDate`
+
+This is especially useful for tailoring follow-up notifications. For instance, send an email only if the In-App notification was not read within 24 hours.
+
+---
+
+### 4. **Advanced Application State Calculations**
+
+For more complex scenarios where you need to perform advanced calculations based on your application state, you can use the [Novu Framework Skip Step](/framework/typescript/steps/overview).
+
+This approach allows you to:
+
+- Access your application's database or external services
+- Perform complex business logic calculations
+- Make API calls to external services
+- Execute custom validation rules
+
+The skip step gives you full programmatic control over whether a notification step should be executed, going beyond the built-in condition builder capabilities.
+
+---
+
+## Query Builder Options
+
+The query builder enables you to construct powerful logical expressions for your step conditions. Supported operators include:
+
+| Operator | Description | Example |
+| --- | --- | --- |
+| `=` | Equal to | `subscriber.locale = "en-US"` |
+| `!=` | Not equal to | `subscriber.isOnline != true` |
+| `<` | Less than | `payload.totalAmount < 100` |
+| `>` | Greater than | `payload.totalAmount > 100` |
+| `<=` | Less than or equal to | `payload.totalAmount <= 200` |
+| `>=` | Greater than or equal to | `payload.totalAmount >= 200` |
+| `contains` | Contains a substring | `payload.orderId contains "123"` |
+| `begins with` | Starts with | `subscriber.firstName begins with "J"` |
+| `ends with` | Ends with | `subscriber.email ends with "@xyz.com"` |
+| `does not contain` | Does not contain a substring | `payload.orderId does not contain "456"` |
+| `does not begin with` | Does not start with | `subscriber.firstName does not begin with "M"` |
+| `does not end with` | Does not end with | `subscriber.lastName does not end with "Smith"` |
+| `is null` | Is null | `subscriber.phone is null` |
+| `is not null` | Is not null | `subscriber.email is not null` |
+| `in` | Matches one of several values | `subscriber.locale in ["en-US", "es-ES"]` |
+| `not in` | Does not match any of the listed values | `subscriber.locale not in ["fr-FR", "de-DE"]` |
+| `between` | Within a range | `payload.totalAmount between [50, 200]` |
+| `not between` | Outside of a range | `payload.totalAmount not between [0, 50]` |
+
+---
+
+## Using Dynamic Data Fields for Comparison
+
+The **value** field in a condition can also be a dynamic data field. This allows you to compare two data points dynamically rather than using static values.
+
+For example:
+
+```json
+{
+ "operator": "AND",
+ "conditions": [
+ {
+ "field": "payload.foo",
+ "operator": "=",
+ "value": "{{payload.bar}}"
+ }
+ ]
+}
+```
+
+
+
+In this case, the step will execute only if `payload.foo` is equal to `payload.bar` at runtime.
+
+You can also use subscriber variables in the same way:
+
+```json
+{
+ "operator": "AND",
+ "conditions": [
+ {
+ "field": "subscriber.firstName",
+ "operator": "=",
+ "value": "{{payload.firstName}}"
+ }
+ ]
+}
+```
+
+
+
+This enables flexible condition logic based on real-time data comparisons.
+
+---
+
+## Building Condition Groups
+
+Novu allows you to group multiple conditions using **AND** and **OR** operators to create complex logic. For instance:
+
+- **AND Group**: All conditions in the group must be true for the step to execute.
+- **OR Group**: At least one condition in the group must be true.
+
+Condition groups can also be nested for advanced use cases.
+
+---
+
+Novu's Step Condition feature empowers you to build intelligent and dynamic workflows tailored to your specific use cases. By leveraging subscriber data, payload information, and step outcomes, you can ensure that each notification reaches the right audience at the right time with the appropriate content.
\ No newline at end of file
diff --git a/workflow/tags.mdx b/workflow/tags.mdx
new file mode 100644
index 000000000..4018a1409
--- /dev/null
+++ b/workflow/tags.mdx
@@ -0,0 +1,40 @@
+---
+title: "Tags: Organizing Your Notifications"
+sidebarTitle: "Tags"
+description: "Learn how to organize and manage notification tags using Novu's visual workflow editor for better user experience and notification management."
+---
+
+**Tags** act like labels or categories that help you organize and manage notifications in your app. By grouping notifications under specific tags, you can better control how they're filtered, displayed, or managed by both your app and your users.
+
+For example, you might want to group all security-related notifications together, separate from updates about account activity or promotional offers.
+
+## Why Use Tags?
+
+- **Filtering Notifications**: Tags make it easy to filter and display notifications based on categories.
+For instance, you can create a UI that allows users to view only security or promotional notifications.
+- **[Preference Management](/inbox/react/components/preferences)**: With tags, users can manage their notification preferences by category, choosing to enable or mute specific types of notifications.
+
+Think of it as organizing emails into foldersâtags help keep things tidy and manageable for both you and your users.
+
+
+## How to Add Tags to Notifications
+
+
+
+ Navigate to the **"Workflows"** tab
+
+
+ Create a new workflow or edit an existing workflow
+
+
+ One of the fields in the workflow is the **Tags** field. You can add one or more (max. 16) tags to a notification
+
+
+
+## Best Practices for Using Tags
+
+- **Define Categories Early**: Identify key notification categories for your app, such as security, promotions, or updates.
+- **Consistent Naming**: Use clear and consistent tag names to avoid confusion (e.g., prefer security over sec_alert).
+- **Keep It Manageable**: Avoid overloading with too many tags. Focus on meaningful groupings that provide real value.
+
+Tags are a powerful way to streamline your notification system, helping users stay organized and informed while giving you greater control over your app's notification behavior.
\ No newline at end of file
diff --git a/workflow/template-editor.mdx b/workflow/template-editor.mdx
new file mode 100644
index 000000000..1701dbfc1
--- /dev/null
+++ b/workflow/template-editor.mdx
@@ -0,0 +1,221 @@
+---
+title: "Template Editor"
+description: "Learn how to use the Novu notification template editor to design notifications"
+---
+
+Each channel step in a Novu workflow comes with its own notification template. This template defines how notifications appear for a specific channel.
+
+Quality templates are used to create personalized, visually appealing, and effective notifications.
+
+- **Injecting variables from your trigger data into your notification template.**
+- **Using Liquid syntax for logic and control flow within templates.**
+- **Previewing and testing your notification templates.**
+
+## Personalizing Notifications with Template Variables
+
+To insert a variable into your Novu notification template, use double curly braces: `{{ variable_name }}`.
+
+Novu templates allow you to reference several types of variables:
+
+### Data payload variables
+These variables originate from the data payload in your workflow trigger.
+For example, if you include `{ "order_id": "12345" }` in your payload, you can reference it in your template as `{{ payload.order_id }}`.
+
+### User properties
+You can access user properties (like `firstName` or custom subscriber properties) using `{{ subscriber.* }}`. For instance:
+
+```liquid
+Hi {{ subscriber.firstName }},
+
+Youâve been upgraded to the {{ subscriber.data.plan }} plan.
+
+Thanks,
+The Novu Team
+```
+
+## Variable Popover
+
+When clicking on a variable in the template editor, a popover will appear. This popover can be used to easily manipulate the variable formatting by applying default values or Liquid Filters.
+
+
+
+
+
+### Applying Liquid Filters
+
+The variable popover will display a list of suggested Liquid Filters based on the variable type, you can apply one or more filters to the variable and re-order using drag and drop.
+Re-ordering filters is useful as the filters are applied in the order they are listed, and the output of each filter is passed to the next one.
+
+### Previewing filters output
+
+With more advanced filter logic, you can preview the output of the filters by clicking on the **Preview** button and pass the variable value to see how the filters will be applied.
+
+### Raw Liquid.js syntax
+
+You can also apply raw Liquid.js syntax to the variable by clicking on the **Raw** button which will reveal the raw Liquid.js content that will be applied to the variable.
+
+## Adding logic with Liquid Filters
+
+Novu supports Liquid filters to add dynamic and conditional content to your notifications. Below are examples of how to use the top 10 Liquid filters in real-world notification templates.
+
+Learn more about the Liquid Templating Language.
+
+
+### `capitalize`
+
+Use `capitalize` to ensure proper formatting for user names.
+
+```liquid
+Hello {{ subscriber.firstName | capitalize }},
+Welcome to Novu! We're excited to have you on board.
+```
+
+**Output**:
+`Hello John,
+Welcome to Novu! We're excited to have you on board.`
+
+---
+
+### `upcase`
+
+Use `upcase` for emphasizing specific information like workspace names.
+
+```liquid
+Your workspace {{ payload.workspaceName | upcase }} has been successfully created.
+```
+
+**Output**:
+`Your workspace TEAM ALPHA has been successfully created.`
+
+---
+
+### `downcase`
+
+Use `downcase` for consistent email formatting or usernames.
+
+```liquid
+Hi {{ subscriber.email | downcase }},
+Weâve sent a confirmation to your inbox.
+```
+
+**Output**:
+`Hi john.doe@example.com,
+Weâve sent a confirmation to your inbox.`
+
+---
+
+### `date`
+
+Use `date` to format subscription or event dates.
+
+```liquid
+Your subscription will renew on {{ payload.renewalDate | date: "%B %d, %Y" }}.
+```
+
+**Output**:
+`Your subscription will renew on December 31, 2024.`
+
+---
+
+### `truncate`
+
+Use `truncate` to shorten long content like notification messages.
+
+```liquid
+New comment on your post: {{ payload.commentText | truncate: 20 }}
+Click here to read more.
+```
+
+**Output**:
+`New comment on your post: Great work on your...
+Click here to read more.`
+
+---
+
+### `truncatewords`
+
+Use `truncatewords` to limit the number of words in a preview.
+
+```liquid
+{{ subscriber.firstName }}, here's a preview of the article:
+{{ payload.articleExcerpt | truncatewords: 5 }}
+```
+
+**Output**:
+`John, here's a preview of the article:
+Novu is a flexible and...`
+
+---
+
+### `replace`
+
+Use `replace` to dynamically update template content.
+
+```liquid
+Hi {{ subscriber.firstName }},
+Your {{ payload.subscriptionType | replace: "basic", "premium" }} subscription is active.
+```
+
+**Output**:
+`Hi John,
+Your premium subscription is active.`
+
+---
+
+### `split`
+
+Use `split` to parse tags or interests.
+
+```liquid
+You have new updates in {{ payload.tags | split: "," | join: ", " }}.
+```
+
+**Input**:
+`"announcements,updates,offers"`
+
+**Output**:
+`You have new updates in announcements, updates, offers.`
+
+---
+
+### `join`
+
+Use `join` to list multiple items in a human-readable way.
+
+```liquid
+Hello {{ subscriber.firstName }},
+You have the following items pending: {{ payload.tasks | join: ", " }}.
+```
+
+**Input**:
+`["Upload documents", "Confirm email", "Schedule meeting"]`
+
+**Output**:
+`Hello John,
+You have the following items pending: Upload documents, Confirm email, Schedule meeting.`
+
+---
+
+### `default`
+
+Use `default` to provide fallback values.
+
+```liquid
+Hi {{ subscriber.nickname | default: subscriber.firstName }},
+Your account settings are updated.
+```
+
+**Output (when nickname is null)**:
+`Hi John,
+Your account settings are updated.`
+
+
+ Learn more about 40+ filters supported by LiquidJS
+
+
+## Previewing and testing notification templates
+
+When your notification template is ready, use the **Preview** mode to visualize how your notification will look. You can:
+
+- **Test dynamic payload data:** Provide sample data to see how your template renders with different values.
+- **Send test notifications:** Save your template, return to the workflow canvas, and run a test with real trigger data.