diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 00000000..863960a4
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,15 @@
+{
+ "extends": [
+ "eslint:recommended",
+ "plugin:mdx/recommended"
+ ],
+ // optional, if you want to lint code blocks at the same time
+ "settings": {
+ "mdx/code-blocks": false
+ },
+ "rules": {
+ "no-undef": "off",
+ "no-unused-expressions": "off",
+ "no-unused-vars": "off"
+ }
+}
diff --git a/.github/workflows/invalidate-echo-snippet.yml b/.github/workflows/invalidate-echo-snippet.yml
index ac9a0c62..58239965 100644
--- a/.github/workflows/invalidate-echo-snippet.yml
+++ b/.github/workflows/invalidate-echo-snippet.yml
@@ -7,13 +7,12 @@ on:
- next
- main
paths:
- - 'echo-terminal.js'
+ - "echo-terminal.js"
jobs:
- build:
- runs-on: ubuntu-latest
-
- steps:
- - run: "curl -X GET https://purge.jsdelivr.net/gh/novuhq/docs/echo-terminal.min.js"
- - run: "curl -X GET https://purge.jsdelivr.net/gh/novuhq/docs/echo-terminal.js"
-
\ No newline at end of file
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - run: "curl -X GET https://purge.jsdelivr.net/gh/novuhq/docs/echo-terminal.min.js"
+ - run: "curl -X GET https://purge.jsdelivr.net/gh/novuhq/docs/echo-terminal.js"
diff --git a/.prettierignore b/.prettierignore
index d926176d..164f3a47 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,4 +1,3 @@
# Ignore all HTML files:
-**/*.mdx
script.js
hubspot.js
\ No newline at end of file
diff --git a/.speakeasy/workflow.yaml b/.speakeasy/workflow.yaml
index 2d133b94..c085d717 100644
--- a/.speakeasy/workflow.yaml
+++ b/.speakeasy/workflow.yaml
@@ -1,12 +1,12 @@
workflowVersion: 1.0.0
speakeasyVersion: latest
sources:
- openapi-with-code-samples:
- inputs:
- - location: registry.speakeasyapi.dev/novu/novu/json-development:main
- overlays:
- - location: registry.speakeasyapi.dev/novu/novu/code-samples-typescript:main
- output: ./openapi.json
- registry:
- location: registry.speakeasyapi.dev/novu/novu/openapi-with-code-samples
+ openapi-with-code-samples:
+ inputs:
+ - location: registry.speakeasyapi.dev/novu/novu/json-development:main
+ overlays:
+ - location: registry.speakeasyapi.dev/novu/novu/code-samples-typescript:main
+ output: ./openapi.json
+ registry:
+ location: registry.speakeasyapi.dev/novu/novu/openapi-with-code-samples
targets: {}
diff --git a/README.md b/README.md
index 55020121..fcc373d2 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,7 @@ First, install the [Mintlify CLI](https://www.npmjs.com/package/mintlify) locall
npm i -g mintlify
```
-__Note__: Please install Node.js (version 18 or higher) before proceeding.
+**Note**: Please install Node.js (version 18 or higher) before proceeding.
Run the following command at the root of the documentation (where mint.json is) to preview the documentation changes
diff --git a/activity-feed/introduction.mdx b/activity-feed/introduction.mdx
deleted file mode 100644
index b4030ead..00000000
--- a/activity-feed/introduction.mdx
+++ /dev/null
@@ -1,74 +0,0 @@
----
-title: 'Activity Feed'
-description: 'Monitor all your activity from one place'
-icon: 'code'
----
-
-## Introduction
-Novu provides a notification activity feed that monitors every outgoing message associated with its relevant metadata. This can be used to monitor activity and discover potential issues with a specific provider or channel type.
-
-
-
-## Viewing a specific subscriber's activity
-
-To use a subscriber's activity feed you can filter the feed by using the subscriberId or email. This will show only the relevant data for this particular subscriber.
-
-To do this, just enter the `subscriberId` or the 'email' of the subscriber you want to get info of and then click the 'search' button on the right-hand side as shown in the image below:
-
-
-
-## Filter by workflow or channel
-
-The activity feed allows you to filter messages based on the associated workflow or channel. This is helpful when you want to assess or debug a particular workflow and its behaviour.
-
-Filtering by workflow or channel is quite simple. Just go to the Workflow dropdown (if you want to filter by workflow) or the channel tab (if you want to filter by channel) and select the corresponding workflow or channel and click the 'search' button on the right-hand side as shown in the image below:
-
-
-
-## Troubleshooting with the activity feed
-
-The activity feed also shows if a transaction is failing. You can see why a transaction is failing and rectify it. For example, take a look at the following image:
-
-You can see that an SMS notification has failed to get delivered. Clicking on it opens the execution details and the reason why that transaction failed
-
-
-This can help troubleshoot the problem and comes in handy at the time of distress.
-
-## Digest info in the activity feed
-
-If you’re using our digest notifications functionality, you’ll be able to see all the digest-related information in the activity feed.
-
-Some of the information related to digest present in the activity feed is:
-
-- Digest step delay
-- Digesting start time
-- Digest triggered events details
-- More digest execution details
-
-
-
-From here, you can see the details of ‘digest triggered events’ to see exactly which events were digested and the content of the notification you sent, as shown below:
-
-
-
-## Trigger Event Lifecycle
-
-### **Trigger request**
-
-The request contains details such as the identifier for the template, the list of subscribers who will receive the notification, the payload of the notification, and any overrides that need to be applied.
-
-### Trigger endpoint
-
-After the request is sent to the `/event/trigger` endpoint, the initial step involves mapping and validating the subscribers for that event. Following that, we validate the template and steps based on the active status or draft template flag.
-
-Once the validation process is complete, the attachments are uploaded to the storage service.
-
-Next, the trigger event with mapped subscribers and attachment links is appended to the **trigger event queue**. By queuing the events, we can achieve faster response times.
-
-### **Trigger event processing**
-
-When the event is picked up by the **trigger queue worker** we process it. For every subscriber listed in the trigger event, we create a notification entity and the corresponding jobs based on the notification template steps. The notification contains data related to the organization, template, subscriber, and event payload. It is updated with a channels field that is generated from the steps.
-
-### **Jobs**
-
-Every job is created according to the steps outlined in the template. If the template contains a digest step, the **filtering logic** is applied to produce the appropriate jobs array depending on the type of digesting: **regular** or **backoff**.
\ No newline at end of file
diff --git a/activity-feed/trigger-event-lifecycle.mdx b/activity-feed/trigger-event-lifecycle.mdx
deleted file mode 100644
index 4675a2dc..00000000
--- a/activity-feed/trigger-event-lifecycle.mdx
+++ /dev/null
@@ -1,71 +0,0 @@
----
-title: 'Trigger Event Lifecycle'
-description: 'Managing Trigger Events from Request to Processing'
-icon: 'arrows-spin'
----
-
-## Trigger Request
-
-A trigger request is the initial step in handling a trigger event. It contains crucial details such as the template identifier, a list of subscribers who will receive the notification, the payload of the notification, and any overrides that need to be applied.
-
-## Trigger Endpoint
-
-Upon sending the request to the `/event/trigger` endpoint, a series of essential steps are initiated:
-
-1. **Subscriber Mapping and Validation:** The first step involves mapping and validating the subscribers for the specified event. This ensures that notifications are sent to the correct recipients.
-
-2. **Template Validation:** Following subscriber validation, the template associated with the event is validated. This validation process considers factors such as the active status or draft template flag to determine if it meets the necessary criteria for processing.
-
-3. **Attachment Upload:** Once the validation process is successfully completed, any attachments associated with the event are uploaded to the designated storage service.
-
-4. **Event Queuing:** The trigger event, now enriched with mapped subscribers and attachment links, is appended to the **trigger event queue**. This queuing mechanism optimizes response times, ensuring efficient event processing.
-
-## Trigger Event Processing
-
-When an event is picked up by the **trigger queue worker**, the processing phase begins. Here's what happens:
-
-- **Notification Entity Creation:** For each subscriber listed in the trigger event, a corresponding notification entity is created. This entity contains essential data related to the organization, template, subscriber, and event payload.
-
-- **Job Creation:** Based on the notification template's defined steps, jobs are generated. These jobs are responsible for carrying out specific tasks related to the event notification. Additionally, the notification entity is updated with a "channels" field generated from these steps, indicating the communication channels through which notifications will be sent.
-
-## Jobs
-
-Jobs play a pivotal role in the trigger event lifecycle. They are created based on the steps outlined in the notification template. Depending on the presence of a digest step, the following logic is applied:
-
-- **Digest Step:** If the template includes a digest step, filtering logic is applied to produce an appropriate array of jobs. This logic differentiates between two types of digesting: **regular** and **backoff**, each serving distinct purposes in event processing.
-
-## Job Statuses
-
-
-| Status | Description |
-|-------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| **PENDING** | This status is assigned to a job before it is added to the worker queue. It indicates that the job is waiting to be processed. |
-| **QUEUED** | After the initial validation and just before adding a job to the worker queue, it is set to `QUEUED`. This status signifies that the job is ready for processing but is awaiting its turn in the queue. |
-| **RUNNING** | When a job is picked up by a worker from the queue, its status is changed to `RUNNING`. This indicates that the job is currently being processed by a worker. |
-| **COMPLETED** | Once a job has been successfully executed and processed, its status is changed to `COMPLETED`. This signifies that the job has been successfully completed. |
-| **FAILED** | If a job encounters an issue during processing or execution, its status is changed to `FAILED`. This indicates that the job has not been successfully completed, and there may have been errors or problems during processing. |
-| **DELAYED** | The `DELAYED` status is applied to specific types of jobs, such as `digest` or `delay` jobs, to indicate that they are delayed and not immediately processed. For `digest` jobs, it means that the digesting process is running or scheduled for a later time. For `delay` jobs, it signifies that the job is set to be executed at a specified delay time. |
-| **CANCELED** | When a job is canceled for any reason, its status is set to `CANCELED`. This indicates that the job will not be processed further and is effectively removed from the processing queue. |
-| **MERGED** | The `MERGED` status is assigned to events that are part of a `digest`. It indicates that an event will be merged into the digesting event. In a digesting process, there is typically a primary or initial event that serves as the digesting event, and subsequent events are merged into it. Instead of having a separate `COMPLETED` status for these merged events, they are marked as `MERGED` to indicate their specific role in the digesting process. |
-| **SKIPPED** | The `SKIPPED` status is used in the context of backoff versions of digesting. In this scenario, the first event's digesting is skipped, and the second event takes on the digesting role. The `SKIPPED` status is applied to the first event's digesting, indicating that it was intentionally skipped in the digesting process. Subsequent events may be merged into the second event's digesting process, as explained with the `MERGED` status. The `SKIPPED` status helps differentiate the skipped event from others in the digesting sequence. |
-
-**Example:**
-
-
-
-
- `PENDING`
-
-
- `QUEUED`
-
-
- `RUNNING`
-
-
- `RUNNING`
-
-
- `COMPLETED`
-
-
diff --git a/additional-resources/data-migrations.mdx b/additional-resources/data-migrations.mdx
index 33e2df25..a6a053e9 100644
--- a/additional-resources/data-migrations.mdx
+++ b/additional-resources/data-migrations.mdx
@@ -1,7 +1,7 @@
---
-title: 'Data Migrations'
-description: 'Learn how to update your database data through migrations.'
-icon: 'database'
+title: "Data Migrations"
+description: "Learn how to update your database data through migrations."
+icon: "database"
---
On occasion, Novu may introduce features that require changes to the database schema or data.
@@ -25,15 +25,15 @@ Some features may have multiple migrations, in which case you will need to run e
Below you will find a list of migrations introduced in previous versions of Novu, alongside the migration path to use in the script above.
-| Version | Feature | Migration Path(s) |
-| --- | --- | --- |
-| [v0.23](https://github.com/novuhq/novu/releases/tag/v0.23.0) | API keys encryption | `./encrypt-api-keys/encrypt-api-keys-migration.ts` |
-| [v0.18](https://github.com/novuhq/novu/releases/tag/v0.18.0) | Multi-Provider | `./integration-scheme-update/add-primary-priority-migration.ts` `./integration-scheme-update/add-integration-identifier-migration.ts` |
-| | Integration Store | `./novu-integrations/novu-integrations.migration.ts` |
-| [v0.16](https://github.com/novuhq/novu/releases/tag/v0.16.0) | In-App Integration | `./in-app-integration/in-app-integration.migration.ts` |
-| | Secure Flag Fix | `./secure-to-boolean/secure-to-boolean-migration.ts` |
-| [v0.15](https://github.com/novuhq/novu/releases/tag/v0.15.0) | Database TTL | `./expire-at/expire-at.migration.ts` |
-| [v0.12](https://github.com/novuhq/novu/releases/tag/v0.12.0) | Organization Invite Fix | `./normalize-users-email/normalize-users-email.migration.ts` |
-| [v0.9](https://github.com/novuhq/novu/releases/tag/v0.9.0) | Seen/Read Support | `./seen-read-support/seen-read-support.migration.ts` |
-| [v0.8](https://github.com/novuhq/novu/releases/tag/v0.8.0) | Secure Credentials | `./fcm-credentials/fcm-credentials-migration.ts` `./encrypt-credentials/encrypt-credentials-migration.ts` |
-| [v0.4](https://github.com/novuhq/novu/releases/tag/v0.4.0) | Change Promotion | `./changes-migration.ts` |
+| Version | Feature | Migration Path(s) |
+| ------------------------------------------------------------ | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
+| [v0.23](https://github.com/novuhq/novu/releases/tag/v0.23.0) | API keys encryption | `./encrypt-api-keys/encrypt-api-keys-migration.ts` |
+| [v0.18](https://github.com/novuhq/novu/releases/tag/v0.18.0) | Multi-Provider | `./integration-scheme-update/add-primary-priority-migration.ts` `./integration-scheme-update/add-integration-identifier-migration.ts` |
+| | Integration Store | `./novu-integrations/novu-integrations.migration.ts` |
+| [v0.16](https://github.com/novuhq/novu/releases/tag/v0.16.0) | In-App Integration | `./in-app-integration/in-app-integration.migration.ts` |
+| | Secure Flag Fix | `./secure-to-boolean/secure-to-boolean-migration.ts` |
+| [v0.15](https://github.com/novuhq/novu/releases/tag/v0.15.0) | Database TTL | `./expire-at/expire-at.migration.ts` |
+| [v0.12](https://github.com/novuhq/novu/releases/tag/v0.12.0) | Organization Invite Fix | `./normalize-users-email/normalize-users-email.migration.ts` |
+| [v0.9](https://github.com/novuhq/novu/releases/tag/v0.9.0) | Seen/Read Support | `./seen-read-support/seen-read-support.migration.ts` |
+| [v0.8](https://github.com/novuhq/novu/releases/tag/v0.8.0) | Secure Credentials | `./fcm-credentials/fcm-credentials-migration.ts` `./encrypt-credentials/encrypt-credentials-migration.ts` |
+| [v0.4](https://github.com/novuhq/novu/releases/tag/v0.4.0) | Change Promotion | `./changes-migration.ts` |
diff --git a/additional-resources/glossary.mdx b/additional-resources/glossary.mdx
index 7fb7cfc0..753d175b 100644
--- a/additional-resources/glossary.mdx
+++ b/additional-resources/glossary.mdx
@@ -1,7 +1,7 @@
---
-title: 'Glossary'
-description: 'Definitions'
-icon: 'book-open'
+title: "Glossary"
+description: "Definitions"
+icon: "book-open"
---
## Introduction
@@ -12,105 +12,127 @@ If you have any questions or need further clarification on any of the terms list
## List of key terms and definitions
-## Notification
+## Notification
+
A brief message or alert that informs users about events, updates, or some other information
-## Channels
+
+## Channels
+
Novu lets you send notifications across different communication mediums, including emails, in-app messages, push notifications, SMS, and chat. Each of these five communication mediums is referred to as a notification ‘channel’.
-
-## Providers
-Providers are responsible for handling message delivery across various channels. Novu currently supports multiple notification channels, each with its own set of providers.
-
- - Chat: This channel offers these providers:
- - Discord
- - MS Teams
- - Slack
- - Zulip
- - Email: The Email channel features these providers:
- - Sendgrid
- - Amazon SES
- - Sendinblue
- - Resend
- - SparkPost
- - Postmark
- - Mailjet
- - Mailtrap
- - Plunk
- - Braze
- - Mailersend
- - Outlook 365 (based on a custom SMTP server)
- - Mailgun
- - Mandrill
- - Netcore
- - Infobip, and
- - Custom SMTP
- - SMS: The SMS channel features these providers:
- - Twilio SMS
- - SMS77
- - Africa’s Talking
- - Infobip
- - Nexmo
- - Plivo
- - Sendchamp
- - AWS SNS
- - Telnyx
- - Termii
- - Firetext
- - Gupshup
- - Clickatell
- - Azure SMS
- - BulkSMS
- - SimpleTexting
- - MessageBird
- - Push Notification Providers: This channel includes these providers:
- - Firebase Cloud Messaging (FCM)
- - Expo Push
- - Apple Push Notification Service (APNS)
- - One Signal
- - Pushpad
- - Pusher Beams
- - Push Webhook
- - In-app Notification Center: Novu provides you with a set of APIs and components to create rich customized notification center experiences:
- - React component
- - Angular component
- - Vue component
- - Web component
- - iFrame embed
- - Custom styling
- - Headless notification center
+
+ {" "}
+
+## Providers Providers are responsible for handling message delivery across various
+channels. Novu currently supports multiple notification channels, each with its own
+set of providers.
+
+- Chat: This channel offers these providers:
+ - Discord
+ - MS Teams
+ - Slack
+ - Zulip
+- Email: The Email channel features these providers:
+ - Sendgrid
+ - Amazon SES
+ - Sendinblue
+ - Resend
+ - SparkPost
+ - Postmark
+ - Mailjet
+ - Mailtrap
+ - Plunk
+ - Braze
+ - Mailersend
+ - Outlook 365 (based on a custom SMTP server)
+ - Mailgun
+ - Mandrill
+ - Netcore
+ - Infobip, and
+ - Custom SMTP
+- SMS: The SMS channel features these providers:
+ - Twilio SMS
+ - SMS77
+ - Africa’s Talking
+ - Infobip
+ - Nexmo
+ - Plivo
+ - Sendchamp
+ - AWS SNS
+ - Telnyx
+ - Termii
+ - Firetext
+ - Gupshup
+ - Clickatell
+ - Azure SMS
+ - BulkSMS
+ - SimpleTexting
+ - MessageBird
+- Push Notification Providers: This channel includes these providers:
+ - Firebase Cloud Messaging (FCM)
+ - Expo Push
+ - Apple Push Notification Service (APNS)
+ - One Signal
+ - Pushpad
+ - Pusher Beams
+ - Push Webhook
+- Inbox: Novu provides you with a set of APIs and components to create rich customized inbox experiences:
+ - React component
+ - Angular component
+ - Vue component
+ - Web component
+ - iFrame embed
+ - Custom styling
+ - Headless Inbox
## Subscribers
+
Subscribers are entities designated to receive the notifications you send. Each subscriber in Novu is uniquely identified by their `subscriberId`.
## Actor
-An `actor` refers to a user or subscriber who initiates actions that trigger events within the system. Each actor is uniquely identified by an "actorId," also known as "subscriberId," which distinguishes them from others.
-Actors hold user-related variables, such as subscriber properties and data payload, containing information like names, emails, and custom data.
+An `actor` refers to a user or subscriber who initiates actions that trigger events within the system. Each actor is uniquely identified by an "actorId," also known as "subscriberId," which distinguishes them from others.
-Additionally, actors can enhance notifications by allowing their avatars to be displayed, improving the context and identification of notifications.
+Actors hold user-related variables, such as subscriber properties and data payload, containing information like names, emails, and custom data.
+Additionally, actors can enhance notifications by allowing their avatars to be displayed, improving the context and identification of notifications.
Including actors in event data enables precise tracking and personalization of actions and events in the Novu platform.
## Workflow
+
Workflow templates define the flow of messages sent to subscribers.
+
## Topics
+
Topics facilitate bulk notifications to multiple subscribers simultaneously, streamlining communication.
+
## Digest Engine
+
The digest engine aggregates multiple trigger events into a single message, ensuring efficient communication.
+
## Delay Actions
+
Delay actions introduce time intervals between workflow steps, optimizing message delivery timing.
+
## Step Filter
+
Step filters customize workflow by specifying notification criteria, enhancing communication efficiency.
+
## Organizations
+
Organizations allow separation of notifications across multiple products, managed through the Novu web dashboard.
-
+
+
+ {" "}
+
## Environments
-Novu runs all your requests in the context of an environment. By default, Novu creates two environments when your account was created, `development` and `production`.
- 1. `Development environment`: The development environment is used for testing purposes and validating notification changes prior to committing them to the production environment.
- 2. `Production environment`: It will be your live/production environment, you cannot make changes to this environment directly. You will first have to make the changes in the `development` environment and then promote it to `production`. This is a read-only environment.
+
+Novu runs all your requests in the context of an environment. By default, Novu creates two environments when your account was created, `development` and `production`. 1. `Development environment`: The development environment is used for testing purposes and validating notification changes prior to committing them to the production environment. 2. `Production environment`: It will be your live/production environment, you cannot make changes to this environment directly. You will first have to make the changes in the `development` environment and then promote it to `production`. This is a read-only environment.
+
## Data associated with an environment
+
- Subscribers (can’t be promoted to production)
- Workflows (can be promoted to production)
- Messages
@@ -118,8 +140,11 @@ Novu runs all your requests in the context of an environment. By default, Novu c
- Connected integrations (can’t be promoted to production)
- Notification feeds (can be promoted to production)
- Brand-related assets and settings
-## Team members
+
+## Team members
+
Members of a team have access to the Novu web dashboard. This allows you to have individuals work on and manage templates and notifications.
-## Layouts
-Layouts are HTML designs or structures to wrap the 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.
+## Layouts
+
+Layouts are HTML designs or structures to wrap the 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.
diff --git a/additional-resources/idempotency.mdx b/additional-resources/idempotency.mdx
index 192d31ce..355fcd26 100644
--- a/additional-resources/idempotency.mdx
+++ b/additional-resources/idempotency.mdx
@@ -1,7 +1,7 @@
---
-title: 'Idempotent Requests'
-description: 'Retry API requests fearlessly, ensuring the operation performs just once!'
-icon: 'repeat-1'
+title: "Idempotent Requests"
+description: "Retry API requests fearlessly, ensuring the operation performs just once!"
+icon: "repeat-1"
---
Our platform has a seamless integration of optional [idempotent](https://en.wikipedia.org/wiki/Idempotence) requests for `POST` and `PATCH` operations.
@@ -12,24 +12,24 @@ Leveraging this feature guarantees the safety and reliability of your requests,
Idempotent requests are critical for workflows that require the insurance of only one successful delivery request.
- This feature was introduced in version 0.22.0 and is fully operable from 0.24.0 and beyond. Currently, the Idempotency headers are not enabled on the cloud platform but are available for self-hosting.
+ This feature was introduced in version 0.22.0 and is fully operable from
+ 0.24.0 and beyond. Currently, the Idempotency headers are not enabled on the
+ cloud platform but are available for self-hosting.
- Please be aware that idempotency might not be supported in all community SDKs.
+ Please be aware that idempotency might not be supported in all community SDKs.
-
## How to Perform an Idempotent Request with SDKs
Supporting SDKS will implement Idempotency for you as long as you have retries turned on.
Not only is this seamless but it also ensures that no event request is dropped provided that your system stays up.
-
- Idempotency is only implemented for /events/trigger endpoint.
-
+Idempotency is only implemented for /events/trigger endpoint.
### Idempotent request with api
+
To make an idempotent request, simply include the `Idempotency-Key: ` in your request header.
This key should be a unique client-generated value, boasting enough entropy to prevent collisions;
we recommend a collision-resistant Unique Identifier, such as UUIDv7, CUID, or ULID, as your idempotency keys.
@@ -51,7 +51,7 @@ Here are some unique pieces constraints you should be aware of especially if you
3. A ongoing processing of the initial request that hasn't yet responded will result in a `409 Conflict` error. This will include a `Retry-After` header.
- Results will not saved if an API request is invalid.
+ Results will not saved if an API request is invalid.
## Expiring Keys
@@ -60,7 +60,9 @@ All idempotency keys are ensured to be automatically removed once they are 24 ho
After this period, the reused key will be treated as a new request and response.
## Practical Examples
+
### Example 1 - No idempotency
+
```javascript
@@ -80,9 +82,11 @@ After this period, the reused key will be treated as a new request and response.
});
```
+
### Example 2 - Idempotency Active
+
```javascript
@@ -107,8 +111,8 @@ After this period, the reused key will be treated as a new request and response.
});
```
-
+
## References
diff --git a/additional-resources/posts-videos-and-articles.mdx b/additional-resources/posts-videos-and-articles.mdx
index 720d6c75..cb7295fd 100644
--- a/additional-resources/posts-videos-and-articles.mdx
+++ b/additional-resources/posts-videos-and-articles.mdx
@@ -1,23 +1,26 @@
---
-title: 'Blog Posts, Articles & Videos'
-description: 'Blog posts, articles, and videos'
+title: "Blog Posts, Articles & Videos"
+description: "Blog posts, articles, and videos"
---
## Blog Posts / Articles
+
- [🪄✨Building a blog with a liking feature using React, Hanko and Novu 🔥](https://dev.to/novu/building-a-blog-with-a-liking-feature-using-react-hanko-and-novu-1m81)
- [How to add In-App notifications to any web app!](https://dev.to/novu/how-to-add-in-app-notifications-to-any-web-app-1b4n)
- [How To Add In-App Notifications To Your Angular App](https://dev.to/novu/how-to-add-in-app-notifications-to-your-angular-app-2dp3)
- [Creating A Hot New Food Delivery App with Novu](https://dev.to/novu/creating-a-hot-new-food-delivery-app-with-novu-2e75)
## Videos
+
- [How to add In-App Notifications to your Web app with Novu](https://www.youtube.com/watch?v=KD8zoUb132k)
- [Subscriber (User) Management & Bulk Import Guide](https://www.youtube.com/watch?v=m5nhYEuz86I&t=92s)
- [Workflow Optimization with Delay Actions](https://www.youtube.com/watch?v=kCMB-WdbzJo)
## External Resources
+
- [Simplify configuration management with Novu and Configu](https://configu.com/blog/video-first-steps-with-configu/)
- [Vercel and Novu integration](https://vercel.com/integrations/novu)
- [Novu is building open-source notification infrastructure for developers](https://venturebeat.com/business/novu-is-building-open-source-notification-infrastructure-for-developers/)
- [Novu - An open-source notification infrastructure for developers](https://reactjsexample.com/-f0-9f-9a-80-open-source-notification-infrastructure-for-products/)
- [Novu Tackles Notification Infrastructure Management](https://thenewstack.io/novu-tackles-notification-infrastructure-management/)
- - [Novu: Omni-channel notification infrastructure for developers](https://www.decibel.vc/articles/novu-omni-channel-notification-infrastructure-for-developers)
\ No newline at end of file
+ - [Novu: Omni-channel notification infrastructure for developers](https://www.decibel.vc/articles/novu-omni-channel-notification-infrastructure-for-developers)
diff --git a/security-and-compliance/security.mdx b/additional-resources/security.mdx
similarity index 99%
rename from security-and-compliance/security.mdx
rename to additional-resources/security.mdx
index 185dd044..1b55fcca 100644
--- a/security-and-compliance/security.mdx
+++ b/additional-resources/security.mdx
@@ -1,6 +1,5 @@
---
title: "Security and Compliance"
-sidebarTitle: "Security"
description: "Common questions related to security, compliance, privacy policy and terms and conditions"
icon: "shield"
---
diff --git a/api-reference/changes/apply-change.mdx b/api-reference/changes/apply-change.mdx
index 331d8b9c..e32c6b59 100644
--- a/api-reference/changes/apply-change.mdx
+++ b/api-reference/changes/apply-change.mdx
@@ -12,14 +12,15 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.changes.applyOne("changeId");
-```
+
+````
```php PHP
use Novu\SDK\Novu;
$novu = new Novu();
$novu->applyChange($changeId, []);
-```
+````
```ruby Ruby
require 'novu'
@@ -75,4 +76,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/changes/apply-changes.mdx b/api-reference/changes/apply-changes.mdx
index 199fe45a..b2c4e1ab 100644
--- a/api-reference/changes/apply-changes.mdx
+++ b/api-reference/changes/apply-changes.mdx
@@ -12,7 +12,8 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.changes.applyMany(["changeId1", "changeId2"]);
-```
+
+````
```php PHP
use Novu\SDK\Novu;
@@ -23,7 +24,7 @@ $novu->applyBulkChanges([
''
]
])->toArray();
-```
+````
```ruby Ruby
require 'novu'
@@ -81,4 +82,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/changes/get-changes-count.mdx b/api-reference/changes/get-changes-count.mdx
index d94f347f..0bb0e891 100644
--- a/api-reference/changes/get-changes-count.mdx
+++ b/api-reference/changes/get-changes-count.mdx
@@ -12,14 +12,15 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.changes.getCount();
-```
+
+````
```php PHP
use Novu\SDK\Novu;
$novu = new Novu();
$novu->getChangesCount()->toArray();
-```
+````
```ruby Ruby
require 'novu'
@@ -57,8 +58,8 @@ public class Main {
```json Response
{
- data: 0
+ "data": 0
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/changes/get-changes.mdx b/api-reference/changes/get-changes.mdx
index fcde6127..b31aefbd 100644
--- a/api-reference/changes/get-changes.mdx
+++ b/api-reference/changes/get-changes.mdx
@@ -12,14 +12,15 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.changes.get();
-```
+
+````
```php PHP
use Novu\SDK\Novu;
$novu = new Novu();
$novu->getChanges();
-```
+````
```ruby Ruby
require 'novu'
@@ -70,4 +71,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/environments/get-api-keys.mdx b/api-reference/environments/get-api-keys.mdx
index e296b702..265336fa 100644
--- a/api-reference/environments/get-api-keys.mdx
+++ b/api-reference/environments/get-api-keys.mdx
@@ -12,14 +12,15 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.environmets.getApiKeys();
-```
+
+````
```php PHP
use Novu\SDK\Novu;
$novu = new Novu();
$novu->getEnvironmentsAPIKeys()->toArray();
-```
+````
```ruby Ruby
require 'novu'
@@ -81,4 +82,4 @@ curl --request GET \
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/environments/get-current-environment.mdx b/api-reference/environments/get-current-environment.mdx
index 5a2f37ba..af67ee80 100644
--- a/api-reference/environments/get-current-environment.mdx
+++ b/api-reference/environments/get-current-environment.mdx
@@ -13,7 +13,8 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.environments.getCurrent();
-```
+
+````
```php PHP
use Novu\SDK\Novu;
@@ -21,7 +22,7 @@ use Novu\SDK\Novu;
$novu = new Novu();
$novu->getCurrentEnvironment()->toArray();
-```
+````
```ruby Ruby
require 'novu'
@@ -92,4 +93,4 @@ curl --request GET \
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/environments/get-environments.mdx b/api-reference/environments/get-environments.mdx
index af706c4b..43d98a30 100644
--- a/api-reference/environments/get-environments.mdx
+++ b/api-reference/environments/get-environments.mdx
@@ -13,14 +13,15 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.environments.getAll();
-```
+
+````
```php PHP
use Novu\SDK\Novu;
$novu = new Novu();
$novu->getEnvironments()->toArray();
-```
+````
```ruby Ruby
require 'novu'
@@ -92,4 +93,4 @@ curl --request GET \
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/environments/regenerate-api-keys.mdx b/api-reference/environments/regenerate-api-keys.mdx
index f1887fd5..cdec258f 100644
--- a/api-reference/environments/regenerate-api-keys.mdx
+++ b/api-reference/environments/regenerate-api-keys.mdx
@@ -12,14 +12,15 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.environmets.regenerateApiKeys();
-```
+
+````
```php PHP
use Novu\SDK\Novu;
$novu = new Novu();
$key = $novu->regenerateEnvironmentsAPIKeys()->toArray();
-```
+````
```ruby Ruby
require 'novu'
@@ -70,4 +71,4 @@ curl --request POST \
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/events/broadcast-event-to-all.mdx b/api-reference/events/broadcast-event-to-all.mdx
index e4179d6a..090f1470 100644
--- a/api-reference/events/broadcast-event-to-all.mdx
+++ b/api-reference/events/broadcast-event-to-all.mdx
@@ -9,7 +9,7 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
@@ -17,16 +17,16 @@ await novu.events.broadcast("", {
payload: {
customKey: "customValue",
customKey1: {
- nestedkey1: "nestedValue1"
- }
+ nestedkey1: "nestedValue1",
+ },
},
overrides: {
email: {
- from: "support@novu.co"
- }
+ from: "support@novu.co",
+ },
},
- tenant: "tenantIdentifier"
-})
+ tenant: "tenantIdentifier",
+});
```
```php PHP
@@ -147,7 +147,7 @@ public class Main {
subscriberRequest.setSubscriberId("");
TriggerEventRequest triggerEventRequest = new TriggerEventRequest();
- triggerEventRequest.setName("");
+ triggerEventRequest.setName("");
triggerEventRequest.setTo(subscriberRequest);
triggerEventRequest.setPayload(Collections.singletonMap("", ""));
@@ -163,10 +163,10 @@ using Novu;
var novuConfiguration = new NovuClientConfiguration
{
- /**
- * Defaults to https://api.novu.co/v1
+ /**
+ * Defaults to https://api.novu.co/v1
*/
- Url = "https://novu-api.my-domain.com/v1",
+ Url = "https://novu-api.my-domain.com/v1",
ApiKey = "12345",
};
@@ -196,11 +196,11 @@ var trigger = await novu.Event.TriggerBroadcastAsync(dto);
```json Response
{
- "data": {
- "acknowledged": true,
- "status": "processed",
- "transactionId": "string"
- }
+ "data": {
+ "acknowledged": true,
+ "status": "processed",
+ "transactionId": "string"
+ }
}
```
diff --git a/api-reference/events/bulk-trigger-event.mdx b/api-reference/events/bulk-trigger-event.mdx
index 70b2e7a9..d7d8219d 100644
--- a/api-reference/events/bulk-trigger-event.mdx
+++ b/api-reference/events/bulk-trigger-event.mdx
@@ -60,13 +60,13 @@ $novu = new Novu();
$novu->bulkTriggerEvent([
[
- 'name' => '',
- 'to' => '',
+ 'name' => '',
+ 'to' => '',
'payload' => ['customVariables' => 'Hello']
],
[
- 'name' => '',
- 'to' => '',
+ 'name' => '',
+ 'to' => '',
'payload' => ['customVariables' => 'World']
],
])->toArray();
@@ -259,7 +259,7 @@ public class Main {
triggerEventRequest1.setName("");
triggerEventRequest1.setTo(subscriberRequest);
triggerEventRequest1.setPayload(Collections.singletonMap("", ""));
-
+
TriggerEventRequest triggerEventRequest2 = new TriggerEventRequest();
triggerEventRequest2.setName("");
triggerEventRequest2.setTo(subscriberRequest);
@@ -280,10 +280,10 @@ using Novu;
var novuConfiguration = new NovuClientConfiguration
{
- /**
- * Defaults to https://api.novu.co/v1
+ /**
+ * Defaults to https://api.novu.co/v1
*/
- Url = "https://novu-api.my-domain.com/v1",
+ Url = "https://novu-api.my-domain.com/v1",
ApiKey = "12345",
};
@@ -314,13 +314,13 @@ var trigger = await novu.Event.TriggerBulkAsync(payload);
```json Response
{
- "data": [
- {
- "acknowledged": true,
- "status": "processed",
- "transactionId": "string"
- }
- ]
+ "data": [
+ {
+ "acknowledged": true,
+ "status": "processed",
+ "transactionId": "string"
+ }
+ ]
}
```
diff --git a/api-reference/events/cancel-triggered-event.mdx b/api-reference/events/cancel-triggered-event.mdx
index 8a140039..d52c5891 100644
--- a/api-reference/events/cancel-triggered-event.mdx
+++ b/api-reference/events/cancel-triggered-event.mdx
@@ -9,7 +9,7 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
@@ -102,10 +102,10 @@ using Novu;
var novuConfiguration = new NovuClientConfiguration
{
- /**
- * Defaults to https://api.novu.co/v1
+ /**
+ * Defaults to https://api.novu.co/v1
*/
- Url = "https://novu-api.my-domain.com/v1",
+ Url = "https://novu-api.my-domain.com/v1",
ApiKey = "12345",
};
@@ -119,8 +119,8 @@ var cancelled = await novu.Event.TriggerCancelAsync("triggerTransactionId");
```json Response
-{
- data: true
+{
+ "data": true
}
```
diff --git a/api-reference/events/trigger-event.mdx b/api-reference/events/trigger-event.mdx
index 7be941bc..86040662 100644
--- a/api-reference/events/trigger-event.mdx
+++ b/api-reference/events/trigger-event.mdx
@@ -9,26 +9,24 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
-await novu.trigger('',
- {
- to: {
- subscriberId: '',
- email: 'john@doemail.com',
- firstName: 'John',
- lastName: 'Doe',
+await novu.trigger("", {
+ to: {
+ subscriberId: "",
+ email: "john@doemail.com",
+ firstName: "John",
+ lastName: "Doe",
+ },
+ payload: {
+ name: "Hello World",
+ organization: {
+ logo: "https://happycorp.com/logo.png",
},
- payload: {
- name: "Hello World",
- organization: {
- logo: 'https://happycorp.com/logo.png',
- },
- },
- }
-);
+ },
+});
```
```php PHP
@@ -166,7 +164,7 @@ public class Main {
triggerEventRequest.setName("");
triggerEventRequest.setTo(subscriberRequest);
triggerEventRequest.setPayload(Collections.singletonMap("", ""));
-
+
TriggerEventResponse response = novu.triggerEvent(triggerEventRequest);
}
}
@@ -179,10 +177,10 @@ using Novu;
var novuConfiguration = new NovuClientConfiguration
{
- /**
- * Defaults to https://api.novu.co/v1
+ /**
+ * Defaults to https://api.novu.co/v1
*/
- Url = "https://novu-api.my-domain.com/v1",
+ Url = "https://novu-api.my-domain.com/v1",
ApiKey = "12345",
};
@@ -219,27 +217,26 @@ var trigger = await novu.Event.Trigger(payload);
```json Response
{
- "data": {
- "acknowledged": true,
- "status": "processed",
- "transactionId": "string"
- }
+ "data": {
+ "acknowledged": true,
+ "status": "processed",
+ "transactionId": "string"
+ }
}
```
-The `transactionId` within Novu is a unique identifier that is used to ensure the idempotent nature of notification delivery.
+The `transactionId` within Novu is a unique identifier that is used to ensure the idempotent nature of notification delivery.
-When you trigger an event to send a notification, you have the option to provide a `transactionId`. If you do not provide one, Novu will generate a UUID for you.
+When you trigger an event to send a notification, you have the option to provide a `transactionId`. If you do not provide one, Novu will generate a UUID for you.
**This identifier is particularly useful for preventing the same notification from being sent multiple times in case the trigger event is inadvertently called more than once.**
-By leveraging the `transactionId`, you can make idempotent requests, which means if the same `transactionId` is used in another request, Novu's API will recognize it and will not send the same notification again.
+By leveraging the `transactionId`, you can make idempotent requests, which means if the same `transactionId` is used in another request, Novu's API will recognize it and will not send the same notification again.
This upholds the principle of idempotency, ensuring that the effect of the operation is the same, no matter how many times the request is repeated with the same `transactionId`.
-
diff --git a/api-reference/execution-details/get-execution-details.mdx b/api-reference/execution-details/get-execution-details.mdx
index 12596b75..9d98c558 100644
--- a/api-reference/execution-details/get-execution-details.mdx
+++ b/api-reference/execution-details/get-execution-details.mdx
@@ -14,16 +14,14 @@ curl --request GET \
```
```javascript Node.js
-import fetch from 'node-fetch';
+import fetch from "node-fetch";
-const response = await fetch('https://api.novu.co/v1/execution-details', {
- method: 'GET',
-
+const response = await fetch("https://api.novu.co/v1/execution-details", {
+ method: "GET",
});
const data = await response.json();
```
-
```php PHP
use Novu\SDK\Novu;
@@ -101,4 +99,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/feeds/create-feed.mdx b/api-reference/feeds/create-feed.mdx
index 602839b2..53cb98bd 100644
--- a/api-reference/feeds/create-feed.mdx
+++ b/api-reference/feeds/create-feed.mdx
@@ -17,9 +17,9 @@ curl --request POST \
```
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.feeds.create("");
```
diff --git a/api-reference/feeds/delete-feed.mdx b/api-reference/feeds/delete-feed.mdx
index 2af755a7..541618b6 100644
--- a/api-reference/feeds/delete-feed.mdx
+++ b/api-reference/feeds/delete-feed.mdx
@@ -15,9 +15,9 @@ curl --request DELETE \
```
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.feeds.delete("");
```
@@ -78,4 +78,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/feeds/get-feeds.mdx b/api-reference/feeds/get-feeds.mdx
index 370919e9..15036ea3 100644
--- a/api-reference/feeds/get-feeds.mdx
+++ b/api-reference/feeds/get-feeds.mdx
@@ -15,9 +15,9 @@ curl --request GET \
```
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.feeds.get();
```
@@ -77,4 +77,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/get-v1blueprints.mdx b/api-reference/get-v1blueprints.mdx
index a4c4a0ec..536c45c6 100644
--- a/api-reference/get-v1blueprints.mdx
+++ b/api-reference/get-v1blueprints.mdx
@@ -4,4 +4,4 @@ openapi: get /v1/blueprints/{templateId}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/get-v1blueprintsgroup-by-category.mdx b/api-reference/get-v1blueprintsgroup-by-category.mdx
index e12d0308..b2f0a932 100644
--- a/api-reference/get-v1blueprintsgroup-by-category.mdx
+++ b/api-reference/get-v1blueprintsgroup-by-category.mdx
@@ -4,4 +4,4 @@ openapi: get /v1/blueprints/group-by-category
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/inbound-parse/validate-the-mx-record-setup-for-the-inbound-parse-functionality.mdx b/api-reference/inbound-parse/validate-the-mx-record-setup-for-the-inbound-parse-functionality.mdx
index 29ed088a..a58a4472 100644
--- a/api-reference/inbound-parse/validate-the-mx-record-setup-for-the-inbound-parse-functionality.mdx
+++ b/api-reference/inbound-parse/validate-the-mx-record-setup-for-the-inbound-parse-functionality.mdx
@@ -9,11 +9,10 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import fetch from 'node-fetch';
+import fetch from "node-fetch";
-const response = await fetch('https://api.novu.co/v1/inbound-parse/mx/status', {
- method: 'GET',
-
+const response = await fetch("https://api.novu.co/v1/inbound-parse/mx/status", {
+ method: "GET",
});
const data = await response.json();
```
@@ -63,10 +62,10 @@ public class Main {
```json Response
{
- "data": {
+ "data": {
"mxRecordConfigured": true
}
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/integrations/create-integration.mdx b/api-reference/integrations/create-integration.mdx
index a796c048..2e547059 100644
--- a/api-reference/integrations/create-integration.mdx
+++ b/api-reference/integrations/create-integration.mdx
@@ -33,8 +33,8 @@ curl --location 'https://api.novu.co/v1/integrations' \
```
```javascript Node.js
-import { Novu, ChannelTypeEnum, ProvidersIdEnum } from '@novu/node';
-const novu = new Novu('');
+import { Novu, ChannelTypeEnum, ProvidersIdEnum } from "@novu/node";
+const novu = new Novu("");
const createPaylod = {
name: "SendGrid",
@@ -47,8 +47,8 @@ const createPaylod = {
// ... other credentials as per provider
},
active: true,
- check: false
-}
+ check: false,
+};
await novu.integrations.create(ProvidersIdEnum.SendGrid, createPayload);
```
@@ -98,6 +98,7 @@ novu = IntegrationApi(url, api_key).create(
)
```
+
```java Java
import co.novu.sdk.Novu;
@@ -111,7 +112,6 @@ public class Main {
}
```
-
@@ -162,4 +162,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/integrations/delete-integration.mdx b/api-reference/integrations/delete-integration.mdx
index ed76a483..fe8c8430 100644
--- a/api-reference/integrations/delete-integration.mdx
+++ b/api-reference/integrations/delete-integration.mdx
@@ -8,12 +8,13 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.integrations.delete("integrationId");
-```
+
+````
```php PHP
// Get integrations
@@ -21,7 +22,7 @@ use Novu\SDK\Novu;
$novu = new Novu('');
$novu->deleteIntegration($integrationId);
-```
+````
```ruby Ruby
require 'novu'
@@ -53,7 +54,6 @@ public class Main {
}
```
-
@@ -107,4 +107,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/integrations/get-active-integrations.mdx b/api-reference/integrations/get-active-integrations.mdx
index 39c83dea..4dbc8f91 100644
--- a/api-reference/integrations/get-active-integrations.mdx
+++ b/api-reference/integrations/get-active-integrations.mdx
@@ -8,25 +8,28 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.integrations.getActive();
-```
+
+````
```php PHP
// Get integrations
use Novu\SDK\Novu;
$novu = new Novu();
$novu->getActiveIntegrations()->toArray();
-```
+````
+
```ruby Ruby
require 'novu'
client = Novu::Client.new('')
client.active_integrations()
```
+
```python Python
from novu.api import IntegrationApi
@@ -70,4 +73,4 @@ public class Main {
primary: true
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/integrations/get-integrations.mdx b/api-reference/integrations/get-integrations.mdx
index a3a695d1..89785c20 100644
--- a/api-reference/integrations/get-integrations.mdx
+++ b/api-reference/integrations/get-integrations.mdx
@@ -8,12 +8,13 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.integrations.getAll();
-```
+
+````
```php PHP
// Get integrations
@@ -21,13 +22,15 @@ use Novu\SDK\Novu;
$novu = new Novu();
$novu->getIntegrations()->toArray();
-```
+````
+
```ruby Ruby
require 'novu'
client = Novu::Client.new('')
client.integrations()
```
+
```go Go
package main
@@ -47,6 +50,7 @@ func main() {
fmt.Println(integrations)
}
```
+
```python Python
from novu.api import IntegrationApi
@@ -69,7 +73,6 @@ public class Main {
}
```
-
@@ -92,4 +95,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/integrations/get-webhook-support-status-for-provider.mdx b/api-reference/integrations/get-webhook-support-status-for-provider.mdx
index 260f8410..138b3f0c 100644
--- a/api-reference/integrations/get-webhook-support-status-for-provider.mdx
+++ b/api-reference/integrations/get-webhook-support-status-for-provider.mdx
@@ -8,25 +8,28 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu, ProvidersIdEnum } from '@novu/node';
+import { Novu, ProvidersIdEnum } from '@novu/node';
const novu = new Novu('');
await novu.integrations.getWebhookProviderStatus(ProvidersIdEnum.SendGrid);
-```
+
+````
```php PHP
// Get integrations
use Novu\SDK\Novu;
$novu = new Novu();
$novu->getWebhookSupportStatusForProvider($providerId)->toArray();
-```
+````
+
```ruby Ruby
require 'novu'
client = Novu::Client.new('')
client.webhook_provider_status('')
```
+
```python Python
from novu.api import IntegrationApi
@@ -36,6 +39,7 @@ novu = IntegrationApi(url, api_key).status(
provider_id="", # Get webhook support status for a given provider using its providerID.
)
```
+
```java Java
import co.novu.sdk.Novu;
@@ -49,15 +53,14 @@ public class Main {
}
```
-
```json Response
{
- 200: "The status of the webhook for the provider requested"
+ "200": "The status of the webhook for the provider requested"
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/integrations/set-integration-as-primary.mdx b/api-reference/integrations/set-integration-as-primary.mdx
index a0f123f7..fccf9789 100644
--- a/api-reference/integrations/set-integration-as-primary.mdx
+++ b/api-reference/integrations/set-integration-as-primary.mdx
@@ -8,12 +8,13 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.integrations.setIntegrationAsPrimary("integrationId")
-```
+
+````
```php PHP
@@ -144,4 +144,4 @@ print(response.json())
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/integrations/update-integration.mdx b/api-reference/integrations/update-integration.mdx
index d295846e..24ce8f90 100644
--- a/api-reference/integrations/update-integration.mdx
+++ b/api-reference/integrations/update-integration.mdx
@@ -9,9 +9,9 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu, ProvidersIdEnum } from '@novu/node';
+import { Novu, ProvidersIdEnum } from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
const updatePayload = {
name: "SendGrid",
@@ -19,14 +19,17 @@ const updatePayload = {
credentials: {
apiKey: "SUPER_SECRET_API_KEY",
from: "no-reply@novu.co",
- senderName: "Novu Team"
+ senderName: "Novu Team",
// ... other credentials as per provider
},
active: true,
- check: false
-}
+ check: false,
+};
-await novu.integrations.getWebhookProviderStatus(ProvidersIdEnum.SendGrid, updatePayload);
+await novu.integrations.getWebhookProviderStatus(
+ ProvidersIdEnum.SendGrid,
+ updatePayload
+);
```
```php PHP
@@ -80,7 +83,6 @@ public class Main {
}
```
-
@@ -132,4 +134,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/layouts/delete-layout.mdx b/api-reference/layouts/delete-layout.mdx
index a36028e4..9cb6da5e 100644
--- a/api-reference/layouts/delete-layout.mdx
+++ b/api-reference/layouts/delete-layout.mdx
@@ -13,14 +13,15 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.layouts.delete("layoutId");
-```
+
+````
```ruby Ruby
require 'novu'
client = Novu::Client.new('')
client.delete_layout('')
-```
+````
```python Python
from novu.api import LayoutApi
@@ -51,10 +52,10 @@ public class Main {
```json Response
{
- 204: "The layout has been deleted correctly",
- 404: "The layout with the layoutId provided does not exist in the database so it can not be deleted.",
- 409: "Either you are trying to delete a layout that is being used or a layout that is the default in the environment."
+ "204": "The layout has been deleted correctly",
+ "404": "The layout with the layoutId provided does not exist in the database so it can not be deleted.",
+ "409": "Either you are trying to delete a layout that is being used or a layout that is the default in the environment."
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/layouts/filter-layouts.mdx b/api-reference/layouts/filter-layouts.mdx
index 1a2d5128..5e0b4035 100644
--- a/api-reference/layouts/filter-layouts.mdx
+++ b/api-reference/layouts/filter-layouts.mdx
@@ -13,14 +13,15 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
const params = {
- page: 0, // optional
- pageSize: 20, // optional
- sortBy: "_id"
- orderBy: -1 //optional
+page: 0, // optional
+pageSize: 20, // optional
+sortBy: "\_id"
+orderBy: -1 //optional
}
await novu.layouts.list(params);
-```
+
+````
```ruby Ruby
require 'novu'
@@ -32,7 +33,7 @@ client.layouts({
'sortBy' => 'createdAt', # optional
'orderBy' => 1 # optional
})
-```
+````
```python Python
from novu.api import LayoutApi
@@ -64,11 +65,11 @@ public class Main {
```json Response
{
- data: ["data"],
- page: 0,
- pageSize: 0,
- totalCount: 0
+ "data": ["data"],
+ "page": 0,
+ "pageSize": 0,
+ "totalCount": 0
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/layouts/get-layout.mdx b/api-reference/layouts/get-layout.mdx
index 78fd7c30..938ba5b9 100644
--- a/api-reference/layouts/get-layout.mdx
+++ b/api-reference/layouts/get-layout.mdx
@@ -13,7 +13,8 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
await novu.layouts.get("layoutId");
-```
+
+````
```ruby Ruby
require 'novu'
@@ -27,7 +28,7 @@ body = {
},
}
client.layout('')
-```
+````
```python Python
from novu.api import LayoutApi
@@ -69,9 +70,7 @@ public class Main {
"channel": "in_app",
"content": "string",
"contentType": "string",
- "variables": [
- {}
- ],
+ "variables": [{}],
"isDefault": true,
"isDeleted": true,
"createdAt": "string",
@@ -81,4 +80,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/layouts/layout-creation.mdx b/api-reference/layouts/layout-creation.mdx
index 760e3611..2435e609 100644
--- a/api-reference/layouts/layout-creation.mdx
+++ b/api-reference/layouts/layout-creation.mdx
@@ -13,22 +13,23 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
const payload = {
- content: "
",
+description: "Organisation's first layout",
+name: "First Layout",
+identifier: "firstlayout",
+variables: [
+{
+type: "String",
+name: "body"
+required: true
+defValue: ""
+}
+]
+isDefault: false
}
await novu.layouts.update("layoutId", payloadToUpdate);
-```
+
+````
```ruby Ruby
require 'novu'
@@ -42,7 +43,7 @@ payload = {
'variables' => [''], # optional
}
client.update_layout('', payload)
-```
+````
```python Python
from novu.api import LayoutApi
@@ -77,11 +78,9 @@ public class Main {
"identifier": "string",
"description": "string",
"content": "string",
- "variables": [
- {}
- ],
+ "variables": [{}],
"isDefault": true
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/messages/delete-message-by-transactionid.mdx b/api-reference/messages/delete-message-by-transactionid.mdx
index b64aa445..59c1621d 100644
--- a/api-reference/messages/delete-message-by-transactionid.mdx
+++ b/api-reference/messages/delete-message-by-transactionid.mdx
@@ -20,4 +20,4 @@ curl --request DELETE \
204 - No Content
```
-
\ No newline at end of file
+
diff --git a/api-reference/messages/delete-message.mdx b/api-reference/messages/delete-message.mdx
index d524f6e5..7438b3fe 100644
--- a/api-reference/messages/delete-message.mdx
+++ b/api-reference/messages/delete-message.mdx
@@ -9,9 +9,9 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu, ChannelTypeEnum } from '@novu/node';
+import { Novu, ChannelTypeEnum } from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.messages.deleteById("");
```
@@ -38,7 +38,7 @@ from novu.api import MessageApi
url = "https://api.novu.co"
api_key = ""
novu = MessageApi(url, api_key).delete(
- message_id= "The message ID to delete",
+ message_id= "The message ID to delete",
)
```
@@ -68,4 +68,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/messages/get-messages.mdx b/api-reference/messages/get-messages.mdx
index 7e3a4e5c..e5787b14 100644
--- a/api-reference/messages/get-messages.mdx
+++ b/api-reference/messages/get-messages.mdx
@@ -86,4 +86,4 @@ public class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/notification/get-notification-graph-statistics.mdx b/api-reference/notification/get-notification-graph-statistics.mdx
index 87856212..6539c193 100644
--- a/api-reference/notification/get-notification-graph-statistics.mdx
+++ b/api-reference/notification/get-notification-graph-statistics.mdx
@@ -34,4 +34,4 @@ $novu = new Novu('');
$notificationGraphStats = $novu->getNotificationGraphStats()->toArray();
```
-
\ No newline at end of file
+
diff --git a/api-reference/notification/get-notification-statistics.mdx b/api-reference/notification/get-notification-statistics.mdx
index 853938c9..c05d9257 100644
--- a/api-reference/notification/get-notification-statistics.mdx
+++ b/api-reference/notification/get-notification-statistics.mdx
@@ -44,4 +44,4 @@ $novu = new Novu('');
$notificationStats = $novu->getNotificationStats()->toArray();
```
-
\ No newline at end of file
+
diff --git a/api-reference/organizations/create-organization.mdx b/api-reference/organizations/create-organization.mdx
index 50ec615e..1aadbaf2 100644
--- a/api-reference/organizations/create-organization.mdx
+++ b/api-reference/organizations/create-organization.mdx
@@ -4,4 +4,4 @@ openapi: post /v1/organizations
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/organizations/delete-member-from-organization.mdx b/api-reference/organizations/delete-member-from-organization.mdx
index b90849ab..b9787028 100644
--- a/api-reference/organizations/delete-member-from-organization.mdx
+++ b/api-reference/organizations/delete-member-from-organization.mdx
@@ -5,4 +5,3 @@ openapi: delete /v1/organizations/members/{memberId}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
diff --git a/api-reference/rate-limiting.mdx b/api-reference/rate-limiting.mdx
index 348993f8..00c1ef03 100644
--- a/api-reference/rate-limiting.mdx
+++ b/api-reference/rate-limiting.mdx
@@ -3,10 +3,7 @@ title: "API Rate Limiting"
description: "In this page you can learn about how rate limiting works with Novu's API"
---
-
- This feature is available from v0.22.0.
-
-
+This feature is available from v0.22.0.
Rate limiting is an essential functionality for establishing a robust and resilient system. It safeguards system resources from being misused by malicious actors or being monopolized by one client.
@@ -17,9 +14,8 @@ A variable-cost token bucket rate limited algorithm has been added to provide th
The following limits apply to each category of the Novu system. Each category has an independent bucket of rate-limit tokens to consume.
Bulk requests have a rate limit cost of 100 times the base limit and consume from the same token pool. For example, the free tier would allow a combined maximum of 10 standard trigger events and 2 bulk trigger events in the same 1-second window.
-
-| Category | Free | Business | Endpoints |
-|-----------------|----------|----------|------------------------------|
-| Events | 60 rps | 600 rps | Trigger |
-| Configuration | 15 rps | 150 rps | Subscribers, Topics, Tenants |
-| Global | 30 rps | 300 rps | All other endpoints consume rate limiting tokens from this category. |
\ No newline at end of file
+| Category | Free | Business | Endpoints |
+| ------------- | ------ | -------- | -------------------------------------------------------------------- |
+| Events | 60 rps | 600 rps | Trigger |
+| Configuration | 15 rps | 150 rps | Subscribers, Topics, Tenants |
+| Global | 30 rps | 300 rps | All other endpoints consume rate limiting tokens from this category. |
diff --git a/api-reference/subscribers/bulk-create-subscribers.mdx b/api-reference/subscribers/bulk-create-subscribers.mdx
index e499a6e8..a733ab75 100644
--- a/api-reference/subscribers/bulk-create-subscribers.mdx
+++ b/api-reference/subscribers/bulk-create-subscribers.mdx
@@ -9,29 +9,30 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.subscribers.bulkCreate([
- {
- subscriberId: 'test-subscriber-1',
- email: 'test-user@sd.com',
- firstName: 'subscriber-1',
- lastName: 'test-1',
- },
- {
- subscriberId: 'test-subscriber-2',
- email: 'test-user-2@sd.com',
- firstName: 'subscriber-2',
- lastName: 'test-2',
- },
- {
- subscriberId: 'test-subscriber-3',
- },
+ {
+ subscriberId: "test-subscriber-1",
+ email: "test-user@sd.com",
+ firstName: "subscriber-1",
+ lastName: "test-1",
+ },
+ {
+ subscriberId: "test-subscriber-2",
+ email: "test-user-2@sd.com",
+ firstName: "subscriber-2",
+ lastName: "test-2",
+ },
+ {
+ subscriberId: "test-subscriber-3",
+ },
]);
```
-``` java Java
+
+```java Java
import co.novu.common.base.Novu;
import co.novu.api.common.SubscriberRequest;
import co.novu.api.subscribers.responses.CreateBulkSubscriberResponse;
@@ -73,22 +74,22 @@ public class Main {
```json Response
{
- "data": {
- "updated": [],
- "created": [
- {
- "subscriberId": "test-subscriber-1"
- },
- {
- "subscriberId": "test-subscriber-2"
- },
- {
- "subscriberId": "test-subscriber-3"
- }
- ],
- "failed": []
- }
+ "data": {
+ "updated": [],
+ "created": [
+ {
+ "subscriberId": "test-subscriber-1"
+ },
+ {
+ "subscriberId": "test-subscriber-2"
+ },
+ {
+ "subscriberId": "test-subscriber-3"
+ }
+ ],
+ "failed": []
+ }
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/subscribers/create-subscriber.mdx b/api-reference/subscribers/create-subscriber.mdx
index e4045d8b..e67867ac 100644
--- a/api-reference/subscribers/create-subscriber.mdx
+++ b/api-reference/subscribers/create-subscriber.mdx
@@ -28,7 +28,7 @@ curl --location 'https://api.novu.co/v1/subscribers' \
```
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
@@ -37,12 +37,13 @@ await novu.subscribers.identify("subscriberId", {
lastName: "Jain",
email: "pawan.jain@domain.com",
phone: "+1234567890",
- avatar: "https://gravatar.com/avatar/553b157d82ac2880237566d5a644e5fe?s=400&d=robohash&r=x",
+ avatar:
+ "https://gravatar.com/avatar/553b157d82ac2880237566d5a644e5fe?s=400&d=robohash&r=x",
locale: "en-US",
data: {
isDeveloper: true,
- customKey: "customValue"
- }
+ customKey: "customValue",
+ },
});
```
@@ -128,10 +129,10 @@ using Novu;
var novuConfiguration = new NovuClientConfiguration
{
- /**
- * Defaults to https://api.novu.co/v1
+ /**
+ * Defaults to https://api.novu.co/v1
*/
- Url = "https://novu-api.my-domain.com/v1",
+ Url = "https://novu-api.my-domain.com/v1",
ApiKey = "12345",
};
@@ -172,24 +173,24 @@ var subscriber = await novu.Subscriber.CreateSubscriber(newSubscriberDto)
```json Response
{
- "data": {
- "_organizationId": "abcd12349876wxyz1234wxyz",
- "_environmentId": "zyxw4321abcd1234lmno5678",
- "firstName": "Alex",
- "lastName": "Benjamin",
- "phone": "123456789",
- "subscriberId": "abcd1234",
- "email": "alex@email.com",
- "avatar": "string",
- "locale": "en-US",
- "channels": [],
- "_id": "6516ed5a9d727fe8256028ed",
- "deleted": false,
- "createdAt": "2023-09-29T15:29:30.667Z",
- "updatedAt": "2023-09-29T15:29:30.667Z",
- "__v": 0,
- "id": "6516ed5a9d727fe8256028ed"
- }
+ "data": {
+ "_organizationId": "abcd12349876wxyz1234wxyz",
+ "_environmentId": "zyxw4321abcd1234lmno5678",
+ "firstName": "Alex",
+ "lastName": "Benjamin",
+ "phone": "123456789",
+ "subscriberId": "abcd1234",
+ "email": "alex@email.com",
+ "avatar": "string",
+ "locale": "en-US",
+ "channels": [],
+ "_id": "6516ed5a9d727fe8256028ed",
+ "deleted": false,
+ "createdAt": "2023-09-29T15:29:30.667Z",
+ "updatedAt": "2023-09-29T15:29:30.667Z",
+ "__v": 0,
+ "id": "6516ed5a9d727fe8256028ed"
+ }
}
```
diff --git a/api-reference/subscribers/delete-subscriber.mdx b/api-reference/subscribers/delete-subscriber.mdx
index 9177e46f..7046bdfc 100644
--- a/api-reference/subscribers/delete-subscriber.mdx
+++ b/api-reference/subscribers/delete-subscriber.mdx
@@ -9,7 +9,7 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
@@ -32,7 +32,6 @@ client = Novu::Client.new('')
client.delete_subscriber('')
```
-
```python Python
from novu.dto.event import InputEventDto
from novu.api import EventApi
@@ -44,7 +43,7 @@ api_key = ""
novu = SubscriberApi(url, api_key).delete(subscriber_id)
```
-``` java Java
+```java Java
import co.novu.common.base.Novu;
import co.novu.api.subscribers.responses.SubscriberDeleteResponse;
@@ -66,10 +65,10 @@ using Novu;
var novuConfiguration = new NovuClientConfiguration
{
- /**
- * Defaults to https://api.novu.co/v1
+ /**
+ * Defaults to https://api.novu.co/v1
*/
- Url = "https://novu-api.my-domain.com/v1",
+ Url = "https://novu-api.my-domain.com/v1",
ApiKey = "12345",
};
@@ -84,11 +83,11 @@ var deleted = await novu.Subscriber.DeleteSubscriber("subscriberId");
```json Response
{
- "data": {
- "acknowledged": true,
- "status": "deleted"
- }
+ "data": {
+ "acknowledged": true,
+ "status": "deleted"
+ }
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/subscribers/get-in-app-notification-feed-for-a-particular-subscriber.mdx b/api-reference/subscribers/get-in-app-notification-feed-for-a-particular-subscriber.mdx
index a48c3cad..ce7f19f9 100644
--- a/api-reference/subscribers/get-in-app-notification-feed-for-a-particular-subscriber.mdx
+++ b/api-reference/subscribers/get-in-app-notification-feed-for-a-particular-subscriber.mdx
@@ -12,15 +12,17 @@ import co.novu.common.base.Novu;
import co.novu.api.subscribers.responses.SubscriberNotificationResponse;
public class Main {
- public static void main(String[] args) {
- String apiKey = "";
- Novu novu = new Novu(apiKey);
- String subscriberId = "";
+public static void main(String[] args) {
+String apiKey = "";
+Novu novu = new Novu(apiKey);
+String subscriberId = "";
SubscriberNotificationResponse response = novu.getSubscriberNotificationsFeed(subscriberId);
}
+
}
-```
+
+````
```json Response
@@ -192,5 +194,6 @@ public class Main {
"page": "number",
"pageSize": "number"
}
-```
-
\ No newline at end of file
+````
+
+
diff --git a/api-reference/subscribers/get-subscriber-global-preferences.mdx b/api-reference/subscribers/get-subscriber-global-preferences.mdx
index 0a3531d8..b9a35dbd 100644
--- a/api-reference/subscribers/get-subscriber-global-preferences.mdx
+++ b/api-reference/subscribers/get-subscriber-global-preferences.mdx
@@ -4,4 +4,4 @@ openapi: get /v1/subscribers/{subscriberId}/preferences/{level}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/subscribers/get-subscriber-preferences.mdx b/api-reference/subscribers/get-subscriber-preferences.mdx
index 82c41b0f..9efcdc13 100644
--- a/api-reference/subscribers/get-subscriber-preferences.mdx
+++ b/api-reference/subscribers/get-subscriber-preferences.mdx
@@ -12,15 +12,17 @@ import co.novu.common.base.Novu;
import co.novu.api.subscribers.responses.SubscriberPreferenceResponse;
public class Main {
- public static void main(String[] args) {
- String apiKey = "";
- Novu novu = new Novu(apiKey);
- String subscriberId = "";
+public static void main(String[] args) {
+String apiKey = "";
+Novu novu = new Novu(apiKey);
+String subscriberId = "";
SubscriberPreferenceResponse response = novu.getSubscriberPreferences(subscriberId);
}
+
}
-```
+
+````
```json Response
@@ -45,6 +47,6 @@ public class Main {
}
]
}
-```
-
+````
+
diff --git a/api-reference/subscribers/get-subscriber.mdx b/api-reference/subscribers/get-subscriber.mdx
index 7f03c8d4..86745d22 100644
--- a/api-reference/subscribers/get-subscriber.mdx
+++ b/api-reference/subscribers/get-subscriber.mdx
@@ -9,7 +9,7 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```javascript Node.js
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
@@ -36,12 +36,15 @@ print(response.text)
```
```javascript JavaScript
-const options = {method: 'GET', headers: {Authorization: ''}};
-
-fetch('https://api.novu.co/v1/subscribers/{subscriberId}', options)
- .then(response => response.json())
- .then(response => console.log(response))
- .catch(err => console.error(err));
+const options = {
+ method: "GET",
+ headers: { Authorization: "" },
+};
+
+fetch("https://api.novu.co/v1/subscribers/{subscriberId}", options)
+ .then((response) => response.json())
+ .then((response) => console.log(response))
+ .catch((err) => console.error(err));
```
```php PHP
@@ -139,9 +142,7 @@ public class Main {
"credentials": {
"webhookUrl": "string",
"channel": "string",
- "deviceTokens": [
- "string"
- ]
+ "deviceTokens": ["string"]
},
"_integrationId": "string"
}
diff --git a/api-reference/subscribers/get-subscribers.mdx b/api-reference/subscribers/get-subscribers.mdx
index a0c3f6d0..9a263883 100644
--- a/api-reference/subscribers/get-subscribers.mdx
+++ b/api-reference/subscribers/get-subscribers.mdx
@@ -12,17 +12,19 @@ import co.novu.common.base.Novu;
import co.novu.api.subscribers.responses.BulkSubscriberResponse;
public class Main {
- public static void main(String[] args) {
- String apiKey = "";
- Novu novu = new Novu(apiKey);
+public static void main(String[] args) {
+String apiKey = "";
+Novu novu = new Novu(apiKey);
Integer page = 0;
Integer limit = 10;
BulkSubscriberResponse response = novu.getSubscribers(page, limit);
}
+
}
-```
+
+````
@@ -66,5 +68,6 @@ public class Main {
"page": "number",
"pageSize": "number"
}
-```
-
\ No newline at end of file
+````
+
+
diff --git a/api-reference/subscribers/handle-chat-oauth.mdx b/api-reference/subscribers/handle-chat-oauth.mdx
index 217d35f4..44920f19 100644
--- a/api-reference/subscribers/handle-chat-oauth.mdx
+++ b/api-reference/subscribers/handle-chat-oauth.mdx
@@ -4,4 +4,4 @@ openapi: get /v1/subscribers/{subscriberId}/credentials/{providerId}/oauth
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/subscribers/handle-providers-oauth-redirect.mdx b/api-reference/subscribers/handle-providers-oauth-redirect.mdx
index d7a1c888..62643dc4 100644
--- a/api-reference/subscribers/handle-providers-oauth-redirect.mdx
+++ b/api-reference/subscribers/handle-providers-oauth-redirect.mdx
@@ -4,4 +4,4 @@ openapi: get /v1/subscribers/{subscriberId}/credentials/{providerId}/oauth/callb
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/subscribers/mark-a-subscriber-feed-message-as-seen.mdx b/api-reference/subscribers/mark-a-subscriber-feed-message-as-seen.mdx
index bed4f570..ace7562b 100644
--- a/api-reference/subscribers/mark-a-subscriber-feed-message-as-seen.mdx
+++ b/api-reference/subscribers/mark-a-subscriber-feed-message-as-seen.mdx
@@ -4,4 +4,4 @@ openapi: post /v1/subscribers/{subscriberId}/messages/markAs
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/subscribers/mark-message-action-as-seen.mdx b/api-reference/subscribers/mark-message-action-as-seen.mdx
index 1a50770b..d60354a3 100644
--- a/api-reference/subscribers/mark-message-action-as-seen.mdx
+++ b/api-reference/subscribers/mark-message-action-as-seen.mdx
@@ -4,4 +4,4 @@ openapi: post /v1/subscribers/{subscriberId}/messages/{messageId}/actions/{type}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/subscribers/marks-all-the-subscriber-messages-as-read-unread-seen-or-unseen-optionally-you-can-pass-feed-id-or-array-to-mark-messages-of-a-particular-feed.mdx b/api-reference/subscribers/marks-all-the-subscriber-messages-as-read-unread-seen-or-unseen-optionally-you-can-pass-feed-id-or-array-to-mark-messages-of-a-particular-feed.mdx
index 851d6e58..b3994f76 100644
--- a/api-reference/subscribers/marks-all-the-subscriber-messages-as-read-unread-seen-or-unseen-optionally-you-can-pass-feed-id-or-array-to-mark-messages-of-a-particular-feed.mdx
+++ b/api-reference/subscribers/marks-all-the-subscriber-messages-as-read-unread-seen-or-unseen-optionally-you-can-pass-feed-id-or-array-to-mark-messages-of-a-particular-feed.mdx
@@ -4,4 +4,4 @@ openapi: post /v1/subscribers/{subscriberId}/messages/mark-all
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/subscribers/update-subscriber-credentials.mdx b/api-reference/subscribers/update-subscriber-credentials.mdx
index f4e793d6..3e892e84 100644
--- a/api-reference/subscribers/update-subscriber-credentials.mdx
+++ b/api-reference/subscribers/update-subscriber-credentials.mdx
@@ -4,4 +4,4 @@ openapi: put /v1/subscribers/{subscriberId}/credentials
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/subscribers/update-subscriber-global-preference.mdx b/api-reference/subscribers/update-subscriber-global-preference.mdx
index e13bf4bc..9920b52e 100644
--- a/api-reference/subscribers/update-subscriber-global-preference.mdx
+++ b/api-reference/subscribers/update-subscriber-global-preference.mdx
@@ -4,4 +4,4 @@ openapi: patch /v1/subscribers/{subscriberId}/preferences
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/subscribers/update-subscriber-online-status.mdx b/api-reference/subscribers/update-subscriber-online-status.mdx
index c04ddb37..4a36e8e8 100644
--- a/api-reference/subscribers/update-subscriber-online-status.mdx
+++ b/api-reference/subscribers/update-subscriber-online-status.mdx
@@ -12,18 +12,20 @@ import co.novu.api.subscribers.responses.SingleSubscriberResponse;
import co.novu.api.subscribers.requests.UpdateSubscriberOnlineStatusRequest;
public class Main {
- public static void main(String[] args) {
- String apiKey = "";
- Novu novu = new Novu(apiKey);
- String subscriberId = "";
+public static void main(String[] args) {
+String apiKey = "";
+Novu novu = new Novu(apiKey);
+String subscriberId = "";
UpdateSubscriberOnlineStatusRequest request = new UpdateSubscriberOnlineStatusRequest();
request.setIsOnline(true);
SingleSubscriberResponse response = novu.updateSubscriberOnlineStatus(request, subscriberId);
}
+
}
-```
+
+````
```json Response
@@ -61,5 +63,6 @@ public class Main {
"updatedAt": "string"
}
}
-```
-
\ No newline at end of file
+````
+
+
diff --git a/api-reference/subscribers/update-subscriber-preference.mdx b/api-reference/subscribers/update-subscriber-preference.mdx
index ef4f6dea..7d6b559b 100644
--- a/api-reference/subscribers/update-subscriber-preference.mdx
+++ b/api-reference/subscribers/update-subscriber-preference.mdx
@@ -12,11 +12,11 @@ import co.novu.api.subscribers.requests.UpdateSubscriberPreferenceRequest;
import co.novu.api.subscribers.responses.SingleSubscriberPrefResponse;
public class Main {
- public static void main(String[] args) {
- String apiKey = "";
- Novu novu = new Novu(apiKey);
- String subscriberId = "";
- String templateId = "";
+public static void main(String[] args) {
+String apiKey = "";
+Novu novu = new Novu(apiKey);
+String subscriberId = "";
+String templateId = "";
PreferenceChannel channel = new PreferenceChannel();
channel.setType("");
@@ -28,8 +28,10 @@ public class Main {
SingleSubscriberPrefResponse response = novu.updateSubscriberPreferences(request, subscriberId, templateId);
}
+
}
-```
+
+````
@@ -53,5 +55,6 @@ public class Main {
}
}
}
-```
+````
+
diff --git a/api-reference/subscribers/update-subscriber.mdx b/api-reference/subscribers/update-subscriber.mdx
index ffd28830..2b7b1bce 100644
--- a/api-reference/subscribers/update-subscriber.mdx
+++ b/api-reference/subscribers/update-subscriber.mdx
@@ -12,10 +12,10 @@ import co.novu.api.subscribers.responses.SingleSubscriberResponse;
import co.novu.api.subscribers.requests.UpdateSubscriberRequest;
public class Main {
- public static void main(String[] args) {
- String apiKey = "";
- Novu novu = new Novu(apiKey);
- String subscriberId = "";
+public static void main(String[] args) {
+String apiKey = "";
+Novu novu = new Novu(apiKey);
+String subscriberId = "";
UpdateSubscriberRequest updateSubscriberRequest = new UpdateSubscriberRequest();
updateSubscriberRequest.setEmail("");
@@ -26,8 +26,10 @@ public class Main {
SingleSubscriberResponse response = novu.updateSubscriber(updateSubscriberRequest, subscriberId);
}
+
}
-```
+
+````
```json Response
@@ -65,5 +67,6 @@ public class Main {
"updatedAt": "string"
}
}
-```
-
\ No newline at end of file
+````
+
+
diff --git a/api-reference/tenants/create-tenant.mdx b/api-reference/tenants/create-tenant.mdx
index 68fa74b0..188a77bb 100644
--- a/api-reference/tenants/create-tenant.mdx
+++ b/api-reference/tenants/create-tenant.mdx
@@ -4,4 +4,4 @@ openapi: post /v1/tenants
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/tenants/delete-tenant.mdx b/api-reference/tenants/delete-tenant.mdx
index 4b2dbcf0..503840a3 100644
--- a/api-reference/tenants/delete-tenant.mdx
+++ b/api-reference/tenants/delete-tenant.mdx
@@ -4,4 +4,4 @@ openapi: delete /v1/tenants/{identifier}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/tenants/get-tenant.mdx b/api-reference/tenants/get-tenant.mdx
index 703c578a..edb80a30 100644
--- a/api-reference/tenants/get-tenant.mdx
+++ b/api-reference/tenants/get-tenant.mdx
@@ -4,4 +4,4 @@ openapi: get /v1/tenants/{identifier}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/tenants/get-tenants.mdx b/api-reference/tenants/get-tenants.mdx
index e2b285da..d580d965 100644
--- a/api-reference/tenants/get-tenants.mdx
+++ b/api-reference/tenants/get-tenants.mdx
@@ -4,4 +4,4 @@ openapi: get /v1/tenants
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/tenants/update-tenant.mdx b/api-reference/tenants/update-tenant.mdx
index 3f4f1b1e..a0b2e776 100644
--- a/api-reference/tenants/update-tenant.mdx
+++ b/api-reference/tenants/update-tenant.mdx
@@ -4,4 +4,4 @@ openapi: patch /v1/tenants/{identifier}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/topics/check-topic-subscriber.mdx b/api-reference/topics/check-topic-subscriber.mdx
index c66c01e0..fc232046 100644
--- a/api-reference/topics/check-topic-subscriber.mdx
+++ b/api-reference/topics/check-topic-subscriber.mdx
@@ -4,4 +4,4 @@ openapi: get /v1/topics/{topicKey}/subscribers/{externalSubscriberId}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/topics/delete-topic.mdx b/api-reference/topics/delete-topic.mdx
index 707c7b2d..a2558b9b 100644
--- a/api-reference/topics/delete-topic.mdx
+++ b/api-reference/topics/delete-topic.mdx
@@ -4,4 +4,4 @@ openapi: delete /v1/topics/{topicKey}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/topics/filter-topics.mdx b/api-reference/topics/filter-topics.mdx
index 848c32d9..cf1ec474 100644
--- a/api-reference/topics/filter-topics.mdx
+++ b/api-reference/topics/filter-topics.mdx
@@ -4,4 +4,4 @@ openapi: get /v1/topics
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/topics/get-topic.mdx b/api-reference/topics/get-topic.mdx
index b33fb38d..b4e996c7 100644
--- a/api-reference/topics/get-topic.mdx
+++ b/api-reference/topics/get-topic.mdx
@@ -4,4 +4,4 @@ openapi: get /v1/topics/{topicKey}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/topics/rename-a-topic.mdx b/api-reference/topics/rename-a-topic.mdx
index 17c4dfde..b4d0c787 100644
--- a/api-reference/topics/rename-a-topic.mdx
+++ b/api-reference/topics/rename-a-topic.mdx
@@ -4,4 +4,4 @@ openapi: patch /v1/topics/{topicKey}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/topics/subscribers-addition.mdx b/api-reference/topics/subscribers-addition.mdx
index bb9fab1d..f9c8f51e 100644
--- a/api-reference/topics/subscribers-addition.mdx
+++ b/api-reference/topics/subscribers-addition.mdx
@@ -4,4 +4,4 @@ openapi: post /v1/topics/{topicKey}/subscribers
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/topics/subscribers-removal.mdx b/api-reference/topics/subscribers-removal.mdx
index d3ba7519..9594cbe2 100644
--- a/api-reference/topics/subscribers-removal.mdx
+++ b/api-reference/topics/subscribers-removal.mdx
@@ -4,4 +4,4 @@ openapi: post /v1/topics/{topicKey}/subscribers/removal
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/topics/topic-creation.mdx b/api-reference/topics/topic-creation.mdx
index dc3f11da..160c9f15 100644
--- a/api-reference/topics/topic-creation.mdx
+++ b/api-reference/topics/topic-creation.mdx
@@ -4,4 +4,4 @@ openapi: post /v1/topics
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
\ No newline at end of file
+
diff --git a/api-reference/workflow-groups/create-workflow-group.mdx b/api-reference/workflow-groups/create-workflow-group.mdx
index 999642e9..392ae957 100644
--- a/api-reference/workflow-groups/create-workflow-group.mdx
+++ b/api-reference/workflow-groups/create-workflow-group.mdx
@@ -16,9 +16,14 @@ curl --request POST \
```
```javascript Node.js
-import { Novu, TemplateVariableTypeEnum, FilterPartTypeEnum, StepTypeEnum } from '@novu/node';
+import {
+ Novu,
+ TemplateVariableTypeEnum,
+ FilterPartTypeEnum,
+ StepTypeEnum,
+} from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.notificationGroups.create("Product Updates");
```
@@ -89,7 +94,7 @@ func main() {
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
-
+
```
@@ -108,4 +113,4 @@ func main() {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/workflow-groups/delete-workflow-group.mdx b/api-reference/workflow-groups/delete-workflow-group.mdx
index c96ae73e..0741804a 100644
--- a/api-reference/workflow-groups/delete-workflow-group.mdx
+++ b/api-reference/workflow-groups/delete-workflow-group.mdx
@@ -14,9 +14,14 @@ curl --request DELETE \
```
```javascript Node.js
-import { Novu, TemplateVariableTypeEnum, FilterPartTypeEnum, StepTypeEnum } from '@novu/node';
+import {
+ Novu,
+ TemplateVariableTypeEnum,
+ FilterPartTypeEnum,
+ StepTypeEnum,
+} from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.notificationGroups.delete("notificationGroupId");
```
@@ -42,7 +47,7 @@ $result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */ }
echo $result;
-
+
```
```ruby Ruby
@@ -63,7 +68,7 @@ request.add_field('Authorization', 'ApiKey REPLACE_WITH_API_KEY')
response = http.request(request)
puts response.body
-
+
```
```python Python
@@ -72,7 +77,7 @@ import requests
response = requests.delete('https://api.novu.co/v1/notification-groups/:id')
print(response.json())
-
+
```
```go Go
@@ -98,7 +103,7 @@ func main() {
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
-
+
```
@@ -114,4 +119,4 @@ func main() {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/workflow-groups/get-workflow-group.mdx b/api-reference/workflow-groups/get-workflow-group.mdx
index c53604dc..208f0a21 100644
--- a/api-reference/workflow-groups/get-workflow-group.mdx
+++ b/api-reference/workflow-groups/get-workflow-group.mdx
@@ -14,9 +14,14 @@ curl --request GET \
```
```javascript Node.js
-import { Novu, TemplateVariableTypeEnum, FilterPartTypeEnum, StepTypeEnum } from '@novu/node';
+import {
+ Novu,
+ TemplateVariableTypeEnum,
+ FilterPartTypeEnum,
+ StepTypeEnum,
+} from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.notificationGroups.getOne("notificationGroupId");
```
@@ -42,7 +47,7 @@ $result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */ }
echo $result;
-
+
```
```ruby Ruby
@@ -63,7 +68,7 @@ request.add_field('Authorization', 'ApiKey REPLACE_WITH_API_KEY')
response = http.request(request)
puts response.body
-
+
```
```python Python
@@ -72,7 +77,7 @@ import requests
response = requests.get('https://api.novu.co/v1/notification-groups/:id')
print(response.json())
-
+
```
```go Go
@@ -98,7 +103,7 @@ func main() {
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
-
+
```
@@ -117,4 +122,4 @@ func main() {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/workflow-groups/get-workflow-groups.mdx b/api-reference/workflow-groups/get-workflow-groups.mdx
index 4d16a991..61efb398 100644
--- a/api-reference/workflow-groups/get-workflow-groups.mdx
+++ b/api-reference/workflow-groups/get-workflow-groups.mdx
@@ -14,9 +14,14 @@ curl --request GET \
```
```javascript Node.js
-import { Novu, TemplateVariableTypeEnum, FilterPartTypeEnum, StepTypeEnum } from '@novu/node';
+import {
+ Novu,
+ TemplateVariableTypeEnum,
+ FilterPartTypeEnum,
+ StepTypeEnum,
+} from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.notificationGroups.get();
```
@@ -82,7 +87,7 @@ func main() {
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
-
+
```
@@ -103,4 +108,4 @@ func main() {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/workflow-groups/update-workflow-group.mdx b/api-reference/workflow-groups/update-workflow-group.mdx
index 2f8b1906..76f6e460 100644
--- a/api-reference/workflow-groups/update-workflow-group.mdx
+++ b/api-reference/workflow-groups/update-workflow-group.mdx
@@ -16,11 +16,18 @@ curl --request PATCH \
```
```javascript Node.js
-import { Novu, TemplateVariableTypeEnum, FilterPartTypeEnum, StepTypeEnum } from '@novu/node';
-
-const novu = new Novu('');
-
-await novu.notificationGroups.update("notificationGroupId", { name: "Changelog Updates"});
+import {
+ Novu,
+ TemplateVariableTypeEnum,
+ FilterPartTypeEnum,
+ StepTypeEnum,
+} from "@novu/node";
+
+const novu = new Novu("");
+
+await novu.notificationGroups.update("notificationGroupId", {
+ name: "Changelog Updates",
+});
```
```php PHP
@@ -44,7 +51,7 @@ $result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */ }
echo $result;
-
+
```
```ruby Ruby
@@ -65,7 +72,7 @@ request.add_field('Authorization', 'ApiKey REPLACE_WITH_API_KEY')
response = http.request(request)
puts response.body
-
+
```
```python Python
@@ -79,7 +86,7 @@ response = requests.patch('https://api.novu.co/v1/notification-groups/:id', json
})
print(response.json())
-
+
```
```java Java
@@ -136,4 +143,4 @@ func main() {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/workflow-overrides/delete-workflow-override.mdx b/api-reference/workflow-overrides/delete-workflow-override.mdx
index 3da0deb8..a0d9c37f 100644
--- a/api-reference/workflow-overrides/delete-workflow-override.mdx
+++ b/api-reference/workflow-overrides/delete-workflow-override.mdx
@@ -2,8 +2,6 @@
openapi: delete /v1/workflow-overrides/{overrideId}
---
-
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
diff --git a/api-reference/workflow-overrides/get-workflow-override-by-id.mdx b/api-reference/workflow-overrides/get-workflow-override-by-id.mdx
index 4c482403..ee223ebe 100644
--- a/api-reference/workflow-overrides/get-workflow-override-by-id.mdx
+++ b/api-reference/workflow-overrides/get-workflow-override-by-id.mdx
@@ -5,4 +5,3 @@ openapi: get /v1/workflow-overrides/{overrideId}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
diff --git a/api-reference/workflow-overrides/get-workflow-override.mdx b/api-reference/workflow-overrides/get-workflow-override.mdx
index f7084444..d4d0c6f0 100644
--- a/api-reference/workflow-overrides/get-workflow-override.mdx
+++ b/api-reference/workflow-overrides/get-workflow-override.mdx
@@ -5,4 +5,3 @@ openapi: get /v1/workflow-overrides/workflows/{workflowId}/tenants/{tenantId}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
diff --git a/api-reference/workflow-overrides/get-workflow-overrides.mdx b/api-reference/workflow-overrides/get-workflow-overrides.mdx
index ee22bcf0..c8813ff3 100644
--- a/api-reference/workflow-overrides/get-workflow-overrides.mdx
+++ b/api-reference/workflow-overrides/get-workflow-overrides.mdx
@@ -5,4 +5,3 @@ openapi: get /v1/workflow-overrides
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
diff --git a/api-reference/workflow-overrides/update-workflow-override-by-id.mdx b/api-reference/workflow-overrides/update-workflow-override-by-id.mdx
index 1729f433..15090d6d 100644
--- a/api-reference/workflow-overrides/update-workflow-override-by-id.mdx
+++ b/api-reference/workflow-overrides/update-workflow-override-by-id.mdx
@@ -5,4 +5,3 @@ openapi: put /v1/workflow-overrides/{overrideId}
import ApikeyWarning from "/snippets/apikey-warning.mdx";
-
diff --git a/api-reference/workflows/create-workflow.mdx b/api-reference/workflows/create-workflow.mdx
index 005bf6b5..a7fa47f4 100644
--- a/api-reference/workflows/create-workflow.mdx
+++ b/api-reference/workflows/create-workflow.mdx
@@ -21,12 +21,17 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```
```javascript Node.js
-import { Novu, TemplateVariableTypeEnum, FilterPartTypeEnum, StepTypeEnum } from '@novu/node';
+import {
+ Novu,
+ TemplateVariableTypeEnum,
+ FilterPartTypeEnum,
+ StepTypeEnum,
+} from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.notificationTemplates.create({
- name: 'Onboarding Workflow',
+ name: "Onboarding Workflow",
// taking first workflow group id
notificationGroupId: workflowGroupsData.data[0]._id,
steps: [
@@ -35,16 +40,16 @@ await novu.notificationTemplates.create({
active: true,
shouldStopOnFail: false,
// UUID is optional.
- uuid: '78ab8c72-46de-49e4-8464-257085960f9e',
- name: 'Chat',
+ uuid: "78ab8c72-46de-49e4-8464-257085960f9e",
+ name: "Chat",
filters: [
{
- value: 'AND',
+ value: "AND",
children: [
{
- field: '{{chatContent}}',
- value: 'flag',
- operator: 'NOT_IN',
+ field: "{{chatContent}}",
+ value: "flag",
+ operator: "NOT_IN",
// 'payload'
on: FilterPartTypeEnum.PAYLOAD,
},
@@ -55,22 +60,22 @@ await novu.notificationTemplates.create({
// 'chat'
type: StepTypeEnum.CHAT,
active: true,
- subject: '',
+ subject: "",
variables: [
{
- name: 'chatContent',
+ name: "chatContent",
// 'String'
type: TemplateVariableTypeEnum.STRING,
required: true,
- "defaultValue": "default message",
+ defaultValue: "default message",
},
],
- content: '{{chatContent}}',
- contentType: 'editor',
+ content: "{{chatContent}}",
+ contentType: "editor",
},
},
],
- description: 'Onboarding workflow to trigger after user sign up',
+ description: "Onboarding workflow to trigger after user sign up",
active: true,
draft: false,
critical: false,
@@ -107,7 +112,7 @@ body = {
'description' => 'description', # optional
'steps' => [ # optional
# insert all fields here
- ],
+ ],
'active' => true, # optional
'draft' => true, # optional
'critical' => true, # optional
@@ -211,9 +216,7 @@ class Main {
"push": true
},
"critical": true,
- "tags": [
- "string"
- ],
+ "tags": ["string"],
"steps": [
{
"_id": "string",
@@ -288,4 +291,5 @@ class Main {
}
}
```
-
\ No newline at end of file
+
+
diff --git a/api-reference/workflows/delete-workflow.mdx b/api-reference/workflows/delete-workflow.mdx
index 88ef656a..12b3c756 100644
--- a/api-reference/workflows/delete-workflow.mdx
+++ b/api-reference/workflows/delete-workflow.mdx
@@ -3,8 +3,8 @@ openapi: delete /v1/workflows/{workflowId}
---
---
-openapi: post /v1/workflows
----
+
+## openapi: post /v1/workflows
import ApikeyWarning from "/snippets/apikey-warning.mdx";
@@ -19,9 +19,14 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```
```javascript Node.js
-import { Novu, TemplateVariableTypeEnum, FilterPartTypeEnum, StepTypeEnum } from '@novu/node';
+import {
+ Novu,
+ TemplateVariableTypeEnum,
+ FilterPartTypeEnum,
+ StepTypeEnum,
+} from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.notificationTemplates.delete("workflowId");
```
@@ -109,8 +114,8 @@ class Main {
```json Response
{
- "data": true
+ "data": true
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/workflows/get-workflow.mdx b/api-reference/workflows/get-workflow.mdx
index d3b87586..4520f06d 100644
--- a/api-reference/workflows/get-workflow.mdx
+++ b/api-reference/workflows/get-workflow.mdx
@@ -15,9 +15,14 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```
```javascript Node.js
-import { Novu, TemplateVariableTypeEnum, FilterPartTypeEnum, StepTypeEnum } from '@novu/node';
+import {
+ Novu,
+ TemplateVariableTypeEnum,
+ FilterPartTypeEnum,
+ StepTypeEnum,
+} from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.notificationTemplates.getOne("workflowIdOrIdentifier");
```
@@ -104,102 +109,102 @@ class Main {
```json Response
{
- "data": {
- "preferenceSettings": {
- "email": true,
- "sms": true,
- "in_app": true,
- "chat": true,
- "push": true
- },
+ "data": {
+ "preferenceSettings": {
+ "email": true,
+ "sms": true,
+ "in_app": true,
+ "chat": true,
+ "push": true
+ },
+ "_id": "7u83d3123t3a9e261ba9934r8",
+ "name": "chat with Discord",
+ "active": true,
+ "draft": false,
+ "critical": true,
+ "isBlueprint": false,
+ "_notificationGroupId": "641eddefda8256b93f750e0b",
+ "tags": [],
+ "triggers": [
+ {
+ "type": "event",
+ "identifier": "chat-with-discord",
+ "variables": [
+ {
+ "name": "chatMsg",
+ "type": "String",
+ "_id": "7u83d3123t3a9e261ba9934r8",
+ "id": "7u83d3123t3a9e261ba9934r8"
+ }
+ ],
+ "reservedVariables": [],
+ "subscriberVariables": [],
"_id": "7u83d3123t3a9e261ba9934r8",
- "name": "chat with Discord",
+ "id": "7u83d3123t3a9e261ba9934r8"
+ }
+ ],
+ "steps": [
+ {
+ "metadata": {
+ "timed": {
+ "weekDays": [],
+ "monthDays": []
+ }
+ },
"active": true,
- "draft": false,
- "critical": true,
- "isBlueprint": false,
- "_notificationGroupId": "641eddefda8256b93f750e0b",
- "tags": [],
- "triggers": [
- {
- "type": "event",
- "identifier": "chat-with-discord",
- "variables": [
- {
- "name": "chatMsg",
- "type": "String",
- "_id": "7u83d3123t3a9e261ba9934r8",
- "id": "7u83d3123t3a9e261ba9934r8"
- }
- ],
- "reservedVariables": [],
- "subscriberVariables": [],
- "_id": "7u83d3123t3a9e261ba9934r8",
- "id": "7u83d3123t3a9e261ba9934r8"
- }
+ "shouldStopOnFail": false,
+ "uuid": "9799f1c9-0de2-4252-8921-01840a71a741",
+ "name": "Chat",
+ "filters": [
+ {
+ "children": [],
+ "_id": "7u83d3123t3a9e261ba99376e",
+ "id": "7u83d3123t3a9e261ba993999"
+ }
],
- "steps": [
+ "_templateId": "6533d389306c4d8cf7853557",
+ "_parentId": null,
+ "_id": "99u3d3123t3a9e261ba993r45",
+ "id": "90uid3123t3a9e261ba9978yu",
+ "template": {
+ "_id": "r567d3123t3a9e261ba9990as",
+ "type": "chat",
+ "active": true,
+ "subject": "",
+ "variables": [
{
- "metadata": {
- "timed": {
- "weekDays": [],
- "monthDays": []
- }
- },
- "active": true,
- "shouldStopOnFail": false,
- "uuid": "9799f1c9-0de2-4252-8921-01840a71a741",
- "name": "Chat",
- "filters": [
- {
- "children": [],
- "_id": "7u83d3123t3a9e261ba99376e",
- "id": "7u83d3123t3a9e261ba993999"
- }
- ],
- "_templateId": "6533d389306c4d8cf7853557",
- "_parentId": null,
- "_id": "99u3d3123t3a9e261ba993r45",
- "id": "90uid3123t3a9e261ba9978yu",
- "template": {
- "_id": "r567d3123t3a9e261ba9990as",
- "type": "chat",
- "active": true,
- "subject": "",
- "variables": [
- {
- "name": "chatMsg",
- "type": "String",
- "required": false,
- "_id": "2383d3123t3a9e261ba997878",
- "id": "8711d389306c4d8cf7859090"
- }
- ],
- "content": "{{chatMsg}}",
- "contentType": "editor",
- "_environmentId": "234edtyuda8256b93f7567f90",
- "_organizationId": "333tydefda8256b93f753yh6",
- "_creatorId": "63123ee5d9af70da9f6a2e4",
- "_feedId": null,
- "_layoutId": null,
- "deleted": false,
- "createdAt": "2023-10-21T13:35:05.825Z",
- "updatedAt": "2023-10-21T13:35:18.156Z",
- "__v": 0,
- "id": "7u83d3123t3a9e261ba9934r8"
- }
+ "name": "chatMsg",
+ "type": "String",
+ "required": false,
+ "_id": "2383d3123t3a9e261ba997878",
+ "id": "8711d389306c4d8cf7859090"
}
- ],
- "_environmentId": "234edtyuda8256b93f7567f90",
- "_organizationId": "333tydefda8256b93f753yh6",
- "_creatorId": "63123ee5d9af70da9f6a2e4",
- "deleted": false,
- "createdAt": "2023-10-21T13:34:48.130Z",
- "updatedAt": "2023-10-21T13:35:18.994Z",
- "__v": 0,
- "id": "7u83d3123t3a9e261ba9934r8"
- }
+ ],
+ "content": "{{chatMsg}}",
+ "contentType": "editor",
+ "_environmentId": "234edtyuda8256b93f7567f90",
+ "_organizationId": "333tydefda8256b93f753yh6",
+ "_creatorId": "63123ee5d9af70da9f6a2e4",
+ "_feedId": null,
+ "_layoutId": null,
+ "deleted": false,
+ "createdAt": "2023-10-21T13:35:05.825Z",
+ "updatedAt": "2023-10-21T13:35:18.156Z",
+ "__v": 0,
+ "id": "7u83d3123t3a9e261ba9934r8"
+ }
+ }
+ ],
+ "_environmentId": "234edtyuda8256b93f7567f90",
+ "_organizationId": "333tydefda8256b93f753yh6",
+ "_creatorId": "63123ee5d9af70da9f6a2e4",
+ "deleted": false,
+ "createdAt": "2023-10-21T13:34:48.130Z",
+ "updatedAt": "2023-10-21T13:35:18.994Z",
+ "__v": 0,
+ "id": "7u83d3123t3a9e261ba9934r8"
+ }
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/workflows/get-workflows.mdx b/api-reference/workflows/get-workflows.mdx
index 04a95cc4..8f874a23 100644
--- a/api-reference/workflows/get-workflows.mdx
+++ b/api-reference/workflows/get-workflows.mdx
@@ -15,13 +15,18 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```
```javascript Node.js
-import { Novu, TemplateVariableTypeEnum, FilterPartTypeEnum, StepTypeEnum } from '@novu/node';
+import {
+ Novu,
+ TemplateVariableTypeEnum,
+ FilterPartTypeEnum,
+ StepTypeEnum,
+} from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.notificationTemplates.getAll({
page: 0, // optional
- limit: 20 // optional
+ limit: 20, // optional
});
```
@@ -88,7 +93,7 @@ func main() {
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
-
+
```
```kotlin Kotlin
@@ -111,1030 +116,1030 @@ class Main {
```json Response
{
- "page": 0,
- "data": [
+ "page": 0,
+ "data": [
+ {
+ "_id": "64f07ea63f28d769494bd74a",
+ "name": "Chat with Novu",
+ "active": true,
+ "draft": false,
+ "critical": true,
+ "isBlueprint": false,
+ "_notificationGroupId": "641eddefda8256b93f750e0b",
+ "tags": [],
+ "triggers": [
{
- "_id": "64f07ea63f28d769494bd74a",
- "name": "Chat with Novu",
- "active": true,
- "draft": false,
- "critical": true,
- "isBlueprint": false,
- "_notificationGroupId": "641eddefda8256b93f750e0b",
- "tags": [],
- "triggers": [
- {
- "type": "event",
- "identifier": "sms-docs",
- "variables": [
- {
- "name": "payloadVar",
- "type": "String",
- "_id": "64f1df7a97770dc90cf8c951"
- }
- ],
- "subscriberVariables": [],
- "_id": "64f07ea63f28d769494bd74b",
- "reservedVariables": []
- }
- ],
- "steps": [
- {
- "active": true,
- "shouldStopOnFail": false,
- "uuid": "0c22b8e5-762f-49b3-b686-09edb2275e8d",
- "name": "Chat",
- "filters": [
- {
- "children": [],
- "_id": "64f1ddba1dde0257bca4352d"
- }
- ],
- "_templateId": "64f1ddba1dde0257bca4351d",
- "_parentId": null,
- "metadata": {
- "timed": {
- "weekDays": [],
- "monthDays": []
- }
- },
- "_id": "64f1ddba1dde0257bca4351d",
- "template": {
- "_id": "64f1ddba1dde0257bca4351d",
- "type": "chat"
- }
- }
- ],
- "preferenceSettings": {
- "email": true,
- "sms": true,
- "in_app": true,
- "chat": true,
- "push": true
- },
- "_environmentId": "641eddefda8256b93f750e07",
- "_organizationId": "641eddefda8256b93f750e01",
- "_creatorId": "641eddee5d9af70da9f6a2e4",
- "deleted": false,
- "createdAt": "2023-08-31T11:51:02.984Z",
- "updatedAt": "2023-09-01T12:56:26.881Z",
- "__v": 0,
- "notificationGroup": {
- "_id": "641eddefda8256b93f750e0b",
- "name": "General",
- "_organizationId": "641eddefda8256b93f750e01",
- "_environmentId": "641eddefda8256b93f750e07",
- "createdAt": "2023-03-25T11:41:35.279Z",
- "updatedAt": "2023-03-25T11:41:35.279Z",
- "__v": 0
- },
- "workflowIntegrationStatus": {
- "hasActiveIntegrations": true,
- "channels": {
- "in_app": {
- "hasActiveIntegrations": true
- },
- "email": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "sms": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "chat": {
- "hasActiveIntegrations": true
- },
- "push": {
- "hasActiveIntegrations": false
- }
- }
+ "type": "event",
+ "identifier": "sms-docs",
+ "variables": [
+ {
+ "name": "payloadVar",
+ "type": "String",
+ "_id": "64f1df7a97770dc90cf8c951"
}
- },
+ ],
+ "subscriberVariables": [],
+ "_id": "64f07ea63f28d769494bd74b",
+ "reservedVariables": []
+ }
+ ],
+ "steps": [
{
- "_id": "64f024843f28d7694946d097",
- "name": "in-app workflow",
- "active": true,
- "draft": false,
- "critical": true,
- "isBlueprint": false,
- "_notificationGroupId": "641eddefda8256b93f750e0b",
- "tags": [],
- "triggers": [
- {
- "type": "event",
- "identifier": "in-app-workflow",
- "variables": [
- {
- "name": "messageIdentifier",
- "type": "String",
- "_id": "64f02b28dd99c21f1e2d4ac7"
- }
- ],
- "subscriberVariables": [],
- "_id": "64f024843f28d7694946d098"
- }
- ],
- "steps": [
- {
- "active": true,
- "shouldStopOnFail": false,
- "uuid": "ba437658-522d-439f-94da-02426b42d616",
- "name": "In-App",
- "filters": [
- {
- "children": [],
- "_id": "64f02b1914b8a3ace6186985"
- }
- ],
- "_templateId": "64f02b1914b8a3ace618697a",
- "_parentId": null,
- "metadata": {
- "timed": {
- "weekDays": [],
- "monthDays": []
- }
- },
- "_id": "64f02b1914b8a3ace618697a",
- "template": {
- "_id": "64f02b1914b8a3ace618697a",
- "type": "in_app"
- }
- }
- ],
- "preferenceSettings": {
- "email": true,
- "sms": true,
- "in_app": true,
- "chat": true,
- "push": true
- },
- "_environmentId": "641eddefda8256b93f750e07",
- "_organizationId": "641eddefda8256b93f750e01",
- "_creatorId": "641eddee5d9af70da9f6a2e4",
- "deleted": false,
- "createdAt": "2023-08-31T05:26:28.637Z",
- "updatedAt": "2023-08-31T05:54:48.445Z",
- "__v": 0,
- "notificationGroup": {
- "_id": "641eddefda8256b93f750e0b",
- "name": "General",
- "_organizationId": "641eddefda8256b93f750e01",
- "_environmentId": "641eddefda8256b93f750e07",
- "createdAt": "2023-03-25T11:41:35.279Z",
- "updatedAt": "2023-03-25T11:41:35.279Z",
- "__v": 0
- },
- "workflowIntegrationStatus": {
- "hasActiveIntegrations": true,
- "channels": {
- "in_app": {
- "hasActiveIntegrations": true
- },
- "email": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "sms": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "chat": {
- "hasActiveIntegrations": true
- },
- "push": {
- "hasActiveIntegrations": false
- }
- }
+ "active": true,
+ "shouldStopOnFail": false,
+ "uuid": "0c22b8e5-762f-49b3-b686-09edb2275e8d",
+ "name": "Chat",
+ "filters": [
+ {
+ "children": [],
+ "_id": "64f1ddba1dde0257bca4352d"
}
- },
+ ],
+ "_templateId": "64f1ddba1dde0257bca4351d",
+ "_parentId": null,
+ "metadata": {
+ "timed": {
+ "weekDays": [],
+ "monthDays": []
+ }
+ },
+ "_id": "64f1ddba1dde0257bca4351d",
+ "template": {
+ "_id": "64f1ddba1dde0257bca4351d",
+ "type": "chat"
+ }
+ }
+ ],
+ "preferenceSettings": {
+ "email": true,
+ "sms": true,
+ "in_app": true,
+ "chat": true,
+ "push": true
+ },
+ "_environmentId": "641eddefda8256b93f750e07",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_creatorId": "641eddee5d9af70da9f6a2e4",
+ "deleted": false,
+ "createdAt": "2023-08-31T11:51:02.984Z",
+ "updatedAt": "2023-09-01T12:56:26.881Z",
+ "__v": 0,
+ "notificationGroup": {
+ "_id": "641eddefda8256b93f750e0b",
+ "name": "General",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_environmentId": "641eddefda8256b93f750e07",
+ "createdAt": "2023-03-25T11:41:35.279Z",
+ "updatedAt": "2023-03-25T11:41:35.279Z",
+ "__v": 0
+ },
+ "workflowIntegrationStatus": {
+ "hasActiveIntegrations": true,
+ "channels": {
+ "in_app": {
+ "hasActiveIntegrations": true
+ },
+ "email": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "sms": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "chat": {
+ "hasActiveIntegrations": true
+ },
+ "push": {
+ "hasActiveIntegrations": false
+ }
+ }
+ }
+ },
+ {
+ "_id": "64f024843f28d7694946d097",
+ "name": "in-app workflow",
+ "active": true,
+ "draft": false,
+ "critical": true,
+ "isBlueprint": false,
+ "_notificationGroupId": "641eddefda8256b93f750e0b",
+ "tags": [],
+ "triggers": [
{
- "_id": "64eec9583cd25fad61223897",
- "name": "Discord chat demo",
- "active": true,
- "draft": false,
- "critical": true,
- "isBlueprint": false,
- "_notificationGroupId": "641eddefda8256b93f750e0b",
- "tags": [],
- "triggers": [
- {
- "type": "event",
- "identifier": "discord-chat-demo",
- "variables": [
- {
- "name": "chatMsg",
- "type": "String",
- "_id": "64eed56c735c8d00d98d2a71"
- }
- ],
- "subscriberVariables": [],
- "_id": "64eec9583cd25fad61223898"
- }
- ],
- "steps": [
- {
- "active": true,
- "shouldStopOnFail": false,
- "uuid": "03bb2304-d18c-4dc1-ae5a-62fe2634e787",
- "name": "Chat",
- "filters": [
- {
- "children": [],
- "_id": "64eeca4faed841efdcaf95eb"
- }
- ],
- "_templateId": "64eeca4faed841efdcaf95e2",
- "_parentId": null,
- "metadata": {
- "timed": {
- "weekDays": [],
- "monthDays": []
- }
- },
- "_id": "64eeca4faed841efdcaf95e2",
- "template": {
- "_id": "64eeca4faed841efdcaf95e2",
- "type": "chat"
- }
- }
- ],
- "preferenceSettings": {
- "email": true,
- "sms": true,
- "in_app": true,
- "chat": true,
- "push": true
- },
- "_environmentId": "641eddefda8256b93f750e07",
- "_organizationId": "641eddefda8256b93f750e01",
- "_creatorId": "641eddee5d9af70da9f6a2e4",
- "deleted": false,
- "createdAt": "2023-08-30T04:45:12.419Z",
- "updatedAt": "2023-08-30T05:36:44.465Z",
- "__v": 0,
- "notificationGroup": {
- "_id": "641eddefda8256b93f750e0b",
- "name": "General",
- "_organizationId": "641eddefda8256b93f750e01",
- "_environmentId": "641eddefda8256b93f750e07",
- "createdAt": "2023-03-25T11:41:35.279Z",
- "updatedAt": "2023-03-25T11:41:35.279Z",
- "__v": 0
- },
- "workflowIntegrationStatus": {
- "hasActiveIntegrations": true,
- "channels": {
- "in_app": {
- "hasActiveIntegrations": true
- },
- "email": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "sms": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "chat": {
- "hasActiveIntegrations": true
- },
- "push": {
- "hasActiveIntegrations": false
- }
- }
+ "type": "event",
+ "identifier": "in-app-workflow",
+ "variables": [
+ {
+ "name": "messageIdentifier",
+ "type": "String",
+ "_id": "64f02b28dd99c21f1e2d4ac7"
}
- },
+ ],
+ "subscriberVariables": [],
+ "_id": "64f024843f28d7694946d098"
+ }
+ ],
+ "steps": [
{
- "_id": "64db9511c51d09cdd01ff086",
- "name": "testing from browser",
- "active": true,
- "draft": false,
- "critical": true,
- "isBlueprint": false,
- "_notificationGroupId": "641eddefda8256b93f750e0b",
- "tags": [],
- "triggers": [
- {
- "type": "event",
- "identifier": "testing-from-browser",
- "variables": [],
- "subscriberVariables": [],
- "_id": "64db9511c51d09cdd01ff087"
- }
- ],
- "steps": [
- {
- "active": true,
- "shouldStopOnFail": false,
- "uuid": "29a67140-4694-443b-b4e1-8111b399198a",
- "name": "testting browser",
- "filters": [
- {
- "children": [],
- "_id": "64db954a98ca413e3d6838a7"
- }
- ],
- "_templateId": "64db954a98ca413e3d68389d",
- "_parentId": null,
- "metadata": {
- "timed": {
- "weekDays": [],
- "monthDays": []
- }
- },
- "_id": "64db954a98ca413e3d68389d",
- "template": {
- "_id": "64db954a98ca413e3d68389d",
- "type": "in_app"
- }
- }
- ],
- "preferenceSettings": {
- "email": true,
- "sms": true,
- "in_app": true,
- "chat": true,
- "push": true
- },
- "_environmentId": "641eddefda8256b93f750e07",
- "_organizationId": "641eddefda8256b93f750e01",
- "_creatorId": "641eddee5d9af70da9f6a2e4",
- "deleted": false,
- "createdAt": "2023-08-15T15:09:05.828Z",
- "updatedAt": "2023-08-25T11:55:48.583Z",
- "__v": 0,
- "notificationGroup": {
- "_id": "641eddefda8256b93f750e0b",
- "name": "General",
- "_organizationId": "641eddefda8256b93f750e01",
- "_environmentId": "641eddefda8256b93f750e07",
- "createdAt": "2023-03-25T11:41:35.279Z",
- "updatedAt": "2023-03-25T11:41:35.279Z",
- "__v": 0
- },
- "workflowIntegrationStatus": {
- "hasActiveIntegrations": true,
- "channels": {
- "in_app": {
- "hasActiveIntegrations": true
- },
- "email": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "sms": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "chat": {
- "hasActiveIntegrations": true
- },
- "push": {
- "hasActiveIntegrations": false
- }
- }
+ "active": true,
+ "shouldStopOnFail": false,
+ "uuid": "ba437658-522d-439f-94da-02426b42d616",
+ "name": "In-App",
+ "filters": [
+ {
+ "children": [],
+ "_id": "64f02b1914b8a3ace6186985"
}
- },
+ ],
+ "_templateId": "64f02b1914b8a3ace618697a",
+ "_parentId": null,
+ "metadata": {
+ "timed": {
+ "weekDays": [],
+ "monthDays": []
+ }
+ },
+ "_id": "64f02b1914b8a3ace618697a",
+ "template": {
+ "_id": "64f02b1914b8a3ace618697a",
+ "type": "in_app"
+ }
+ }
+ ],
+ "preferenceSettings": {
+ "email": true,
+ "sms": true,
+ "in_app": true,
+ "chat": true,
+ "push": true
+ },
+ "_environmentId": "641eddefda8256b93f750e07",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_creatorId": "641eddee5d9af70da9f6a2e4",
+ "deleted": false,
+ "createdAt": "2023-08-31T05:26:28.637Z",
+ "updatedAt": "2023-08-31T05:54:48.445Z",
+ "__v": 0,
+ "notificationGroup": {
+ "_id": "641eddefda8256b93f750e0b",
+ "name": "General",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_environmentId": "641eddefda8256b93f750e07",
+ "createdAt": "2023-03-25T11:41:35.279Z",
+ "updatedAt": "2023-03-25T11:41:35.279Z",
+ "__v": 0
+ },
+ "workflowIntegrationStatus": {
+ "hasActiveIntegrations": true,
+ "channels": {
+ "in_app": {
+ "hasActiveIntegrations": true
+ },
+ "email": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "sms": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "chat": {
+ "hasActiveIntegrations": true
+ },
+ "push": {
+ "hasActiveIntegrations": false
+ }
+ }
+ }
+ },
+ {
+ "_id": "64eec9583cd25fad61223897",
+ "name": "Discord chat demo",
+ "active": true,
+ "draft": false,
+ "critical": true,
+ "isBlueprint": false,
+ "_notificationGroupId": "641eddefda8256b93f750e0b",
+ "tags": [],
+ "triggers": [
{
- "_id": "64c0e3b9ec5b16b5d790d55a",
- "name": "headless-demo",
- "active": true,
- "draft": false,
- "critical": true,
- "isBlueprint": false,
- "_notificationGroupId": "641eddefda8256b93f750e0b",
- "tags": [],
- "triggers": [
- {
- "type": "event",
- "identifier": "headless-demo",
- "variables": [
- {
- "name": "description",
- "type": "String",
- "_id": "64c0e3d2ec5b16b5d790d5f6"
- }
- ],
- "subscriberVariables": [],
- "_id": "64c0e3b9ec5b16b5d790d55b"
- }
- ],
- "steps": [
- {
- "active": true,
- "shouldStopOnFail": false,
- "uuid": "e0ba19d2-7833-4525-971c-4f40dd47e2ff",
- "name": "In-App",
- "filters": [
- {
- "children": [],
- "_id": "64c0e3d2ec5b16b5d790d5f5"
- }
- ],
- "_templateId": "64c0e3d2ec5b16b5d790d5ea",
- "_parentId": null,
- "metadata": {
- "timed": {
- "weekDays": [],
- "monthDays": []
- }
- },
- "_id": "64c0e3d2ec5b16b5d790d5ea",
- "template": {
- "_id": "64c0e3d2ec5b16b5d790d5ea",
- "type": "in_app"
- }
- }
- ],
- "preferenceSettings": {
- "email": true,
- "sms": true,
- "in_app": true,
- "chat": true,
- "push": true
- },
- "_environmentId": "641eddefda8256b93f750e07",
- "_organizationId": "641eddefda8256b93f750e01",
- "_creatorId": "641eddee5d9af70da9f6a2e4",
- "deleted": false,
- "createdAt": "2023-07-26T09:13:29.090Z",
- "updatedAt": "2023-07-26T09:13:54.856Z",
- "__v": 0,
- "notificationGroup": {
- "_id": "641eddefda8256b93f750e0b",
- "name": "General",
- "_organizationId": "641eddefda8256b93f750e01",
- "_environmentId": "641eddefda8256b93f750e07",
- "createdAt": "2023-03-25T11:41:35.279Z",
- "updatedAt": "2023-03-25T11:41:35.279Z",
- "__v": 0
- },
- "workflowIntegrationStatus": {
- "hasActiveIntegrations": true,
- "channels": {
- "in_app": {
- "hasActiveIntegrations": true
- },
- "email": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "sms": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "chat": {
- "hasActiveIntegrations": true
- },
- "push": {
- "hasActiveIntegrations": false
- }
- }
+ "type": "event",
+ "identifier": "discord-chat-demo",
+ "variables": [
+ {
+ "name": "chatMsg",
+ "type": "String",
+ "_id": "64eed56c735c8d00d98d2a71"
}
- },
+ ],
+ "subscriberVariables": [],
+ "_id": "64eec9583cd25fad61223898"
+ }
+ ],
+ "steps": [
{
- "_id": "64a41ffee2134f0077e0d222",
- "name": "emailDigestWorkflow",
- "active": true,
- "draft": false,
- "critical": false,
- "isBlueprint": false,
- "_notificationGroupId": "641eddefda8256b93f750e0b",
- "tags": [],
- "triggers": [
- {
- "type": "event",
- "identifier": "emaildigestworkflow",
- "variables": [],
- "subscriberVariables": [
- {
- "name": "email",
- "_id": "64b8f8c024a8ba51900fece6"
- }
- ],
- "_id": "64a41ffee2134f0077e0d223"
- }
- ],
- "steps": [
- {
- "active": true,
- "shouldStopOnFail": false,
- "uuid": "13b27589-a7ad-47e3-b10d-a1085dd3687d",
- "name": "Digest",
- "filters": [],
- "_templateId": "64a421ae5f8a9af84368c9fe",
- "_parentId": null,
- "metadata": {
- "amount": 20,
- "unit": "seconds",
- "type": "regular",
- "backoffAmount": null,
- "backoff": false,
- "timed": {
- "weekDays": [],
- "monthDays": []
- }
- },
- "_id": "64a421ae5f8a9af84368c9fe",
- "template": {
- "_id": "64a421ae5f8a9af84368c9fe",
- "type": "digest"
- }
- },
- {
- "active": true,
- "replyCallback": {
- "active": false
- },
- "shouldStopOnFail": false,
- "uuid": "4e1d8ebb-355c-4224-8a79-fcbc3c0233a1",
- "name": "Email",
- "filters": [
- {
- "children": [],
- "_id": "64a420215f8a9af84368b6b8"
- }
- ],
- "_templateId": "64a420215f8a9af84368b6a6",
- "_parentId": "64a421ae5f8a9af84368c9fe",
- "metadata": {
- "timed": {
- "weekDays": [],
- "monthDays": []
- }
- },
- "_id": "64a420215f8a9af84368b6a6",
- "template": {
- "_id": "64a420215f8a9af84368b6a6",
- "type": "email"
- }
- }
- ],
- "preferenceSettings": {
- "email": true,
- "sms": true,
- "in_app": true,
- "chat": true,
- "push": true
- },
- "_environmentId": "641eddefda8256b93f750e07",
- "_organizationId": "641eddefda8256b93f750e01",
- "_creatorId": "641eddee5d9af70da9f6a2e4",
- "deleted": false,
- "createdAt": "2023-07-04T13:34:54.781Z",
- "updatedAt": "2023-07-20T09:05:04.701Z",
- "__v": 0,
- "notificationGroup": {
- "_id": "641eddefda8256b93f750e0b",
- "name": "General",
- "_organizationId": "641eddefda8256b93f750e01",
- "_environmentId": "641eddefda8256b93f750e07",
- "createdAt": "2023-03-25T11:41:35.279Z",
- "updatedAt": "2023-03-25T11:41:35.279Z",
- "__v": 0
- },
- "workflowIntegrationStatus": {
- "hasActiveIntegrations": true,
- "channels": {
- "in_app": {
- "hasActiveIntegrations": true
- },
- "email": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "sms": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "chat": {
- "hasActiveIntegrations": true
- },
- "push": {
- "hasActiveIntegrations": false
- }
- }
+ "active": true,
+ "shouldStopOnFail": false,
+ "uuid": "03bb2304-d18c-4dc1-ae5a-62fe2634e787",
+ "name": "Chat",
+ "filters": [
+ {
+ "children": [],
+ "_id": "64eeca4faed841efdcaf95eb"
}
- },
+ ],
+ "_templateId": "64eeca4faed841efdcaf95e2",
+ "_parentId": null,
+ "metadata": {
+ "timed": {
+ "weekDays": [],
+ "monthDays": []
+ }
+ },
+ "_id": "64eeca4faed841efdcaf95e2",
+ "template": {
+ "_id": "64eeca4faed841efdcaf95e2",
+ "type": "chat"
+ }
+ }
+ ],
+ "preferenceSettings": {
+ "email": true,
+ "sms": true,
+ "in_app": true,
+ "chat": true,
+ "push": true
+ },
+ "_environmentId": "641eddefda8256b93f750e07",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_creatorId": "641eddee5d9af70da9f6a2e4",
+ "deleted": false,
+ "createdAt": "2023-08-30T04:45:12.419Z",
+ "updatedAt": "2023-08-30T05:36:44.465Z",
+ "__v": 0,
+ "notificationGroup": {
+ "_id": "641eddefda8256b93f750e0b",
+ "name": "General",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_environmentId": "641eddefda8256b93f750e07",
+ "createdAt": "2023-03-25T11:41:35.279Z",
+ "updatedAt": "2023-03-25T11:41:35.279Z",
+ "__v": 0
+ },
+ "workflowIntegrationStatus": {
+ "hasActiveIntegrations": true,
+ "channels": {
+ "in_app": {
+ "hasActiveIntegrations": true
+ },
+ "email": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "sms": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "chat": {
+ "hasActiveIntegrations": true
+ },
+ "push": {
+ "hasActiveIntegrations": false
+ }
+ }
+ }
+ },
+ {
+ "_id": "64db9511c51d09cdd01ff086",
+ "name": "testing from browser",
+ "active": true,
+ "draft": false,
+ "critical": true,
+ "isBlueprint": false,
+ "_notificationGroupId": "641eddefda8256b93f750e0b",
+ "tags": [],
+ "triggers": [
{
- "_id": "6492d92f616db8f05a982022",
- "name": "digest showcase",
- "active": true,
- "draft": false,
- "critical": true,
- "isBlueprint": false,
- "_notificationGroupId": "641eddefda8256b93f750e0b",
- "tags": [],
- "triggers": [
- {
- "type": "event",
- "identifier": "digest-showcase",
- "variables": [],
- "subscriberVariables": [],
- "_id": "6492d92f616db8f05a982023"
- }
- ],
- "steps": [
- {
- "active": true,
- "shouldStopOnFail": false,
- "uuid": "556f0514-01b6-46f9-9e3d-72a4c060af54",
- "name": "Digest",
- "filters": [],
- "_templateId": "6492d9735da9bfaf640771a2",
- "_parentId": null,
- "metadata": {
- "amount": 10,
- "unit": "seconds",
- "type": "regular",
- "backoffAmount": null,
- "backoff": false,
- "timed": {
- "weekDays": [],
- "monthDays": []
- }
- },
- "_id": "6492d9735da9bfaf640771a2",
- "template": {
- "_id": "6492d9735da9bfaf640771a2",
- "type": "digest"
- }
- },
- {
- "active": true,
- "shouldStopOnFail": false,
- "uuid": "024a27f4-82da-485c-b4a7-bea05c2631e3",
- "name": "In-App",
- "filters": [
- {
- "children": [],
- "_id": "6492d9735da9bfaf640771b6"
- }
- ],
- "_templateId": "6492d9735da9bfaf640771aa",
- "_parentId": "6492d9735da9bfaf640771a2",
- "metadata": {
- "timed": {
- "weekDays": [],
- "monthDays": []
- }
- },
- "_id": "6492d9735da9bfaf640771aa",
- "template": {
- "_id": "6492d9735da9bfaf640771aa",
- "type": "in_app"
- }
- }
- ],
- "preferenceSettings": {
- "email": true,
- "sms": true,
- "in_app": true,
- "chat": true,
- "push": true
- },
- "_environmentId": "641eddefda8256b93f750e07",
- "_organizationId": "641eddefda8256b93f750e01",
- "_creatorId": "641eddee5d9af70da9f6a2e4",
- "deleted": false,
- "createdAt": "2023-06-21T11:04:15.546Z",
- "updatedAt": "2023-07-19T13:32:18.474Z",
- "__v": 0,
- "notificationGroup": {
- "_id": "641eddefda8256b93f750e0b",
- "name": "General",
- "_organizationId": "641eddefda8256b93f750e01",
- "_environmentId": "641eddefda8256b93f750e07",
- "createdAt": "2023-03-25T11:41:35.279Z",
- "updatedAt": "2023-03-25T11:41:35.279Z",
- "__v": 0
- },
- "workflowIntegrationStatus": {
- "hasActiveIntegrations": true,
- "channels": {
- "in_app": {
- "hasActiveIntegrations": true
- },
- "email": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "sms": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "chat": {
- "hasActiveIntegrations": true
- },
- "push": {
- "hasActiveIntegrations": false
- }
- }
+ "type": "event",
+ "identifier": "testing-from-browser",
+ "variables": [],
+ "subscriberVariables": [],
+ "_id": "64db9511c51d09cdd01ff087"
+ }
+ ],
+ "steps": [
+ {
+ "active": true,
+ "shouldStopOnFail": false,
+ "uuid": "29a67140-4694-443b-b4e1-8111b399198a",
+ "name": "testting browser",
+ "filters": [
+ {
+ "children": [],
+ "_id": "64db954a98ca413e3d6838a7"
}
- },
+ ],
+ "_templateId": "64db954a98ca413e3d68389d",
+ "_parentId": null,
+ "metadata": {
+ "timed": {
+ "weekDays": [],
+ "monthDays": []
+ }
+ },
+ "_id": "64db954a98ca413e3d68389d",
+ "template": {
+ "_id": "64db954a98ca413e3d68389d",
+ "type": "in_app"
+ }
+ }
+ ],
+ "preferenceSettings": {
+ "email": true,
+ "sms": true,
+ "in_app": true,
+ "chat": true,
+ "push": true
+ },
+ "_environmentId": "641eddefda8256b93f750e07",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_creatorId": "641eddee5d9af70da9f6a2e4",
+ "deleted": false,
+ "createdAt": "2023-08-15T15:09:05.828Z",
+ "updatedAt": "2023-08-25T11:55:48.583Z",
+ "__v": 0,
+ "notificationGroup": {
+ "_id": "641eddefda8256b93f750e0b",
+ "name": "General",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_environmentId": "641eddefda8256b93f750e07",
+ "createdAt": "2023-03-25T11:41:35.279Z",
+ "updatedAt": "2023-03-25T11:41:35.279Z",
+ "__v": 0
+ },
+ "workflowIntegrationStatus": {
+ "hasActiveIntegrations": true,
+ "channels": {
+ "in_app": {
+ "hasActiveIntegrations": true
+ },
+ "email": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "sms": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "chat": {
+ "hasActiveIntegrations": true
+ },
+ "push": {
+ "hasActiveIntegrations": false
+ }
+ }
+ }
+ },
+ {
+ "_id": "64c0e3b9ec5b16b5d790d55a",
+ "name": "headless-demo",
+ "active": true,
+ "draft": false,
+ "critical": true,
+ "isBlueprint": false,
+ "_notificationGroupId": "641eddefda8256b93f750e0b",
+ "tags": [],
+ "triggers": [
{
- "_id": "6471aa6f3a4ec8a599669991",
- "name": "quickstart",
- "active": true,
- "draft": false,
- "critical": false,
- "isBlueprint": false,
- "_notificationGroupId": "641eddefda8256b93f750e0b",
- "tags": [],
- "triggers": [
- {
- "type": "event",
- "identifier": "quickstart",
- "variables": [
- {
- "name": "description",
- "type": "String",
- "_id": "6471aaa08b0b51ed173ba8fd"
- }
- ],
- "subscriberVariables": [],
- "_id": "6471aa6f3a4ec8a599669992"
- }
- ],
- "steps": [
- {
- "active": true,
- "shouldStopOnFail": false,
- "uuid": "982bf6a1-6f0c-46c6-a8ad-6daa67f327e2",
- "name": "In-App",
- "filters": [
- {
- "children": [],
- "_id": "6471aa85720b54f89ed97de3"
- }
- ],
- "_templateId": "6471aa85720b54f89ed97dd8",
- "_parentId": null,
- "metadata": {
- "timed": {
- "weekDays": [],
- "monthDays": []
- }
- },
- "_id": "6471aa85720b54f89ed97dd8",
- "template": {
- "_id": "6471aa85720b54f89ed97dd8",
- "type": "in_app"
- }
- }
- ],
- "preferenceSettings": {
- "email": true,
- "sms": true,
- "in_app": true,
- "chat": true,
- "push": true
- },
- "_environmentId": "641eddefda8256b93f750e07",
- "_organizationId": "641eddefda8256b93f750e01",
- "_creatorId": "641eddee5d9af70da9f6a2e4",
- "deleted": false,
- "createdAt": "2023-05-27T06:59:59.254Z",
- "updatedAt": "2023-05-27T07:00:48.618Z",
- "__v": 0,
- "notificationGroup": {
- "_id": "641eddefda8256b93f750e0b",
- "name": "General",
- "_organizationId": "641eddefda8256b93f750e01",
- "_environmentId": "641eddefda8256b93f750e07",
- "createdAt": "2023-03-25T11:41:35.279Z",
- "updatedAt": "2023-03-25T11:41:35.279Z",
- "__v": 0
- },
- "workflowIntegrationStatus": {
- "hasActiveIntegrations": true,
- "channels": {
- "in_app": {
- "hasActiveIntegrations": true
- },
- "email": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "sms": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "chat": {
- "hasActiveIntegrations": true
- },
- "push": {
- "hasActiveIntegrations": false
- }
- }
+ "type": "event",
+ "identifier": "headless-demo",
+ "variables": [
+ {
+ "name": "description",
+ "type": "String",
+ "_id": "64c0e3d2ec5b16b5d790d5f6"
+ }
+ ],
+ "subscriberVariables": [],
+ "_id": "64c0e3b9ec5b16b5d790d55b"
+ }
+ ],
+ "steps": [
+ {
+ "active": true,
+ "shouldStopOnFail": false,
+ "uuid": "e0ba19d2-7833-4525-971c-4f40dd47e2ff",
+ "name": "In-App",
+ "filters": [
+ {
+ "children": [],
+ "_id": "64c0e3d2ec5b16b5d790d5f5"
+ }
+ ],
+ "_templateId": "64c0e3d2ec5b16b5d790d5ea",
+ "_parentId": null,
+ "metadata": {
+ "timed": {
+ "weekDays": [],
+ "monthDays": []
}
+ },
+ "_id": "64c0e3d2ec5b16b5d790d5ea",
+ "template": {
+ "_id": "64c0e3d2ec5b16b5d790d5ea",
+ "type": "in_app"
+ }
+ }
+ ],
+ "preferenceSettings": {
+ "email": true,
+ "sms": true,
+ "in_app": true,
+ "chat": true,
+ "push": true
+ },
+ "_environmentId": "641eddefda8256b93f750e07",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_creatorId": "641eddee5d9af70da9f6a2e4",
+ "deleted": false,
+ "createdAt": "2023-07-26T09:13:29.090Z",
+ "updatedAt": "2023-07-26T09:13:54.856Z",
+ "__v": 0,
+ "notificationGroup": {
+ "_id": "641eddefda8256b93f750e0b",
+ "name": "General",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_environmentId": "641eddefda8256b93f750e07",
+ "createdAt": "2023-03-25T11:41:35.279Z",
+ "updatedAt": "2023-03-25T11:41:35.279Z",
+ "__v": 0
+ },
+ "workflowIntegrationStatus": {
+ "hasActiveIntegrations": true,
+ "channels": {
+ "in_app": {
+ "hasActiveIntegrations": true
+ },
+ "email": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "sms": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "chat": {
+ "hasActiveIntegrations": true
+ },
+ "push": {
+ "hasActiveIntegrations": false
+ }
+ }
+ }
+ },
+ {
+ "_id": "64a41ffee2134f0077e0d222",
+ "name": "emailDigestWorkflow",
+ "active": true,
+ "draft": false,
+ "critical": false,
+ "isBlueprint": false,
+ "_notificationGroupId": "641eddefda8256b93f750e0b",
+ "tags": [],
+ "triggers": [
+ {
+ "type": "event",
+ "identifier": "emaildigestworkflow",
+ "variables": [],
+ "subscriberVariables": [
+ {
+ "name": "email",
+ "_id": "64b8f8c024a8ba51900fece6"
+ }
+ ],
+ "_id": "64a41ffee2134f0077e0d223"
+ }
+ ],
+ "steps": [
+ {
+ "active": true,
+ "shouldStopOnFail": false,
+ "uuid": "13b27589-a7ad-47e3-b10d-a1085dd3687d",
+ "name": "Digest",
+ "filters": [],
+ "_templateId": "64a421ae5f8a9af84368c9fe",
+ "_parentId": null,
+ "metadata": {
+ "amount": 20,
+ "unit": "seconds",
+ "type": "regular",
+ "backoffAmount": null,
+ "backoff": false,
+ "timed": {
+ "weekDays": [],
+ "monthDays": []
+ }
+ },
+ "_id": "64a421ae5f8a9af84368c9fe",
+ "template": {
+ "_id": "64a421ae5f8a9af84368c9fe",
+ "type": "digest"
+ }
},
{
- "_id": "6469fc87301d88d6d2b74741",
- "name": "Email quickstart",
- "active": true,
- "draft": false,
- "critical": false,
- "isBlueprint": false,
- "_notificationGroupId": "641eddefda8256b93f750e0b",
- "tags": [],
- "triggers": [
- {
- "type": "event",
- "identifier": "email-quickstart",
- "variables": [
- {
- "name": "email",
- "type": "String",
- "_id": "646a031c25b1fb30f274ac35"
- },
- {
- "name": "description",
- "type": "String",
- "_id": "646a031c25b1fb30f274ac36"
- }
- ],
- "subscriberVariables": [
- {
- "name": "email",
- "_id": "646a031c25b1fb30f274ac34"
- }
- ],
- "_id": "6469fc87301d88d6d2b74742"
- }
- ],
- "steps": [
- {
- "active": true,
- "replyCallback": {
- "active": false
- },
- "shouldStopOnFail": false,
- "uuid": "3b512084-6cba-400c-8644-d9e9bff6bbfc",
- "name": "Email",
- "filters": [
- {
- "children": [],
- "_id": "6469fd9bc2c5b74546b2cc80"
- }
- ],
- "_templateId": "6469fd9bc2c5b74546b2cc76",
- "_parentId": null,
- "metadata": {
- "timed": {
- "weekDays": [],
- "monthDays": []
- }
- },
- "_id": "6469fd9bc2c5b74546b2cc76",
- "template": {
- "_id": "6469fd9bc2c5b74546b2cc76",
- "type": "email"
- }
- }
- ],
- "preferenceSettings": {
- "email": true,
- "sms": true,
- "in_app": true,
- "chat": true,
- "push": true
- },
- "_environmentId": "641eddefda8256b93f750e07",
- "_organizationId": "641eddefda8256b93f750e01",
- "_creatorId": "641eddee5d9af70da9f6a2e4",
- "deleted": false,
- "createdAt": "2023-05-21T11:12:07.036Z",
- "updatedAt": "2023-05-21T11:40:12.955Z",
- "__v": 0,
- "notificationGroup": {
- "_id": "641eddefda8256b93f750e0b",
- "name": "General",
- "_organizationId": "641eddefda8256b93f750e01",
- "_environmentId": "641eddefda8256b93f750e07",
- "createdAt": "2023-03-25T11:41:35.279Z",
- "updatedAt": "2023-03-25T11:41:35.279Z",
- "__v": 0
- },
- "workflowIntegrationStatus": {
- "hasActiveIntegrations": true,
- "channels": {
- "in_app": {
- "hasActiveIntegrations": true
- },
- "email": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "sms": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "chat": {
- "hasActiveIntegrations": true
- },
- "push": {
- "hasActiveIntegrations": false
- }
- }
+ "active": true,
+ "replyCallback": {
+ "active": false
+ },
+ "shouldStopOnFail": false,
+ "uuid": "4e1d8ebb-355c-4224-8a79-fcbc3c0233a1",
+ "name": "Email",
+ "filters": [
+ {
+ "children": [],
+ "_id": "64a420215f8a9af84368b6b8"
+ }
+ ],
+ "_templateId": "64a420215f8a9af84368b6a6",
+ "_parentId": "64a421ae5f8a9af84368c9fe",
+ "metadata": {
+ "timed": {
+ "weekDays": [],
+ "monthDays": []
+ }
+ },
+ "_id": "64a420215f8a9af84368b6a6",
+ "template": {
+ "_id": "64a420215f8a9af84368b6a6",
+ "type": "email"
+ }
+ }
+ ],
+ "preferenceSettings": {
+ "email": true,
+ "sms": true,
+ "in_app": true,
+ "chat": true,
+ "push": true
+ },
+ "_environmentId": "641eddefda8256b93f750e07",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_creatorId": "641eddee5d9af70da9f6a2e4",
+ "deleted": false,
+ "createdAt": "2023-07-04T13:34:54.781Z",
+ "updatedAt": "2023-07-20T09:05:04.701Z",
+ "__v": 0,
+ "notificationGroup": {
+ "_id": "641eddefda8256b93f750e0b",
+ "name": "General",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_environmentId": "641eddefda8256b93f750e07",
+ "createdAt": "2023-03-25T11:41:35.279Z",
+ "updatedAt": "2023-03-25T11:41:35.279Z",
+ "__v": 0
+ },
+ "workflowIntegrationStatus": {
+ "hasActiveIntegrations": true,
+ "channels": {
+ "in_app": {
+ "hasActiveIntegrations": true
+ },
+ "email": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "sms": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "chat": {
+ "hasActiveIntegrations": true
+ },
+ "push": {
+ "hasActiveIntegrations": false
+ }
+ }
+ }
+ },
+ {
+ "_id": "6492d92f616db8f05a982022",
+ "name": "digest showcase",
+ "active": true,
+ "draft": false,
+ "critical": true,
+ "isBlueprint": false,
+ "_notificationGroupId": "641eddefda8256b93f750e0b",
+ "tags": [],
+ "triggers": [
+ {
+ "type": "event",
+ "identifier": "digest-showcase",
+ "variables": [],
+ "subscriberVariables": [],
+ "_id": "6492d92f616db8f05a982023"
+ }
+ ],
+ "steps": [
+ {
+ "active": true,
+ "shouldStopOnFail": false,
+ "uuid": "556f0514-01b6-46f9-9e3d-72a4c060af54",
+ "name": "Digest",
+ "filters": [],
+ "_templateId": "6492d9735da9bfaf640771a2",
+ "_parentId": null,
+ "metadata": {
+ "amount": 10,
+ "unit": "seconds",
+ "type": "regular",
+ "backoffAmount": null,
+ "backoff": false,
+ "timed": {
+ "weekDays": [],
+ "monthDays": []
}
+ },
+ "_id": "6492d9735da9bfaf640771a2",
+ "template": {
+ "_id": "6492d9735da9bfaf640771a2",
+ "type": "digest"
+ }
},
{
- "_id": "6450b033631887e5f013f0df",
- "name": "notif-genenerator",
- "active": true,
- "draft": false,
- "critical": false,
- "isBlueprint": false,
- "_notificationGroupId": "641eddefda8256b93f750e0b",
- "tags": [],
- "triggers": [
- {
- "type": "event",
- "identifier": "notif-genenerator",
- "variables": [
- {
- "name": "description",
- "type": "String",
- "_id": "645a5b18e1a93324256bdf59"
- }
- ],
- "subscriberVariables": [],
- "_id": "6450b033631887e5f013f0e0"
- }
- ],
- "steps": [
- {
- "active": true,
- "shouldStopOnFail": false,
- "uuid": "0486c699-2db4-4868-9ed5-c407acacb728",
- "name": "In-App",
- "filters": [
- {
- "children": [],
- "_id": "6450b06e9c851c56f803d489"
- }
- ],
- "_templateId": "6450b06e9c851c56f803d47e",
- "_parentId": null,
- "_id": "6450b06e9c851c56f803d47e",
- "template": {
- "_id": "6450b06e9c851c56f803d47e",
- "type": "in_app"
- }
- }
- ],
- "preferenceSettings": {
- "email": true,
- "sms": true,
- "in_app": true,
- "chat": true,
- "push": true
- },
- "_environmentId": "641eddefda8256b93f750e07",
- "_organizationId": "641eddefda8256b93f750e01",
- "_creatorId": "641eddee5d9af70da9f6a2e4",
- "deleted": false,
- "createdAt": "2023-05-02T06:39:47.699Z",
- "updatedAt": "2023-05-09T14:39:20.811Z",
- "__v": 0,
- "notificationGroup": {
- "_id": "641eddefda8256b93f750e0b",
- "name": "General",
- "_organizationId": "641eddefda8256b93f750e01",
- "_environmentId": "641eddefda8256b93f750e07",
- "createdAt": "2023-03-25T11:41:35.279Z",
- "updatedAt": "2023-03-25T11:41:35.279Z",
- "__v": 0
+ "active": true,
+ "shouldStopOnFail": false,
+ "uuid": "024a27f4-82da-485c-b4a7-bea05c2631e3",
+ "name": "In-App",
+ "filters": [
+ {
+ "children": [],
+ "_id": "6492d9735da9bfaf640771b6"
+ }
+ ],
+ "_templateId": "6492d9735da9bfaf640771aa",
+ "_parentId": "6492d9735da9bfaf640771a2",
+ "metadata": {
+ "timed": {
+ "weekDays": [],
+ "monthDays": []
+ }
+ },
+ "_id": "6492d9735da9bfaf640771aa",
+ "template": {
+ "_id": "6492d9735da9bfaf640771aa",
+ "type": "in_app"
+ }
+ }
+ ],
+ "preferenceSettings": {
+ "email": true,
+ "sms": true,
+ "in_app": true,
+ "chat": true,
+ "push": true
+ },
+ "_environmentId": "641eddefda8256b93f750e07",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_creatorId": "641eddee5d9af70da9f6a2e4",
+ "deleted": false,
+ "createdAt": "2023-06-21T11:04:15.546Z",
+ "updatedAt": "2023-07-19T13:32:18.474Z",
+ "__v": 0,
+ "notificationGroup": {
+ "_id": "641eddefda8256b93f750e0b",
+ "name": "General",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_environmentId": "641eddefda8256b93f750e07",
+ "createdAt": "2023-03-25T11:41:35.279Z",
+ "updatedAt": "2023-03-25T11:41:35.279Z",
+ "__v": 0
+ },
+ "workflowIntegrationStatus": {
+ "hasActiveIntegrations": true,
+ "channels": {
+ "in_app": {
+ "hasActiveIntegrations": true
+ },
+ "email": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "sms": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "chat": {
+ "hasActiveIntegrations": true
+ },
+ "push": {
+ "hasActiveIntegrations": false
+ }
+ }
+ }
+ },
+ {
+ "_id": "6471aa6f3a4ec8a599669991",
+ "name": "quickstart",
+ "active": true,
+ "draft": false,
+ "critical": false,
+ "isBlueprint": false,
+ "_notificationGroupId": "641eddefda8256b93f750e0b",
+ "tags": [],
+ "triggers": [
+ {
+ "type": "event",
+ "identifier": "quickstart",
+ "variables": [
+ {
+ "name": "description",
+ "type": "String",
+ "_id": "6471aaa08b0b51ed173ba8fd"
+ }
+ ],
+ "subscriberVariables": [],
+ "_id": "6471aa6f3a4ec8a599669992"
+ }
+ ],
+ "steps": [
+ {
+ "active": true,
+ "shouldStopOnFail": false,
+ "uuid": "982bf6a1-6f0c-46c6-a8ad-6daa67f327e2",
+ "name": "In-App",
+ "filters": [
+ {
+ "children": [],
+ "_id": "6471aa85720b54f89ed97de3"
+ }
+ ],
+ "_templateId": "6471aa85720b54f89ed97dd8",
+ "_parentId": null,
+ "metadata": {
+ "timed": {
+ "weekDays": [],
+ "monthDays": []
+ }
+ },
+ "_id": "6471aa85720b54f89ed97dd8",
+ "template": {
+ "_id": "6471aa85720b54f89ed97dd8",
+ "type": "in_app"
+ }
+ }
+ ],
+ "preferenceSettings": {
+ "email": true,
+ "sms": true,
+ "in_app": true,
+ "chat": true,
+ "push": true
+ },
+ "_environmentId": "641eddefda8256b93f750e07",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_creatorId": "641eddee5d9af70da9f6a2e4",
+ "deleted": false,
+ "createdAt": "2023-05-27T06:59:59.254Z",
+ "updatedAt": "2023-05-27T07:00:48.618Z",
+ "__v": 0,
+ "notificationGroup": {
+ "_id": "641eddefda8256b93f750e0b",
+ "name": "General",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_environmentId": "641eddefda8256b93f750e07",
+ "createdAt": "2023-03-25T11:41:35.279Z",
+ "updatedAt": "2023-03-25T11:41:35.279Z",
+ "__v": 0
+ },
+ "workflowIntegrationStatus": {
+ "hasActiveIntegrations": true,
+ "channels": {
+ "in_app": {
+ "hasActiveIntegrations": true
+ },
+ "email": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "sms": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "chat": {
+ "hasActiveIntegrations": true
+ },
+ "push": {
+ "hasActiveIntegrations": false
+ }
+ }
+ }
+ },
+ {
+ "_id": "6469fc87301d88d6d2b74741",
+ "name": "Email quickstart",
+ "active": true,
+ "draft": false,
+ "critical": false,
+ "isBlueprint": false,
+ "_notificationGroupId": "641eddefda8256b93f750e0b",
+ "tags": [],
+ "triggers": [
+ {
+ "type": "event",
+ "identifier": "email-quickstart",
+ "variables": [
+ {
+ "name": "email",
+ "type": "String",
+ "_id": "646a031c25b1fb30f274ac35"
},
- "workflowIntegrationStatus": {
- "hasActiveIntegrations": true,
- "channels": {
- "in_app": {
- "hasActiveIntegrations": true
- },
- "email": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "sms": {
- "hasActiveIntegrations": true,
- "hasPrimaryIntegrations": true
- },
- "chat": {
- "hasActiveIntegrations": true
- },
- "push": {
- "hasActiveIntegrations": false
- }
- }
+ {
+ "name": "description",
+ "type": "String",
+ "_id": "646a031c25b1fb30f274ac36"
+ }
+ ],
+ "subscriberVariables": [
+ {
+ "name": "email",
+ "_id": "646a031c25b1fb30f274ac34"
+ }
+ ],
+ "_id": "6469fc87301d88d6d2b74742"
+ }
+ ],
+ "steps": [
+ {
+ "active": true,
+ "replyCallback": {
+ "active": false
+ },
+ "shouldStopOnFail": false,
+ "uuid": "3b512084-6cba-400c-8644-d9e9bff6bbfc",
+ "name": "Email",
+ "filters": [
+ {
+ "children": [],
+ "_id": "6469fd9bc2c5b74546b2cc80"
+ }
+ ],
+ "_templateId": "6469fd9bc2c5b74546b2cc76",
+ "_parentId": null,
+ "metadata": {
+ "timed": {
+ "weekDays": [],
+ "monthDays": []
+ }
+ },
+ "_id": "6469fd9bc2c5b74546b2cc76",
+ "template": {
+ "_id": "6469fd9bc2c5b74546b2cc76",
+ "type": "email"
+ }
+ }
+ ],
+ "preferenceSettings": {
+ "email": true,
+ "sms": true,
+ "in_app": true,
+ "chat": true,
+ "push": true
+ },
+ "_environmentId": "641eddefda8256b93f750e07",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_creatorId": "641eddee5d9af70da9f6a2e4",
+ "deleted": false,
+ "createdAt": "2023-05-21T11:12:07.036Z",
+ "updatedAt": "2023-05-21T11:40:12.955Z",
+ "__v": 0,
+ "notificationGroup": {
+ "_id": "641eddefda8256b93f750e0b",
+ "name": "General",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_environmentId": "641eddefda8256b93f750e07",
+ "createdAt": "2023-03-25T11:41:35.279Z",
+ "updatedAt": "2023-03-25T11:41:35.279Z",
+ "__v": 0
+ },
+ "workflowIntegrationStatus": {
+ "hasActiveIntegrations": true,
+ "channels": {
+ "in_app": {
+ "hasActiveIntegrations": true
+ },
+ "email": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "sms": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "chat": {
+ "hasActiveIntegrations": true
+ },
+ "push": {
+ "hasActiveIntegrations": false
+ }
+ }
+ }
+ },
+ {
+ "_id": "6450b033631887e5f013f0df",
+ "name": "notif-genenerator",
+ "active": true,
+ "draft": false,
+ "critical": false,
+ "isBlueprint": false,
+ "_notificationGroupId": "641eddefda8256b93f750e0b",
+ "tags": [],
+ "triggers": [
+ {
+ "type": "event",
+ "identifier": "notif-genenerator",
+ "variables": [
+ {
+ "name": "description",
+ "type": "String",
+ "_id": "645a5b18e1a93324256bdf59"
}
+ ],
+ "subscriberVariables": [],
+ "_id": "6450b033631887e5f013f0e0"
}
- ],
- "totalCount": 20,
- "pageSize": 10
+ ],
+ "steps": [
+ {
+ "active": true,
+ "shouldStopOnFail": false,
+ "uuid": "0486c699-2db4-4868-9ed5-c407acacb728",
+ "name": "In-App",
+ "filters": [
+ {
+ "children": [],
+ "_id": "6450b06e9c851c56f803d489"
+ }
+ ],
+ "_templateId": "6450b06e9c851c56f803d47e",
+ "_parentId": null,
+ "_id": "6450b06e9c851c56f803d47e",
+ "template": {
+ "_id": "6450b06e9c851c56f803d47e",
+ "type": "in_app"
+ }
+ }
+ ],
+ "preferenceSettings": {
+ "email": true,
+ "sms": true,
+ "in_app": true,
+ "chat": true,
+ "push": true
+ },
+ "_environmentId": "641eddefda8256b93f750e07",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_creatorId": "641eddee5d9af70da9f6a2e4",
+ "deleted": false,
+ "createdAt": "2023-05-02T06:39:47.699Z",
+ "updatedAt": "2023-05-09T14:39:20.811Z",
+ "__v": 0,
+ "notificationGroup": {
+ "_id": "641eddefda8256b93f750e0b",
+ "name": "General",
+ "_organizationId": "641eddefda8256b93f750e01",
+ "_environmentId": "641eddefda8256b93f750e07",
+ "createdAt": "2023-03-25T11:41:35.279Z",
+ "updatedAt": "2023-03-25T11:41:35.279Z",
+ "__v": 0
+ },
+ "workflowIntegrationStatus": {
+ "hasActiveIntegrations": true,
+ "channels": {
+ "in_app": {
+ "hasActiveIntegrations": true
+ },
+ "email": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "sms": {
+ "hasActiveIntegrations": true,
+ "hasPrimaryIntegrations": true
+ },
+ "chat": {
+ "hasActiveIntegrations": true
+ },
+ "push": {
+ "hasActiveIntegrations": false
+ }
+ }
+ }
+ }
+ ],
+ "totalCount": 20,
+ "pageSize": 10
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/workflows/update-workflow-status.mdx b/api-reference/workflows/update-workflow-status.mdx
index 6d1131fa..448d748f 100644
--- a/api-reference/workflows/update-workflow-status.mdx
+++ b/api-reference/workflows/update-workflow-status.mdx
@@ -19,11 +19,16 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```
```javascript Node.js
-import { Novu, TemplateVariableTypeEnum, FilterPartTypeEnum, StepTypeEnum } from '@novu/node';
+import {
+ Novu,
+ TemplateVariableTypeEnum,
+ FilterPartTypeEnum,
+ StepTypeEnum,
+} from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
-await novu.notificationTemplates.updateStatus("workflowId", false)
+await novu.notificationTemplates.updateStatus("workflowId", false);
```
```php PHP
@@ -90,7 +95,7 @@ func main() {
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
-
+
```
```kotlin Kotlin
@@ -127,9 +132,7 @@ class Main {
"push": true
},
"critical": true,
- "tags": [
- "string"
- ],
+ "tags": ["string"],
"steps": [
{
"_id": "string",
@@ -205,4 +208,4 @@ class Main {
}
```
-
\ No newline at end of file
+
diff --git a/api-reference/workflows/update-workflow.mdx b/api-reference/workflows/update-workflow.mdx
index 65653fc8..0ede7390 100644
--- a/api-reference/workflows/update-workflow.mdx
+++ b/api-reference/workflows/update-workflow.mdx
@@ -19,13 +19,18 @@ import ApikeyWarning from "/snippets/apikey-warning.mdx";
```
```javascript Node.js
-import { Novu, TemplateVariableTypeEnum, FilterPartTypeEnum, StepTypeEnum } from '@novu/node';
+import {
+ Novu,
+ TemplateVariableTypeEnum,
+ FilterPartTypeEnum,
+ StepTypeEnum,
+} from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
await novu.notificationTemplates.update("workflowId", {
name: "Send daily digest email update",
- description: "This workflow will send daily digest email to user at 9:00 AM"
+ description: "This workflow will send daily digest email to user at 9:00 AM",
/**
* all other fields from create workflow payload
*/
@@ -62,7 +67,7 @@ body = {
'description' => 'description', # optional
'steps' => [ # optional
# insert all fields here
- ],
+ ],
'active' => true, # optional
'draft' => true, # optional
'critical' => true, # optional
@@ -128,7 +133,7 @@ func main() {
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
-
+
```
```kotlin Kotlin
@@ -165,9 +170,7 @@ class Main {
"push": true
},
"critical": true,
- "tags": [
- "string"
- ],
+ "tags": ["string"],
"steps": [
{
"_id": "string",
@@ -243,4 +246,4 @@ class Main {
}
```
-
\ No newline at end of file
+
diff --git a/architecture/diagrams.mdx b/architecture/diagrams.mdx
index b2508538..7a3a0e23 100644
--- a/architecture/diagrams.mdx
+++ b/architecture/diagrams.mdx
@@ -2,13 +2,14 @@
title: "Novu Architecture Diagram"
version: "v0.21.0"
---
+
# Novu Architecture Diagram powered by [terrastruct](https://terrastruct.com) and D2
If the diagram below is not rendering, please [click here](https://app.terrastruct.com/diagrams/1895866270) to view it on terrastruct.com.
+ title="Novu"
+ width="1280"
+ height="720"
+ src="https://app.terrastruct.com/diagrams/745235552"
+>
diff --git a/architecture/introduction.mdx b/architecture/introduction.mdx
index f8e9f4df..b1c5e62c 100644
--- a/architecture/introduction.mdx
+++ b/architecture/introduction.mdx
@@ -3,6 +3,7 @@ title: "Introduction to Novu"
description: "Overview of Novu's Architecture"
version: "v0.21.0"
---
+
Novu is an open-source notification infrastructure designed to provide a robust, efficient, and flexible solution for managing notifications across various platforms.
The architecture of Novu is meticulously crafted to ensure accurate delivery of notifications while maintaining high performance and scalability.
diff --git a/channels-and-providers/default-providers.mdx b/channels-and-providers/default-providers.mdx
deleted file mode 100644
index 02d1a2d9..00000000
--- a/channels-and-providers/default-providers.mdx
+++ /dev/null
@@ -1,44 +0,0 @@
----
-title: 'Novu Providers'
-description: 'Learn about the default Novu email and sms providers'
-icon: 'code'
----
-
-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://web.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. Read more about them [here](/channels-and-providers/integration-store).
diff --git a/channels-and-providers/integration-store.mdx b/channels-and-providers/integration-store.mdx
deleted file mode 100644
index 37421bef..00000000
--- a/channels-and-providers/integration-store.mdx
+++ /dev/null
@@ -1,30 +0,0 @@
----
-title: 'Integration Store'
-description: "Learn about Novu's integration store"
-icon: 'store'
----
-
-## Introduction
-Novu's integration store serves as the central hub from where you can seamlessly enable and disable various services for efficient communication.
-
-This feature simplifies the process of managing your communication channels. You can see which provider is enabled/disabled for what channel, which provider works in what environment and more. Moreover, it provides a clear overview of enabled and disabled services, offering you greater control over your communication strategy.
-
-
-
-From this image above, you can see that I've configured `Sendgrid` and `Twilio` as my email and sms provider respectively and both are in the `development` environment.
-
-## Streamline Communication Services
-
-With the Integration Store, you can streamline your communication services effortlessly. Whether it's Email, Chat, or SMS, this feature allows you to integrate different communication channels with ease. This centralization ensures that you can manage all your services conveniently from a single location.
-
-## Enabling and Disabling Services
-
-The Integration Store allows you to activate or deactivate specific services according to your communication needs. You can enable a service by simply entering the required `API key`, `identifier` and other required info depending on the provider you're choosing. Conversely, if you need to deactivate a service temporarily or make changes, you can disable it just as effortlessly.
-
-## Enhanced Flexibility
-
-By providing a comprehensive range of communication services under one roof, the Integration Store enhances your flexibility. You have the power to customize your communication strategy by enabling the services that align with your requirements.
-
-## Conclusion
-
-Novu's integration store offers a centralized and user-friendly platform for managing your communication services effectively. With its categorization, clear visibility, and easy enablement/disabling of services, you can fine-tune your communication strategy and streamline your interactions, enhancing the overall communication experience of your product.
\ No newline at end of file
diff --git a/channels-and-providers/introduction.mdx b/channels-and-providers/introduction.mdx
deleted file mode 100644
index 782abc89..00000000
--- a/channels-and-providers/introduction.mdx
+++ /dev/null
@@ -1,26 +0,0 @@
----
-title: 'Overview'
-description: 'Learn about what channels, providers and oganizations are'
-icon: 'code'
----
-
-## Channels:
-
-Novu lets you send notifications across different communication mediums, including emails, in-app messages, push notifications, SMS, and chat. Each of these five communication mediums is referred to as a notification ‘channel’.
-
-
-
-## Providers:
-
-Providers are what allow us to handle message delivery over multiple channels. Of the five notification channels that Novu currently supports, each channel except the ‘in-app’ channel has multiple providers.
-
-The in-app channel only has one provider (the default Novu provider).
-
-All the remaining channels have multiple providers.
-
-## Organizations:
-Organizations enable you to segregate notifications across multiple products that you may have. You can use Novu to send notifications across multiple apps and can create organizations.
-
-
-
-Credentials are saved per instance of the active integrations of a provider. In case of more than one active provider of the same type, If `integrationIdentifier` is not sent in [this](https://docs.novu.co/api-reference/subscribers/update-subscriber-credentials) API, then the most recently created provider will be used to update the credentials.
\ No newline at end of file
diff --git a/community/add-a-new-provider.mdx b/community/add-a-new-provider.mdx
index f5d620fe..fc7c616d 100644
--- a/community/add-a-new-provider.mdx
+++ b/community/add-a-new-provider.mdx
@@ -8,7 +8,7 @@ Interested in expanding Novu's capabilities? By contributing to our growing ecos
## How to add a new provider?
-Novu currently supports five channels `in_app`, `push`, `email`, `chat` and `sms`.
+Novu currently supports five channels `in_app`, `push`, `email`, `chat` and `sms`.
For `in_app` we support only our own provider, so new providers cannot be added to this channel. For the other four channels, we support the integration of external providers. This guide will help in adding new providers for any of these 4 channels.
@@ -16,7 +16,7 @@ In this guide, we are adding a new provider for the email channel, but all of th
## Description
-Providers allow us to handle message delivery over multiple channels.
+Providers allow us to handle message delivery over multiple channels.
We have multiple providers for each channel (SMS, Email, Push and Chat). To get started with adding a new provider let's look at setting up our repository.
@@ -30,7 +30,10 @@ We have multiple providers for each channel (SMS, Email, Push and Chat). To get
Need help installing the requirements? [Read more here](/community/run-in-local-machine)
- We have used pnpm package manager in this guide. You can use npm as well.
+
+ {" "}
+ We have used pnpm package manager in this guide. You can use npm as well.{" "}
+
## Initialization
@@ -116,16 +119,23 @@ export class ExampleProviderEmailProvider implements IEmailProvider {
### Template test case for `example-provider`.
```ts packages/providers/src/lib/example-provider/example-provider.provider.sepc.ts
-import { ExampleProviderEmailProvider } from './example-provider.provider';
+import { ExampleProviderEmailProvider } from "./example-provider.provider";
-test('should trigger example-provider library correctly', async () => {});
+test("should trigger example-provider library correctly", async () => {});
```
- Add the provider's SDK as a dependency in the provider's package.json file. Run `pnpm run setup:project` to build all dependencies again. Use this new sdk method to complete the provider's `sendMessage` function. Check the **[reference links for adding new providers](#reference-for-adding-new-providers)** section for each channel's provider example.
+
+ {" "}
+ Add the provider's SDK as a dependency in the provider's package.json file. Run
+ `pnpm run setup:project` to build all dependencies again. Use this new sdk method
+ to complete the provider's `sendMessage` function. Check the **[reference links
+ for adding new providers](#reference-for-adding-new-providers)** section for each
+ channel's provider example.{" "}
+
### Add provider logos
-In order to present this new provider in the `integration store` we need logos in dark and light mode. Add dark color svg logo in `apps/web/public/static/images/providers/dark/sqaure` directory and light color svg logo in `apps/web/public/static/images/providers/light/sqaure` directory.
+In order to present this new provider in the `integration store` we need logos in dark and light mode. Add dark color svg logo in `apps/web/public/static/images/providers/dark/sqaure` directory and light color svg logo in `apps/web/public/static/images/providers/light/sqaure` directory.
Use the provider name as the file name. The sample name for our above-added provider is `example-provider.svg`.
@@ -157,6 +167,7 @@ export const exampleProviderConfig: IConfigCredentials[] = [
1. Here the `key` is of type `CredentialsKeyEnum`.
> If a new key is added, add this key at these 3 places:-
+>
> - In `CredentialsKeyEnum` at file `libs/shared/src/consts/providers/provider.enum.ts`
> - In `CredentialsDto` at file `apps/api/src/app/integrations/dtos/credentials.dto.ts`
> - In `credentials` field of `integrationSchema` at file `libs/dal/src/repositories/integration/integration.schema.ts`
@@ -267,7 +278,13 @@ If everything is working fine without any error, commit your local branch change
Hurray 🎉! You have successfully added a new provider in Novu!
-️ In this guide, we have used only one credential `apiKey` for our `example-provider`. This is for reference purposes only. A provider can have more than one credential as per its `SDK` requirements. At each step, you will need to add all credentials carefully. Check providers referenced below for more information.
+
+ ️ In this guide, we have used only one credential `apiKey` for
+ our `example-provider`. This is for reference purposes only. A provider can
+ have more than one credential as per its `SDK` requirements. At each step, you
+ will need to add all credentials carefully. Check providers referenced below
+ for more information.{" "}
+
### Reference for Adding New Providers
diff --git a/community/changelog.mdx b/community/changelog.mdx
index 8e61fd37..95d9a7d6 100644
--- a/community/changelog.mdx
+++ b/community/changelog.mdx
@@ -3,21 +3,34 @@ title: "Changelog"
description: "See the most recent changes and learn about how to shape Novu's future"
---
-
- Learn about what's changed, new features, bug fixes, and see Novu's history across versions.
+
+ Learn about what's changed, new features, bug fixes, and see Novu's history
+ across versions.
Using the changelog, you can:
+
- Keep an eye on the latest updates,
- Learn more about the newly added features and improvements, and
- Stay informed about bug fixes and enhancement
## Getting involved:
+
Community is at the heart of everything we do at Novu. To get more involved with the community, you can:
+
- **Fork and Contribute** to our open issues as well as suggest new ideas at our [github repository](https://github.com/novuhq/novu)
- **Join our community** to ask questions, engage with other users and share ideas. Here's the [joining link.](https://discord.gg/novu?ref=docs-join-our-community)
- **Participate in our office hours** to learn more and connect with our core team. Join us [here.](https://www.youtube.com/@novuhq/streams)
-Remember, we're not building just another product, but a community of passionate developers who shape its evolution. Our changelog isn't just a list of updates but a reflection of our journey together. Your voice matters, and your ideas and feedback are what fuel our progress and shape our future. So, join us in this adventure, and – Let's build something amazing, one feature at a time!
-
\ No newline at end of file
+ Remember, we're not building just another product, but a community of
+ passionate developers who shape its evolution. Our changelog isn't just a list
+ of updates but a reflection of our journey together. Your voice matters, and
+ your ideas and feedback are what fuel our progress and shape our future. So,
+ join us in this adventure, and – Let's build something amazing, one feature at
+ a time!
+
diff --git a/community/code-of-conduct.mdx b/community/code-of-conduct.mdx
index 99b728f9..00fcd75f 100644
--- a/community/code-of-conduct.mdx
+++ b/community/code-of-conduct.mdx
@@ -4,7 +4,6 @@ sidebarTitle: "Code of Conduct"
description: "The set of rules and guidelines that govern interaction among community members"
---
-
As a community-driven company, Novu is committed to creating an inclusive and welcoming environment for all members, regardless of factors such as age, body size, disability, ethnicity, gender identity, experience level, education, socio-economic status, nationality, personal appearance, race, religion, or sexual orientation.
However, diverse communities may face challenges, such as potential misunderstandings and miscommunications. To ensure respectful interactions, free from behaviour that may create an unsafe environment, we have established this Code of Conduct.
@@ -27,7 +26,6 @@ It's crucial to keep in mind that our community members are from all kinds of ba
- Accept responsibility and apologise to those affected by mistakes, and learn from such experiences
- Focus on what is best not just for us as individuals, but for the overall community!
-
### Patience
Our community thrives on the generosity of volunteered time. Questions, contributions, and support requests may embark on a time-travelling journey before finding their destination. Repeated "bumps" or persistent "reminders" don’t display patience and are looked down upon. Lastly, it is a bad practice to ask general questions to a specific person (in direct messages for example). Try to ask in public as much as you can, and patiently wait for the response
@@ -36,7 +34,7 @@ Our community thrives on the generosity of volunteered time. Questions, contribu
Please be courteous and respectful to fellow members. Avoid offensive comments related to age, body size, disability, ethnicity, gender identity, experience level, education, socio-economic status, nationality, personal appearance, race, religion, or sexual orientation.
-Strictly prohibited are sexualized imagery, violence, intimidation, stalking, disruptions, sharing personal information without explicit permission, unwanted physical contact, and unwelcome sexual attention.
+Strictly prohibited are sexualized imagery, violence, intimidation, stalking, disruptions, sharing personal information without explicit permission, unwanted physical contact, and unwelcome sexual attention.
Use inclusive language respecting our community's diversity.
@@ -46,9 +44,9 @@ Avoid assumptions about others' backgrounds. Maintain a positive and professiona
### Inquisitive
-***The only stupid question is the one that does not get asked***.
+**_The only stupid question is the one that does not get asked_**.
-We encourage our users to ask early and ask often. Rather than asking whether you can ask a question (the answer is always yes!), instead, simply ask your question. You are encouraged to provide as many specifics as possible.
+We encourage our users to ask early and ask often. Rather than asking whether you can ask a question (the answer is always yes!), instead, simply ask your question. You are encouraged to provide as many specifics as possible.
Code snippets in the form of images are bad practice. Instead, use text formatted as code (using backticks) on Discord or simply send a gist. Refrain from pasting multiple lines of code directly into the chat channels - instead use [gist.github.com](http://gist.github.com/) or another paste site to provide code snippets.
@@ -91,15 +89,22 @@ We expect all participants, organizers, speakers, and attendees to follow these
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
1. **Correction**
+
- `Community Impact`: Use of inappropriate language or other behaviour deemed unprofessional or unwelcome in the community.
- `Consequence`: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behaviour was inappropriate. A public apology may be requested.
+
2. **Warning**
+
- `Community Impact`: A violation through a single incident or series of actions.
- `Consequence`: A warning with consequences for continued behaviour. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
+
3. **Temporary Ban**
+
- `Community Impact`: A serious violation of community standards, including sustained inappropriate behaviour.
- `Consequence`: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
+
4. **Permanent Ban**
+
- `Community Impact`: Demonstrating a pattern of violation of community standards, including sustained inappropriate behaviour, harassment of an individual, or aggression toward or disparagement of classes of individuals.
- `Consequence`: A permanent ban from any sort of public interaction within the community.
@@ -117,6 +122,6 @@ Our Code of Conduct was adapted from Codes of Conduct of other open-source proje
Community Impact Guidelines were inspired by Mozilla's code of conduct enforcement ladder.
-For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq.
+For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq.
-Translations are available at https://www.contributor-covenant.org/translations.
\ No newline at end of file
+Translations are available at https://www.contributor-covenant.org/translations.
diff --git a/self-hosting-novu/deploy-with-docker.mdx b/community/deploy-with-docker.mdx
similarity index 77%
rename from self-hosting-novu/deploy-with-docker.mdx
rename to community/deploy-with-docker.mdx
index bbb283d9..17c176f9 100644
--- a/self-hosting-novu/deploy-with-docker.mdx
+++ b/community/deploy-with-docker.mdx
@@ -1,7 +1,7 @@
---
-title: 'Deploy with Docker'
-description: 'Learn how to deploy Novu with Docker'
-icon: 'docker'
+title: "Deploy with Docker"
+description: "Learn how to deploy Novu with Docker"
+icon: "docker"
---
Docker compose is the easiest way to get started with self-hosted Novu.
@@ -13,10 +13,18 @@ You need the following installed in your system:
- [Docker](https://docs.docker.com/engine/install/) and [docker-compose](https://docs.docker.com/compose/install/)
- [Git](https://git-scm.com/downloads)
+
-
-
-In above loom video `local/deployment` directory is used. Now it has been moved to `docker/community`. Follow below mentioned steps.
+
+ In above loom video `local/deployment` directory is used. Now it has been
+ moved to `docker/community`. Follow below mentioned steps.
+
## Quick Start
@@ -44,7 +52,7 @@ Now visit [http://localhost:4200](http://localhost:4200/) to start using Novu.
While we provide you with some example secrets for getting started, you should NEVER deploy your Novu setup using the defaults provided.
-Update the `.env` file with your own secrets.
+Update the `.env` file with your own secrets.
### Required Variables:
@@ -68,17 +76,17 @@ We strongly recommend that you decouple your database before deploying.
When self-hosting Novu, in order to trigger an event you must first create a new `Novu` object and configure it with the proper `backendUrl`.
```tsx
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const config = {
- backendUrl: '',
+ backendUrl: "",
};
-const novu = new Novu('', config);
+const novu = new Novu("", config);
-await novu.trigger('', {
+await novu.trigger("", {
to: {
- subscriberId: '',
+ subscriberId: "",
},
payload: {},
});
@@ -91,17 +99,16 @@ When using the IFrame embed to attach the notification center rather than the Re
```html
-
```
### Using React Component with custom installation
@@ -121,8 +128,7 @@ Currently, we are caching data in the most heavily loaded areas of the system: t
To implement a reverse-proxy or load balancer in front of Novu, you need to set the GLOBAL_CONTEXT_PATH for the base path of the application.
This is the path that the application will be served from after the domain.
-For example:
- - company.com/novu
+For example: - company.com/novu
This is used to set the base path for the application, and is used to set the base path for the API, web, and websocket connections.
The following environment variables are used to set the context path for each public service that Novu provides:
@@ -140,17 +146,15 @@ the WIDGET_CONTEXT_PATH to widget,
the WS_CONTEXT_PATH to ws,
and the WEB_CONTEXT_PATH to web.
-This would produce the following urls:
- - API: company.com/novu/api
- - WIDGET: company.com/novu/widget
- - WS: company.com/novu/ws
- - WEB: company.com/novu/web
+This would produce the following urls: - API: company.com/novu/api - WIDGET: company.com/novu/widget - WS: company.com/novu/ws - WEB: company.com/novu/web
However the Service context path can be used entirely independently of the GLOBAL_CONTEXT_PATH.
For example, if I wanted to expose the api as novu-api, I would set the API_CONTEXT_PATH to novu-api without setting the GLOBAL_CONTEXT_PATH.
-This would producte the following url:
- - API: company.com/novu-api
-
- These env variables should be present on all services novu provides due to tight coupling.
+This would producte the following url: - API: company.com/novu-api
+
+ {" "}
+ These env variables should be present on all services novu provides due to tight
+ coupling.
+
diff --git a/community/feature-flags.mdx b/community/feature-flags.mdx
index e8b4834a..08a70acb 100644
--- a/community/feature-flags.mdx
+++ b/community/feature-flags.mdx
@@ -8,14 +8,22 @@ Feature flags allow to turn certain functionality on and off based on configurat
To enable the specific feature, you need to pass an environment variable to all services:
- Feature flag environment variable accepts boolean values: `true` or `false`.
+ Feature flag environment variable accepts boolean values: `true` or `false`.
- `IS_MULTI_PROVIDER_CONFIGURATION_ENABLED` adds ability to connect multiple providers per channel and make them active. It also shows redesigned integrations store page.
-
+
+
+ {" "}
+
- `IS_MULTI_TENANCY_ENABLED` adds ability to manage tenants from dashboard.
-
+
+
+ {" "}
+
- `IS_TEMPLATE_STORE_ENABLED` enables template store which contains pre-made workflows for common use cases (like **Password Reset** workflow etc).
-
+
+ {" "}
+
diff --git a/community/get-involved.mdx b/community/get-involved.mdx
index f767a939..fdc35481 100644
--- a/community/get-involved.mdx
+++ b/community/get-involved.mdx
@@ -25,8 +25,10 @@ Our fellow community members are always ready to help you get past a blocker. Ho
- If there is any issue in our backend SDKs, please mention the SDK version and relevant details.
- If looking for self-hosting support, please share `Novu Version` and remote server details. Our latest version is `0.24.0`. Please be patient with self-hosting help. We are a small team and we will try our best to help you.
-Intercome is suitable if you're using Novu cloud or. Kindly use Discord or Github for community self-hosting questions.
-
+
+ Intercome is suitable if you're using Novu cloud or. Kindly use Discord or
+ Github for community self-hosting questions.
+
## Contributing
@@ -41,19 +43,19 @@ All community members are of one of the following four types:
- Everyone who joins our community becomes an open-source user automatically.
- You can become an active community member by:
- - Submitting >2 PRs
- - Opening >2 issues
- - Sending >5 messages on Github
- - Commenting >3 times on Github
+ - Submitting >2 PRs
+ - Opening >2 issues
+ - Sending >5 messages on Github
+ - Commenting >3 times on Github
- Active community members are one step closer to becoming Power community members and then an active moderator.
### Become a power community member
- All active community members are eligible to become a power community member and can become so by having at least one of the following:
- - Submitting 3 PRs
- - Opening 3 Issues
- - Sending 10 Discord messages
- - Commenting >10 times on Github
+ - Submitting 3 PRs
+ - Opening 3 Issues
+ - Sending 10 Discord messages
+ - Commenting >10 times on Github
- Power community members are just one step away from becoming a Novu ambassador.
### Become a Novu Ambassador
@@ -68,7 +70,6 @@ A Novu ambassador is a trusted power member of the community that can do the fol
We are launching the Novu Ambassador program soon with amazing perks. Stay tuned!
-
## Activities
Are you passionate about notifications like we are? There are many different—and easy—ways to get involved.
@@ -84,16 +85,15 @@ Are you passionate about notifications like we are? There are many different—a
- Check out our[GitHub repo](https://github.com/novuhq/docs)
- No documentation is perfect, and neither is ours
- Help us improve our docs by
- - Updating outdated examples
- - Correcting typos and language for clarity
- - Find and fix broken links, etc.
-
+ - Updating outdated examples
+ - Correcting typos and language for clarity
+ - Find and fix broken links, etc.
### Help with the SDKs
- Link to contributors guide(https://github.com/novuhq/novu/blob/next/CONTRIBUTING.md)
- We have SDKs in various languages and frameworks, most written and maintained by community members.
-- You can either become a maintainer there or help the existing maintainers by bringing the SDK up to speed with the latest features present in the core product.
+- You can either become a maintainer there or help the existing maintainers by bringing the SDK up to speed with the latest features present in the core product.
- We have backend SDKs in the following: [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) [Laravel](https://github.com/novuhq/novu-laravel), and [Kotlin](https://github.com/novuhq/novu-kotlin)
- And client-side SDKs in the follwing: [Vue](https://github.com/novuhq/novu/tree/next/packages/notification-center-vue), [React](https://github.com/novuhq/novu/tree/next/packages/notification-center), [Angular](https://github.com/novuhq/novu/tree/next/packages/notification-center-angular), [Web Component](https://github.com/novuhq/novu/tree/next/packages/notification-center), [iframe embed](https://docs.novu.co/notification-center/client/iframe), and [Headless Javascript.](https://docs.novu.co/notification-center/client/headless/get-started)
@@ -111,7 +111,9 @@ Are you passionate about notifications like we are? There are many different—a
- Or a feature request if you find something that should be a feature but isn't.
-At Novu, we believe that no contribution is small, and the only wrong question is the one that doesn’t get asked. So feel free to ask any question or raise that Pull Request. You’re always welcome here! 🤗
+ At Novu, we believe that no contribution is small, and the only wrong question
+ is the one that doesn’t get asked. So feel free to ask any question or raise
+ that Pull Request. You’re always welcome here! 🤗
### Participate in office hours
@@ -121,4 +123,4 @@ At Novu, we believe that no contribution is small, and the only wrong question i
We’re excited to have you on board and look forward to your valuable contributions!
-Together, we’ll shape the future of Novu. 🫂
\ No newline at end of file
+Together, we’ll shape the future of Novu. 🫂
diff --git a/community/introduction.mdx b/community/introduction.mdx
index 1c01312a..39be2634 100644
--- a/community/introduction.mdx
+++ b/community/introduction.mdx
@@ -15,7 +15,7 @@ How to get help and support from the Novu team?
- If there is any bug, please share steps to reproduce that bug.
- If there is any issue in running Novu in local machine, please share system details like operating system, RAM size, npm version, node version.
- If there is any issue in our backend sdks, please mention sdk version and relevant details.
-- If looking for self hosting support, please share `Novu Version` and remote server details. Our latest version is `0.21.0`. Please be patient for self hosting help. We are a small team and we will try our best to help you.
+- If looking for self hosting support, please share `Novu Version` and remote server details. Our latest version is `0.21.0`. Please be patient for self hosting help. We are a small team and we will try our best to help you.
### Discord
@@ -27,7 +27,10 @@ Join us on [Discord](https://discord.gg/novu?ref=docs-community-introduction) to
For personalized support, our Intercom chat is available directly within the Novu app. Our team is ready to answer your queries and provide solutions to ensure your experience with Novu is smooth and productive.
-Intercom is best for issues in using Novu cloud option only. Kindly use discord or github for community self hosting questions.
+
+ Intercom is best for issues in using Novu cloud option only. Kindly use
+ discord or github for community self hosting questions.
+
### GitHub Issues
diff --git a/community/machine-setup.mdx b/community/machine-setup.mdx
index c4096d9e..d7750a81 100644
--- a/community/machine-setup.mdx
+++ b/community/machine-setup.mdx
@@ -131,7 +131,7 @@ Follow the instructions to install the AWS CLI so you can use it to create env l
You should get something like this:
-
+
If needed, see:
@@ -256,5 +256,5 @@ For better productivity and wellness, we suggest removing the not-used apps from
Right Click on the app icon > Options > Remove from Dock
-
+
diff --git a/community/monorepo-structure.mdx b/community/monorepo-structure.mdx
index 95646785..c6d7e3bb 100644
--- a/community/monorepo-structure.mdx
+++ b/community/monorepo-structure.mdx
@@ -27,7 +27,6 @@ For additional information on running Novu locally, visit the [run locally](http
The `apps` folder contains high-level applications and APIs. The app's outputs usually contain deployable units that a user can interact with either as an API or as a web/cli application.
-
The API package is our main service for handling backend logic. It handles anything from authentication, authorization, workflow management, triggering events, etc... This is where the Novu business logic is handled.
@@ -39,9 +38,10 @@ The `apps` folder contains high-level applications and APIs. The app's outputs u
This is the Novu admin panel which is used to visually communicate with the API. You can configure workflows, manage content, enable or disable notifications, visually track the notification activity feed, etc...
The `WEB` project is a create-react-app built, well, with React. 😄
+
- This is the client of our embeddable notification center widget. It is consumed mainly with the embed script in an Iframe. We can access it on port 4500 to interact with it directly.
+ This is the client of our embeddable Inbox widget. It is consumed mainly with the embed script in an Iframe. We can access it on port 4500 to interact with it directly.
This is our service for managing and handling workers.
@@ -64,21 +64,27 @@ The `apps` folder contains high-level applications and APIs. The app's outputs u
This is the connector between our client's web app and the widget project. It’s a small shim script that generates an iframe and attaches it to a client-specified div to host the notification widget.
If you are familiar with the Google Analytics embedded snippet or intercom-like embeddings, it uses the same mechanics.
+
-
## Packages (on npm)
- A Standalone Node.js wrapper around the Novu API. Exists to provide type-safe and easier access to the different API endpoints Novu exposes (Triggers, subscribers, etc…).
+ A Standalone Node.js wrapper around the Novu API. Exists to provide
+ type-safe and easier access to the different API endpoints Novu exposes
+ (Triggers, subscribers, etc…).
- A Nest.js wrapper around the `@novu/node` package was created by the community to easily interact with the core library from a nest project. Also released on NPM as a package.
+ A Nest.js wrapper around the `@novu/node` package was created by the
+ community to easily interact with the core library from a nest project. Also
+ released on NPM as a package.
- React component library that contains widget bell with the notification center. Can get override of components like ‘bell icon’, and ‘notification center’.
+ React component library that contains widget bell with the notification
+ center. Can get override of components like ‘bell icon’, and ‘notification
+ center’.
@@ -124,4 +130,4 @@ Novu provides a single API to manage providers across multiple channels with a s
### 📱 In-App
-- [Novu](https://docs.novu.co/notification-center/getting-started)
\ No newline at end of file
+- [Novu](https://docs.novu.co/notification-center/getting-started)
diff --git a/community/roadmap.mdx b/community/roadmap.mdx
index 6d3cc9b2..a49b89f0 100644
--- a/community/roadmap.mdx
+++ b/community/roadmap.mdx
@@ -7,8 +7,7 @@ description: "Learn about our roadmap"
Learn about ongoing developments, upcoming plans, and items in our backlog..
-
-Your involvement in shaping the future of our notification infrastructure solution is highly encouraged.
+Your involvement in shaping the future of our notification infrastructure solution is highly encouraged.
## Get involved
@@ -16,6 +15,11 @@ Your involvement in shaping the future of our notification infrastructure soluti
**Upvote and Comment:** Review the existing feature requests and upvote the ones that resonate with you. Feel free to provide additional insights or use-cases through comments.
-**Contribute:** If you're a developer, you can actively contribute to the development of the features in progress or even the backlog ones. [Join our community of contributors](https://discord.gg/novu?ref=docs-contribute) and help us bring these enhancements to life.
+**Contribute:** If you're a developer, you can actively contribute to the development of the features in progress or even the backlog ones. [Join our community of contributors](https://discord.gg/novu?ref=docs-contribute) and help us bring these enhancements to life.
-Remember, this roadmap is a living document that evolves based on your input and the direction the community decides to take. Your voice matters, and we're excited to work together in building a robust notification infrastructure solution that meets everyone's needs.
\ No newline at end of file
+
+ Remember, this roadmap is a living document that evolves based on your input
+ and the direction the community decides to take. Your voice matters, and we're
+ excited to work together in building a robust notification infrastructure
+ solution that meets everyone's needs.
+
diff --git a/community/run-in-local-machine.mdx b/community/run-in-local-machine.mdx
index bcd7ee0f..5a116d32 100644
--- a/community/run-in-local-machine.mdx
+++ b/community/run-in-local-machine.mdx
@@ -15,9 +15,19 @@ description: "Prerequisites and steps to run Novu in local machine. Learn how to
Need help installing the requirements? Read more [here](/community/machine-setup).
-We recommend having at least 8GB of RAM to run Novu on a local machine as Novu has multiple services running together with external services like redis, mongodb etc.
-
-
+
+ We recommend having at least 8GB of RAM to run Novu on a local machine as Novu
+ has multiple services running together with external services like redis,
+ mongodb etc.
+
+
+
### Setup the project
@@ -27,16 +37,12 @@ your forked version of the project:
1. Clone the repository
-
- ```shell
- git clone https://github.com/novuhq/novu.git
- ````
-
-
- ```shell
- git clone https://github.com/{YOUR_GITHUB_USER_NAME}/novu.git
- ```
-
+
+ ```shell git clone https://github.com/novuhq/novu.git ````
+
+
+ ```shell git clone https://github.com/{YOUR_GITHUB_USER_NAME}/novu.git ```
+
2. Install all dependencies
@@ -64,9 +70,21 @@ The `npm run start` will start the Jarvis CLI tool which allows you to run the
- **start:node** - Runs the `@novu/node` package in watch mode
- **start:notification-center** - Runs and builds the React package for the Novu notification center
-
-
-
+
+
+
### Set up your environment variables
@@ -81,7 +99,7 @@ The command `npm run setup:project` creates default environment variables that
- `S3_BUCKET_NAME`The name of the S3 Bucket
- `S3_REGION`The AWS region of the S3 Bucket
- `PORT`The port on which the API backend should listen on
- - `FRONT_BASE_URL`The base url on which your frontend is accessible for the user. (e.g. web.novu.co)
+ - `FRONT_BASE_URL`The base url on which your frontend is accessible for the user. (e.g. dashboard.novu.co)
- `DISABLE_USER_REGISTRATION` (default: false)If users should not be able to create new accounts. Possible values are: true, false
- `REDIS_HOST`The domain / IP of your redis instance
- `REDIS_PORT`The port of your redis instance
@@ -113,75 +131,74 @@ The command `npm run setup:project` creates default environment variables that
- `SENDGRID_API_KEY`The api key of the Sendgrid account used to send various emails
- `MONGO_URL`The URL of your MongoDB instance
- `MONGO_MAX_POOL_SIZE`The max pool size of the MongoDB connection
- - `NOVU_API_KEY`The api key of web.novu.co used to send various emails
+ - `NOVU_API_KEY`The api key of dashboard.novu.co used to send various emails
- `SENTRY_DSN`The DSN of sentry.io used to report errors happening in production
-
- - `NODE_ENV` (default: local)The environment of the app. Possible values are: dev, test, production, ci, local
- - `PORT`The port on which the Worker app should listen on
- - `STORE_ENCRYPTION_KEY`The encryption key used to encrypt/decrypt provider credentials
- - `MAX_NOVU_INTEGRATION_MAIL_REQUESTS`The number of free emails that can be sent with the Novu email provider
- - `NOVU_EMAIL_INTEGRATION_API_KEY`The Novu email provider Sentry API key
- - `STORAGE_SERVICE`The storage service name: AWS, GCS, or AZURE
- - `S3_LOCAL_STACK`The LocalStack service URL
- - `S3_BUCKET_NAME`The name of the S3 Bucket
- - `S3_REGION`The AWS region of the S3 Bucket
- - `GCS_BUCKET_NAME`The name of the GCS Bucket
- - `AZURE_ACCOUNT_NAME`The name of the Azure account
- - `AZURE_ACCOUNT_KEY`The Azure account key
- - `AZURE_HOST_NAME`The Azure host name
- - `AZURE_CONTAINER_NAME`The Azure container name
- - `AWS_ACCESS_KEY_ID`The AWS access key
- - `AWS_SECRET_ACCESS_KEY`The AWS secret access key
- - `REDIS_HOST`The domain / IP of your redis instance
- - `REDIS_PORT`The port of your redis instance
- - `REDIS_PASSWORD`Optional password of your redis instance
- - `REDIS_DB_INDEX`The Redis database index
- - `REDIS_CACHE_SERVICE_HOST`The domain / IP of your redis instance for caching
- - `REDIS_CACHE_SERVICE_PORT`The port of your redis instance for caching
- - `REDIS_DB_INDEX`The Redis cache database index
- - `REDIS_CACHE_TTL`The Redis cache ttl
- - `REDIS_CACHE_PASSWORD`The Redis cache password
- - `REDIS_CACHE_CONNECTION_TIMEOUT`The Redis cache connection timeout
- - `REDIS_CACHE_KEEP_ALIVE`The Redis cache TCP keep alive on the socket timeout
- - `REDIS_CACHE_FAMILY`The Redis cache IP stack version
- - `REDIS_CACHE_KEY_PREFIX`The Redis cache prefix prepend to all keys
- - `REDIS_CACHE_SERVICE_TLS`The Redis cache TLS connection support
- - `IN_MEMORY_CLUSTER_MODE_ENABLED`The flag that enables the cluster mode. It might be Redis or ElastiCache cluster, depending on the env variables set for either service.
- - `ELASTICACHE_CLUSTER_SERVICE_HOST`ElastiCache cluster host
- - `ELASTICACHE_CLUSTER_SERVICE_PORT`ElastiCache cluster port
- - `REDIS_CLUSTER_SERVICE_HOST`Redis cluster host
- - `REDIS_CLUSTER_SERVICE_PORTS`Redis cluster ports
- - `REDIS_CLUSTER_DB_INDEX`Redis cluster database index
- - `REDIS_CLUSTER_TTL`Redis cluster ttl
- - `REDIS_CLUSTER_PASSWORD`Redis cluster password
- - `REDIS_CLUSTER_CONNECTION_TIMEOUT`Redis cluster connection timeout
- - `REDIS_CLUSTER_KEEP_ALIVE`Redis cluster TCP keep alive on the socket timeout
- - `REDIS_CLUSTER_FAMILY`Redis cluster IP stack version
- - `REDIS_CLUSTER_KEY_PREFIX`Redis cluster prefix prepend to all keys
- - `MONGO_URL`The URL of your MongoDB instance
- - `MONGO_MAX_POOL_SIZE`The max pool size of the MongoDB connection
- - `NEW_RELIC_APP_NAME`The New Relic app name
- - `NEW_RELIC_LICENSE_KEY`The New Relic license key
- - `SEGMENT_TOKEN`The Segment Analytics token
-
-
-
- - `REACT_APP_ENVIRONMENT` The environment of the app. Possible values are: dev, test, production, ci, local
- - `REACT_APP_API_URL` The base url on which your API backend would be accessible
- - `REACT_APP_WS_URL` The base url on which your WebSocket service would be accessible
- - `SKIP_PREFLIGHT_CHECK` (default: true)Solves a problem with React App dependency tree.
-
- When configuring different than default values for the API and WebSocket URLs,
- in order for the Web app to apply the changes done to the `./env` file, it is
- needed to run the script `pnpm envsetup`. This will generate a file
- called `env-config.js` that will be copied inside of the `public` folder of
- the application. Its purpose is to inject in the `window._env_`object the
- chosen environment variables that manage the URLs the Web client will call to
- access to the API backend and the WebSocket service.
-
-
+{" "}
+
+ - `NODE_ENV` (default: local)The environment of the app. Possible values are:
+ dev, test, production, ci, local - `PORT`The port on which the Worker app
+ should listen on - `STORE_ENCRYPTION_KEY`The encryption key used to
+ encrypt/decrypt provider credentials - `MAX_NOVU_INTEGRATION_MAIL_REQUESTS`The
+ number of free emails that can be sent with the Novu email provider -
+ `NOVU_EMAIL_INTEGRATION_API_KEY`The Novu email provider Sentry API key -
+ `STORAGE_SERVICE`The storage service name: AWS, GCS, or AZURE -
+ `S3_LOCAL_STACK`The LocalStack service URL - `S3_BUCKET_NAME`The name of the
+ S3 Bucket - `S3_REGION`The AWS region of the S3 Bucket - `GCS_BUCKET_NAME`The
+ name of the GCS Bucket - `AZURE_ACCOUNT_NAME`The name of the Azure account -
+ `AZURE_ACCOUNT_KEY`The Azure account key - `AZURE_HOST_NAME`The Azure host
+ name - `AZURE_CONTAINER_NAME`The Azure container name - `AWS_ACCESS_KEY_ID`The
+ AWS access key - `AWS_SECRET_ACCESS_KEY`The AWS secret access key -
+ `REDIS_HOST`The domain / IP of your redis instance - `REDIS_PORT`The port of
+ your redis instance - `REDIS_PASSWORD`Optional password of your redis instance
+ - `REDIS_DB_INDEX`The Redis database index - `REDIS_CACHE_SERVICE_HOST`The
+ domain / IP of your redis instance for caching - `REDIS_CACHE_SERVICE_PORT`The
+ port of your redis instance for caching - `REDIS_DB_INDEX`The Redis cache
+ database index - `REDIS_CACHE_TTL`The Redis cache ttl -
+ `REDIS_CACHE_PASSWORD`The Redis cache password -
+ `REDIS_CACHE_CONNECTION_TIMEOUT`The Redis cache connection timeout -
+ `REDIS_CACHE_KEEP_ALIVE`The Redis cache TCP keep alive on the socket timeout -
+ `REDIS_CACHE_FAMILY`The Redis cache IP stack version -
+ `REDIS_CACHE_KEY_PREFIX`The Redis cache prefix prepend to all keys -
+ `REDIS_CACHE_SERVICE_TLS`The Redis cache TLS connection support -
+ `IN_MEMORY_CLUSTER_MODE_ENABLED`The flag that enables the cluster mode. It
+ might be Redis or ElastiCache cluster, depending on the env variables set for
+ either service. - `ELASTICACHE_CLUSTER_SERVICE_HOST`ElastiCache cluster host -
+ `ELASTICACHE_CLUSTER_SERVICE_PORT`ElastiCache cluster port -
+ `REDIS_CLUSTER_SERVICE_HOST`Redis cluster host -
+ `REDIS_CLUSTER_SERVICE_PORTS`Redis cluster ports -
+ `REDIS_CLUSTER_DB_INDEX`Redis cluster database index -
+ `REDIS_CLUSTER_TTL`Redis cluster ttl - `REDIS_CLUSTER_PASSWORD`Redis cluster
+ password - `REDIS_CLUSTER_CONNECTION_TIMEOUT`Redis cluster connection timeout
+ - `REDIS_CLUSTER_KEEP_ALIVE`Redis cluster TCP keep alive on the socket timeout
+ - `REDIS_CLUSTER_FAMILY`Redis cluster IP stack version -
+ `REDIS_CLUSTER_KEY_PREFIX`Redis cluster prefix prepend to all keys -
+ `MONGO_URL`The URL of your MongoDB instance - `MONGO_MAX_POOL_SIZE`The max
+ pool size of the MongoDB connection - `NEW_RELIC_APP_NAME`The New Relic app
+ name - `NEW_RELIC_LICENSE_KEY`The New Relic license key - `SEGMENT_TOKEN`The
+ Segment Analytics token
+
+
+{" "}
+
+ - `REACT_APP_ENVIRONMENT` The environment of the app. Possible values are:
+ dev, test, production, ci, local - `REACT_APP_API_URL` The base url on which
+ your API backend would be accessible - `REACT_APP_WS_URL` The base url on
+ which your WebSocket service would be accessible -
+ `SKIP_PREFLIGHT_CHECK` (default: true)Solves a problem with React App
+ dependency tree.
+
+ When configuring different than default values for the API and WebSocket
+ URLs, in order for the Web app to apply the changes done to
+ the `./env` file, it is needed to run the script `pnpm envsetup`. This will
+ generate a file called `env-config.js` that will be copied inside of
+ the `public` folder of the application. Its purpose is to inject in
+ the `window._env_`object the chosen environment variables that manage the
+ URLs the Web client will call to access to the API backend and the WebSocket
+ service.
+
+
- `NODE_ENV` (default: local)The environment of the app. Possible values are: dev, test, production, ci, local
diff --git a/community/windows-machine-setup.mdx b/community/windows-machine-setup.mdx
index 4a1ce470..21c7bb0e 100644
--- a/community/windows-machine-setup.mdx
+++ b/community/windows-machine-setup.mdx
@@ -18,13 +18,14 @@ Download the .exe installation file for NVM for Windows [here](https://github.co
After installing NVM for Windows, check that the installation is successfull and added to path by running `nvm -v` on a terminal.
- After installing NVM, if you get `nvm: command not found` or see
- no feedback from your terminal after you type `nvm -v`, simply **close
- your current terminal, open a new terminal**, and try verifying again.
+ After installing NVM, if you get `nvm: command not found` or see no feedback
+ from your terminal after you type `nvm -v`, simply **close your current
+ terminal, open a new terminal**, and try verifying again.
Once nvm is installed and working you can install any version of Node using the syntax `nvm install vX.Y.Z` and to switch to a node version,
run `nvm use vX.Y.Z`. Novu requires node v20.8.1 or higher:
+
```shell
nvm install v18.17.0
nvm use v18.17.0
@@ -37,12 +38,15 @@ For package management, we use [PNPM](https://pnpm.io/) instead of npm or yarn t
```shell
npm install -g pnpm
```
+
### MongoDB
+
for detailed instructions on installing MongoDB community edition on a Windows machine please refere to the MongoDB doc [here](https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-windows).
After installation, whether you have installed as a Windows service or just the binaries, ensure that the MongoDB instance is started before you proceed.
### Redis
+
To install Redis for local development you'll first need to enable WSL2 (Windows Subsystem for Linux). detailed instructions for installing
WSL can be found [here](https://learn.microsoft.com/en-us/windows/wsl/install)
@@ -50,11 +54,13 @@ If you have WSL installed and enabled, you can easily install Redis using the na
for Ubuntu or Debian which is the default distro installed by WSL, use the following commands
1. First install `lsb-release`, `curl` and `gpg` if you do not already have them:
+
```shell
sudo apt install lsb-release curl gpg
```
2. Add the repository to the apt index, update it, and then install:
+
```shell
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
@@ -63,10 +69,13 @@ echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://pack
sudo apt-get update
sudo apt-get install redis
```
+
3. Lastly, start the Redis server like so:
+
```shell
sudo service redis-server start
```
+
### Docker
Docker is not a requirement to run Novu on your local machine, but if you would prefer to use Docker, Follow the installation guide on [docker website](https://docs.docker.com/desktop/install/windows-install/) to install **Docker Desktop** on your Windows machine.
@@ -90,6 +99,7 @@ If needed, see:
This will allow you to use [local.novu.co](http://local.novu.co) instead of [localhost](http://localhost) when accessing the service on your machine.
Navigate to `C:\Windows\System32\drivers\etc` in the file explorer and open the `hosts` file with a text editor (like Notepad):
+
Note that this file can only be edited when running as an Administrator.
diff --git a/concepts/controls.mdx b/concepts/controls.mdx
new file mode 100644
index 00000000..69269320
--- /dev/null
+++ b/concepts/controls.mdx
@@ -0,0 +1,116 @@
+---
+title: "Controls"
+---
+
+Controls are defined using [JSON Schema](/recipes/json-schema) or Zod, providing a strong run-time validation system for your workflows.
+
+This ensures that you as the developer and your non-technical peers are speaking the same language.
+Those responsible for styling and copy can edit with confidence, knowing their changes are tested in code.
+
+## Controls vs Payload
+
+**Control Schema** - For Non-Technical Peers and Developers. Managed in the Novu Dashboard UI, defined by developers and used by non-technical peers.
+
+**Payload Schema** - For Developers. Passed during the `novu.trigger` method, and controlled by the developer.
+
+## Common usecases
+
+- **Content** - Modify any static content: email subject, email body, push notification title, etc...
+- **Styling** - Modify the styling of the content: button color, background color, font size, etc...
+- **Behaviour** - Modify the behaviour of the content: show/hide a section, show/hide a button, etc...
+- **Order** - Modify the order of the content: the order of the email sections, the order of the buttons, etc...
+- **Actions** - Modify the behaviour of actions: digest duration, etc...
+- **Other** - Any other use case that should be controller without modifying code
+
+## Step Controls
+
+Step Control schema defines the control passed during the `step` method. These controls can be modified and persisted in the Novu Dashboard UI.
+The snippet below shows a configuration for the Step Control schema. If you don’t provide a schema, Typescript will infer the data type to `unknown`, reminding you of the best practice to specify your schema.
+
+
+
+ ```tsx Zod Schema
+ import { z } from 'zod';
+
+ workflow("new-signup", async ({ step, payload }) => {
+ await step.email(
+ "send-email",
+ async (controls) => {
+ return {
+ subject: controls.subject,
+ body: render(
+
+ ),
+ };
+ },
+ {
+ controlSchema: z.object({
+ hideBanner: z.boolean().default(false),
+ subject: z.string().defaul('This is the default title'),
+ components: z.array(z.object({
+ type: z.enum(['header', 'cta-row', 'footer']),
+ content: z.string()
+ }))
+ })
+ }
+ );
+ });
+ ```
+
+ ```tsx JSON Schema
+ workflow("new-signup", async ({ step, payload }) => {
+ await step.email(
+ "send-email",
+ async (controls) => {
+ return {
+ subject: controls.subject,
+ body: render(
+
+ ),
+ };
+ },
+ {
+ // Learn about JSON Schema here: https://json-schema.org/specification
+ controlSchema: {
+ // Always `object`
+ type: "object",
+ // Specify the properties to validate. Supports deep nesting.
+ properties: {
+ hideBanner: { type: "boolean", default: false },
+ subject: { type: "string" },
+ // Allowing no code control over the component in the Dashboard UI
+ components: {
+ type: "array",
+ items: {
+ type: "object",
+ },
+ properties: {
+ subject: { type: "string" },
+ content: { type: "string" },
+ }
+ },
+ },
+ // Specify the array of which properties are required.
+ required: ["complianceFooter"],
+ // 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,
+ }
+ );
+ });
+ ```
+
+
+## Supported Schema Types
+- **ZodSchema** - A TypeScript-first schema declaration and validation library.
+- **[JSON Schema](/recipes/json-schema)** - The most popular schema language for defining JSON data structures.
+
diff --git a/concepts/endpoint.mdx b/concepts/endpoint.mdx
new file mode 100644
index 00000000..8d8e1280
--- /dev/null
+++ b/concepts/endpoint.mdx
@@ -0,0 +1,68 @@
+---
+title: "Bridge Endpoint"
+---
+
+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.
+
+You can view the Bridge Endpoint as a webhook endpoint that Novu will call when it needs to retrieve contextual information for a given subscriber and notification.
+
+Using the `create-novu-app` command creates a Bridge application for you with a Bridge Endpoint ready to go.
+
+## The `serve` function
+
+We offer framework specific wrappers in form of an exported `serve` function that abstracts away:
+
+- Parsing the incoming request for `GET`, `POST`, `PUT` and `OPTIONS` requests
+- HMAC header authentication
+- Framework specific response and error handling
+
+Currently, we offer `serve` functions for the following frameworks:
+
+- [Next.js](/quickstart/nextjs)
+- [Express.js](/quickstart/express)
+- [Nuxt](/quickstart/nuxt)
+- [h3](/quickstart/h3)
+- [Remix](/quickstart/remix)
+- [Sveltekit](/quickstart/svelte)
+
+## Writing a custom `serve` function
+
+If we currently don't support your framework, you can write a custom `serve` function like the following example:
+
+```ts
+import { type Request, type Response } from "express";
+import { NovuRequestHandler, ServeHandlerOptions } from "@novu/framework";
+
+export const serve = (options: ServeHandlerOptions): any => {
+ const requestHandler = new NovuRequestHandler({
+ frameworkName: "express",
+ ...options,
+ handler: (incomingRequest: Request, response: Response) => ({
+ method: () => incomingRequest.method,
+ headers: (key) => {
+ const header = incomingRequest.headers[key];
+ return Array.isArray(header) ? header[0] : header;
+ },
+ queryString: (key) => {
+ const qs = incomingRequest.query[key];
+ return Array.isArray(qs) ? qs[0] : qs;
+ },
+ body: () => incomingRequest.body,
+ url: () =>
+ new URL(
+ incomingRequest.url,
+ `https://${incomingRequest.headers.get("host") || ""}`
+ ),
+ transformResponse: ({ body, headers, status }) => {
+ Object.entries(headers).forEach(([headerName, headerValue]) => {
+ response.setHeader(headerName, headerValue);
+ });
+
+ return response.status(status).send(body);
+ },
+ }),
+ });
+
+ return requestHandler.createHandler();
+};
+```
diff --git a/platform/environments.mdx b/concepts/environments.mdx
similarity index 61%
rename from platform/environments.mdx
rename to concepts/environments.mdx
index 1fcc0cc1..a22c5949 100644
--- a/platform/environments.mdx
+++ b/concepts/environments.mdx
@@ -1,7 +1,6 @@
---
-title: 'Environments'
-description: 'Learn about environments in Novu'
-icon: 'house-building'
+title: "Environments"
+description: "Learn about environments in Novu"
---
Novu runs all your requests in the context of an environment. By default, Novu creates two environments when your account was just created, `development` and `production`.
@@ -34,25 +33,6 @@ Each environment will be accessed using a separate credential set:
We suggest configuring these key sets based on your active environment, the same as you would use to manage different service credentials and serve them based on the current environment in which your code is deployed.
-## Promoting pending changes to production
+## Promoting changes to production
-After making a change to a workflow or brand relating settings, this change will be added under the [changes](https://web.novu.co/changes?utm_campaign=docs-environments) page in the admin panel.
-
-A change is generated by making a difference between the `development` environment and the target `production` environment. All pending changes will be listed on the [changes](https://web.novu.co/changes?utm_campaign=docs-environments) page.
-
-A change can either be applied manually or by pressing the **Promote all changes** button.
-
-
-
-
-
-
-
- Before pushing a change to production, make sure that the code associated with this change was pushed to production. This is specifically important when adding new variables to a workflow.
-
-
-## API Reference Links
-
-- [Get Current Environment API](/api-reference/environments/get-current-environment/)
-- [Get API Keys API](/api-reference/environments/get-api-keys/)
-- [Regenerate API Keys API](/api-reference/environments/regenerate-api-keys/)
\ No newline at end of file
+When moving changes from the `development` environment to the `production` environment, we suggest using your CI/CD pipeline to promote the changes.
diff --git a/getting-started/concepts.mdx b/concepts/introduction.mdx
similarity index 68%
rename from getting-started/concepts.mdx
rename to concepts/introduction.mdx
index 2218d255..891320df 100644
--- a/getting-started/concepts.mdx
+++ b/concepts/introduction.mdx
@@ -1,12 +1,11 @@
---
-title: 'Concepts'
-description: 'Learn about the key concepts of Novu'
-icon: 'building-columns'
+title: "Introduction"
+description: "Learn about the key concepts of Novu"
---
## Notification
-A notification conveys information from source to recipient, triggered by a workflow acting as a message blueprint. Notifications can be individual or bundled as [digest](/workflows/digest) for user-friendliness.
+A notification conveys information from source to recipient, triggered by a workflow acting as a message blueprint. Notifications can be individual or bundled as [digest](/workflows/digest) for user-friendliness.
## Messages
@@ -18,7 +17,7 @@ All notifications are sent via a workflow. Each workflow acts as a container for
## Channel
-A channel in Novu represents a configured provider, such as Sendgrid for email, to send notifications to your recipients. A channel is the communication-context domain with the recipients (subscribers).
+A channel in Novu represents a configured provider, such as Sendgrid for email, to send notifications to your recipients. A channel is the communication-context domain with the recipients (subscribers).
Most providers within Novu use credentials that you supply to deliver notifications on your behalf. These credentials and other settings are what make a configured channel. [Learn more](/channels-and-providers/introduction)
@@ -47,13 +46,7 @@ Providers are the channel service providers (Twilio, Sendgrid, APN, etc,) you c
- Production
- Development
-Novu uses the concept of environments to ensure logical separation of your data and configuration. This means that subscribers, and preferences created in one environment are **never** accessible to another. [Learn more about environments.](/platform/environments)
-
-## Handlebars & Helpers
-
-Handlebars is a simple templating language that generates HTML.
-
-Novu-specific Helpers make it possible to define custom iterators and other functionality that can invoke the passed block with a new context. [Learn more about helpers.](/content-creation-design/handlebars-helpers)
+Novu uses the concept of environments to ensure logical separation of your data and configuration. This means that subscribers, and preferences created in one environment are **never** accessible to another. [Learn more about environments.](/platform/environments)
## Organization
@@ -63,31 +56,11 @@ Switching your organization in the UI only affects the UI and does not deactivat
Keep in mind that workflows and integration stores for one organization cannot be used for subscribers of other organizations.
-
-
-To create a new organization, you interact with a drop down menu in the bottom of the left navigation bar within Novu’s application. Type the name of your new organization, and if the name is new, you will see a button that enables you to add a new one.
-
-
-
-
-To switch between organizations, you again interact with the same drop down menu and switch between the organizations you have in your Novu account.
-
-
+## Inbox
-## Notification Center
+The Inbox is a beautifully designed and highly functional in-app experience for your users that you can add to your product quickly and effortlessly.
-Notification Center is a beautifully designed and highly functional in-app experience for your users that you can add to your product quickly and effortlessly.
-
-The core components of our Notification Center are:
+The core components of the component:
- A list of notifications with real-time updates
- Notification preference management
@@ -96,22 +69,10 @@ The core components of our Notification Center are:
[Learn more](/notification-center/introduction)
-## Preference
+## Subscriber Preference
A preference indicates a user's willingness to receive a particular type of notification. Preferences always belong to a user and can be paired with an identifier that represents the account or tenant that the user belongs to (for multi-tenant applications). [Learn more](/subscribers/preferences)
-## Delay Actions
-
-The delay action awaits a specified amount of time before moving on to trigger the following steps of the workflow. [Learn more](/workflows/delay-action)
-
-## Digest
-
-The digest engine collects multiple trigger events, aggregates them into a single message and delivers it to the subscriber. [Learn more](/workflows/digest)
-
-## 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. [Learn more](/content-creation-design/layouts)
-
## Tenants
-A tenant represents a group of users. As a developer, when your apps have organizations, they are referred to as tenants. Tenants in Novu provides the ability to tailor specific notification experiences to users of different **groups** or **organizations**. [Learn more about Novu Tenants.](/tenants/introduction)
\ No newline at end of file
+A tenant represents a group of users. As a developer, when your apps have organizations, they are referred to as tenants. Tenants in Novu provides the ability to tailor specific notification experiences to users of different **groups** or **organizations**. [Learn more about Novu Tenants.](/tenants/introduction)
diff --git a/concepts/payload.mdx b/concepts/payload.mdx
new file mode 100644
index 00000000..6039892f
--- /dev/null
+++ b/concepts/payload.mdx
@@ -0,0 +1,57 @@
+---
+title: "Payload"
+---
+
+Workflow payload is the data passed during the `novu.trigger` method. This is useful for ensuring that the payload is correctly formatted and that the data is valid.
+
+## Payload Schema
+
+Payload schema is defining the payload passed during the `novu.trigger` method. This is useful for ensuring that the payload is correctly formatted and that the data is valid.
+
+```tsx
+workflow(
+ "comment-on-post",
+ async ({ step, payload }) => {
+ await step.email("send-email", async () => {
+ return {
+ subject: `You have a new comment from: ${payload.author_name}.`,
+ body: render(),
+ };
+ });
+ },
+ {
+ payloadSchema: {
+ // Always `object`
+ type: "object",
+ // Specify the properties to validate. Supports deep nesting.
+ properties: {
+ post_id: { type: "number" },
+ author_name: { type: "string" },
+ comment: { type: "string", maxLength: 200 },
+ },
+ // Specify the array of which properties are required.
+ required: ["post_id", "comment"],
+ // 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,
+ }
+);
+```
+
+## Passing Payload
+
+Here is an example of the validated payload during trigger:
+
+```tsx
+novu.trigger("comment-on-post", {
+ to: "subscriber_id",
+ payload: {
+ post_id: 1234,
+ author_name: "John Doe",
+ comment: "Looks good!",
+ },
+});
+```
diff --git a/subscribers/preferences.mdx b/concepts/preferences.mdx
similarity index 53%
rename from subscribers/preferences.mdx
rename to concepts/preferences.mdx
index 63920399..a67ca2cb 100644
--- a/subscribers/preferences.mdx
+++ b/concepts/preferences.mdx
@@ -1,6 +1,5 @@
---
title: "Preferences"
-icon: "layer-group"
---
Novu provides a way to store user preferences in the subscribers data model.
@@ -14,20 +13,13 @@ This allows subscribers to specify and manage their preferences, without your in
## Workflow level channel preferences
-When creating a new workflow on the Web platform, you can specify default preferences for the subscribers in channel settings. They will be used unless the subscriber overrides them by his own custom preference.
+When creating a new workflow, you can specify default preferences for the subscribers in channel settings. They will be used unless the subscriber overrides them by his own custom preference.
-This will allow you to create sensible defaults but still provide the user with the ability to override them. Template level preference can be managed in channel settings. All channels are `ON` unless specified otherwise.
-
-`Workflow Settings > Channels`
-
-
+This will allow you to create sensible defaults but still provide the user with the ability to override them. All channels are `ON` unless specified otherwise.
## Subscriber level channel preferences
-Our notification center component will show a user the available preferences, user will be able to modify on the channel level. Critical workflows will be excluded from the list. Click on cog (setting) icon on notification center component to open subscriber channel preferences page.
+Our Inbox component will show a user the available preferences, user will be able to modify on the channel level. Critical workflows will be excluded from the list. Click on cog (setting) icon on notification center component to open subscriber channel preferences page.
Only channels with a matched step will be returned from the API in
- notification center preference page. In case no channel content was found, the
+ Ibox preference page. In case no channel content was found, the
API will return an empty array.
## Global level channel preferences
-Since v0.20.0
Subscribers can set global channel preferences, which override individual settings. For instance, if there are 10 workflows, and a subscriber wants to disable SMS notifications for all of them, they can do so with a single global preference.
-### Get subscriber global preference
-
-
-
-
-```javascript
-import { Novu } from '@novu/node';
-
-const novu = new Novu('');
-
-await novu.subscribers.getGlobalPreference("subscriberId" );
-```
-
-
-
-
-[Get subscriber's global preference API](/api-reference/subscribers/get-subscriber-global-preferences)
-
-### Update subscriber global preference
-
-
-
-
-
-```javascript
-import { Novu } from '@novu/node';
-
-const novu = new Novu('');
-
-// enable in-app channel and disable email channel
-await novu.subscribers.updateGlobalPreference("subscriberId", {
- enabled: true,
- preferences: [{
- type: "in_app"
- enabled: true
- }, {
- type: "email"
- enabled: false
- }]
-});
-```
-
-
-
-
-[Update subscriber's global preference API](/api-reference/subscribers/update-subscriber-global-preference)
-
-Global subscriber preference can be updated and accessed using API and SDK only. Currently we have not added support of global subscriber preference in UI.
+
+ Global subscriber preference can be updated and accessed using API and SDK
+ only. Currently we have not added support of global subscriber preference in
+ UI.
+
## Exclude workflows from preferences (critical workflow)
In some cases, you don't want the subscriber to be able to unsubscribe from mandatory notifications such as Account Verification, Password Reset, etc...
-In those cases you can turn off the toggle `Users will be able to manage subscriptions` in channel settings. Workflow will become `critical`, once this toggle is turned `OFF`. By default, every workflow is `non-critical` and subscribers can manage channel preferences irrespective of workflow-level channel preferences. Critical workflow will not show on the subscriber preferences page.
-
-## Get subscriber preferences
-
-
-
-
-
-```javascript
-import { Novu } from "@novu/node";
-
-const novu = new Novu("");
-
-// 111 is subscriberId
-await novu.subscribers.getPreference("111");
-```
-
-
-
-
-```php
-use Novu\SDK\Novu;
-
-$novu = new Novu('');
-
-// 111 is subscriberId
-$novu->getSubscriberPreferences('111')->toArray();
-```
-
-
-
-
-## Get subscriber preference by level
-
-
-
-
-
-```javascript
-import { Novu, PreferenceLevelEnum } from '@novu/node';
-
-const novu = new Novu('');
-// Get global level preference
-await novu.subscribers.getPreferenceByLevel("subscriberId", PreferenceLevelEnum.GLOBAL)
-
-// Get template level preference
-await novu.subscribers.getPreferenceByLevel("subscriberId", PreferenceLevelEnum.TEMPLATE);
-```
-
-
-
-
-## Update subscriber preference for a workflow
-
-
-
-
-
-```javascript
-import { Novu, ChannelTypeEnum } from "@novu/node";
-
-const novu = new Novu("");
-
-// enable in_app channel
-await novu.subscribers.updatePreference("subscriberId", "workflowIdentifier", {
- enabled: true,
- channel: { type: ChannelTypeEnum.IN_APP, enabled: true },
-});
-
-// enable email channel
-await novu.subscribers.updatePreference("subscriberId", "workflowIdentifier", {
- enabled: true,
- channel: { type: ChannelTypeEnum.EMAIL, enabled: true },
-});
-```
-
-
-
-
-```php
-use Novu\SDK\Novu;
-
-$novu = new Novu('');
-
-// enable in_app channel
-$novu->updateSubscriberPreference('subscriberId', 'workflowIdentfier', [
- 'enabled' => true
- 'channel' => [
- 'type' => 'in_app',
- 'enabled' => true
- ]
-]);
-
-// enable email channel
-$novu->updateSubscriberPreference('subscriberId', 'workflowIdentfier', [
- 'enabled' => true
- 'channel' => [
- 'type' => 'email',
- 'enabled' => true
- ]
-]);
-```
-
-
-
+In those cases you can mark a workflow as `critical` in workflow settings. By default, every workflow is `non-critical` and subscribers can manage channel preferences irrespective of workflow-level channel preferences. Critical workflow will not show on the subscriber preferences page.
## Order of priority of preferences
@@ -315,13 +159,15 @@ $novu->updateSubscriberPreference('subscriberId', 'workflowIdentfier', [
This field can only be changed using API.
-
- In the case of a new workflow, the subscriber will inherit all preferences
- from the workflow.However, after subsequent preference updates, the
- subscriber's preferences will not inherit workflow-level preferences.
-
+{" "}
+
+ In the case of a new workflow, the subscriber will inherit all preferences
+ from the workflow.However, after subsequent preference updates, the
+ subscriber's preferences will not inherit workflow-level preferences.
+
You can turn off all workflow's channels for a subscriber using [subscriber preference](/subscribers/preferences#subscriber-level-channel-preferences). If all channels are off, then the subscriber will not receive any message from any channel step and hence workflow is disabled for that subscriber
+
diff --git a/concepts/subscribers.mdx b/concepts/subscribers.mdx
new file mode 100644
index 00000000..2d3c6edc
--- /dev/null
+++ b/concepts/subscribers.mdx
@@ -0,0 +1,193 @@
+---
+title: "Subscribers"
+---
+
+In Novu, we call the entities designed to receive notifications as `Subscribers`. Each subscriber is unique and identified by a unique subscriberId.
+
+
+ We recommend using the internal unique id your application uses for a specific
+ user as the `subscriberId`.
+
+
+Each subscriber has the following data points:
+
+- **User Data** - Data stored in the subscriber object that you can easily access in your notification templates. This contains basic info such as first name, last name, avatar, locale, email, and phone. This data is fixed and structured.
+- **Custom Data** - Apart from the above fixed structured user data, any unstructured custom data such as user's address, nationality, height, etc can also be stored in the `data` field using key-value pairs.
+- **Channel Specific Credentials** - `deviceTokens` required to send push notifications and `webhookUrl` for chat channel providers can also be stored.
+
+## Subscriber attributes
+
+| Field | Type | Required | Example |
+| :----------- | :----- | :------- | :------------------------------------ |
+| subscriberId | string | true | b0bea066-f5fe-11ed-b67e-0242ac120002 |
+| firstName | string | false | John |
+| lastName | string | false | Doe |
+| email | string | false | john.doe@domain.org. |
+| phone | string | false | +13603963366 |
+| locale | string | false | en |
+| avatar | string | false | https://example.com/images/avatar.jpg |
+| data | object | false | `{"key": "value"}` |
+
+## Subscriber response schema
+
+**Novu subscriber object**
+
+```json
+{
+ "_id": "NOVU_GENERATED_SUBSCRIBER_ID",
+ "_organizationId": "NOVU_GENERATED_ORG_ID",
+ "_environmentId": "NOVU_GENERATED_ENV_ID",
+ "firstName": "John",
+ "lastName": "Doe",
+ "subscriberId": "subscriberId",
+ "email": "[john.doe@org.com](mailto:john.doe@org.com)",
+ "phone": "+98712345670"
+ "data": {
+ "custome_key_1" : "custom_value_1",
+ "custome_key_2" : "custom_value_2"
+ }
+ "channels": [
+ {
+ "credentials": {
+ "deviceTokens": [
+ "token1",
+ "token2"
+ ]
+ },
+ "_integrationId": "NOVU_GENERATED_INTEGRATION_ID",
+ "providerId": "fcm"
+ },
+ {
+ "credentials": {
+ "webhookUrl": "URL"
+ },
+ "_integrationId": "NOVU_GENERATED_INTEGRATION_ID",
+ "providerId": "discord"
+ }
+ ],
+ "deleted": false,
+ "createdAt": "2022-10-13T17:40:53.231Z",
+ "updatedAt": "2022-10-13T17:41:53.238Z",
+ "__v": 0,
+ "isOnline": false,
+ "lastOnlineAt": "2022-10-13T17:41:53.238Z",
+ "avatar": "AVATAR_URL",
+ "id": "NOVU_GENERATED_SUBSCRIBER_ID"
+}
+```
+
+## Creating a subscriber
+
+We support creating new subscriber using two ways, `Ahead of Trigger` means adding subscribers before triggering notification or `Just-in-time` means sending complete subscriber data in `to` field while triggering.
+
+### Just-in-time
+
+A non-existing subscriber can be added by sending subscriber data in `to` field of the trigger method. If any subscriber with provided `subscriberId` does not exists, a new subscriber will be created. In this case, subscriber will be created first and then the trigger will be executed synchronously.
+
+
+
+ ```jsx
+ import { Novu } from '@novu/node';
+
+ const novu = new Novu('');
+
+ await novu.trigger('', {
+ to: {
+ subscriberId: '111',
+ email: 'john.doe@domain.com',
+ firstName: 'John',
+ lastName: 'Doe',
+ phone: '+13603963366',
+ },
+ payload: {
+ customVariable: 'variableValue',
+ organization: {
+ logo: 'https://organization.com/logo.png',
+ },
+ },
+ });
+ ```
+
+
+ ```php
+ use Novu\SDK\Novu;
+
+ $novu = new Novu('');
+
+ $novu->triggerEvent([
+ 'name' => '',
+ 'to' => [
+ 'subscriberId' => '111',
+ 'email' => 'john.doe@domain.com',
+ 'firstName' => 'John',
+ 'lastName' => 'Doe',
+ 'phone' => '+13603963366'
+ ]
+ 'payload' => [
+ 'customVariable' => 'variableValue',
+ 'organization' => [
+ 'logo' => 'https://organization.com/logo.png',
+ ]
+ ],
+ ]);
+ ```
+
+
+
+
+You can also pass only the `subscriberId` during a request, and hydrate the data directly from your database or other sources during the trigger execution. This is useful when you don't want to store all the subscriber data in Novu.
+
+### Migration (Optional)
+
+Create the subscriber and then trigger the notification to this subscriber. Here `subscriberId` is the required field and other fields are optional.
+
+
+
+```jsx
+import { Novu } from '@novu/node';
+
+const novu = new Novu('');
+
+await novu.subscribers.identify('111', {
+ email: 'john.doe@domain.com',
+ firstName: 'John',
+ lastName: 'Doe',
+ phone: '+13603963366',
+ avatar: 'https://example.com/images/avatar.jpg',
+ locale: 'en-US',
+ data: { customKey1: 'customVal1', customKey2: 'customVal2' },
+});
+
+````
+
+
+
+```php
+use Novu\SDK\Novu;
+
+$novu = new Novu('');
+
+$novu->createSubscriber([
+ 'subscriberId' => '111',
+ 'email' => 'john.doe@domain.com',
+ 'firstName' => 'John',
+ 'lastName' => 'Doe',
+ 'phone' => '+13603963366',
+ 'avatar' => 'https://example.com/images/avatar.jpg',
+ 'locale' => 'en',
+ 'data' => [
+ 'customKey1' => 'customVal1',
+ 'customKey2' => 'customVal2'
+ ]
+]);
+````
+
+
+
+
+Novu will create a subscriber if one does not exist and will update the existing subscriber based on the `identify` payload. You can call this function during registration or signup to make sure the subscriber data is up-to-date, if you wish to save additional attributes with a subscriber, you can pass additional custom data in the **data** field as key-value pairs.
+
+## Bulk Subscriber Creation
+
+You can create subscribers in bulk _(up to 500 at once)_ via the SDKs or [API](/api-reference/subscribers/bulk-create-subscribers).
+
diff --git a/concepts/tenants.mdx b/concepts/tenants.mdx
new file mode 100644
index 00000000..633eb33e
--- /dev/null
+++ b/concepts/tenants.mdx
@@ -0,0 +1,81 @@
+---
+title: "Tenants"
+description: "Learn all about Tenants"
+---
+
+Multi-tenancy is a common use case for a lot of companies that have multiple organizations that use their applications. In some cases, there is a need to separate the behavior of the notification system depending on the individual tenants.
+
+Currently, Novu supports the following customizations:
+
+- Workflow level customizations
+- Integration customizations
+
+## Tenant Management
+
+Tenants can be created and modified via the [API](http://docs.novu.co/api-reference/tenants/get-tenants) or [Web](https://dashboard.novu.co/tenants?utm_campaign=docs-tenants). Each tenant can have multiple fields on it:
+
+- Identifier - The identifier is a unique value, and can be used later when pointing to this tenant during trigger calls.
+- Name - A human-readable name of the tenant.
+- Data - A custom data object that can store information about the tenant. This data can be later accessed inside workflows.
+
+## Workflow Level Customizations
+
+When triggering a workflow, it is possible to pass the tenant information (id or object, in case of an object, novu will upsert the tenant if it’s not existing) like so:
+
+
+
+ ```javascript
+ import { Novu } from '@novu/node';
+
+ const novu = new Novu("");
+
+ await novu.trigger('',
+ {
+ to: {
+ subscriberId: '',
+ },
+ payload: {
+ name: "Hello World",
+ },
+ actor: "actorId"
+ tenant: "tenantIdentifier"
+ }
+ );
+
+````
+
+
+```php
+ use Novu\SDK\Novu;
+
+ $novu = new Novu('');
+
+ $novu->triggerEvent([
+ 'name' => '',
+ 'payload' => [
+ 'name' => 'Hello'
+ ],
+ 'to' => [
+ 'subscriberId' => ''
+ ],
+ 'actor': "actorId"
+ 'tenant': "tenantIdentifier"
+ ]);
+````
+
+
+
+
+## Integration Level Customizations
+
+When creating an integration, you can create a condition where you can specify a delivery provider for a channel when a particular tenant id is matched.
+
+The delivery provider specified will only be used if the trigger is executed with the tenant id.
+
+
+
+
+
+
+
+
diff --git a/subscribers/topics.mdx b/concepts/topics.mdx
similarity index 73%
rename from subscribers/topics.mdx
rename to concepts/topics.mdx
index 44b37dcb..cc533a8b 100644
--- a/subscribers/topics.mdx
+++ b/concepts/topics.mdx
@@ -1,12 +1,12 @@
---
-title: 'Topics'
-icon: 'people'
+title: "Topics"
---
Novu offers a simple API providing an easy interface for triggering notifications to multiple subscribers at once. It is called Topics and allows the users to manage their bulk notifications without having to do complex loop implementations. A topic is identified by a custom key that is provided by the user. This custom key will be the identifier for the topic.
-The topic key should be unique and can't be changed once chosen. Novu also safe guards for key uniqueness behind the scenes.
+ The topic key should be unique and can't be changed once chosen. Novu also
+ safe guards for key uniqueness behind the scenes.
Users can also assign a name to a topic. This name doesn't need to be unique and it can be changed using the API. So far, it is for descriptive goals.
@@ -18,13 +18,13 @@ A topic would get assigned different subscribers that will receive a notificatio
In order to be able to send a notification to a topic, first the user needs to create one. It can be done like this:
```typescript
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
const result = await novu.topics.create({
- key: 'unique-topic-identifier',
- name: 'descriptive-topic-name',
+ key: "unique-topic-identifier",
+ name: "descriptive-topic-name",
});
```
@@ -33,11 +33,11 @@ If successful this will return the internal Id generated by Novu and the topic k
That topic key can be used to retrieve the whole Topic entity:
```typescript
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
-const key = 'unique-topic-identifier';
+const key = "unique-topic-identifier";
const result = await novu.topics.get(key);
```
@@ -47,12 +47,12 @@ const result = await novu.topics.get(key);
Descriptive name given during creation of topic can be changed later. This can be done like this:
```typescript
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
-const topicKey = 'posts:comment:12345';
-const topicName = 'Post Comments';
+const topicKey = "posts:comment:12345";
+const topicName = "Post Comments";
const result = await novu.topics.rename(topicKey, topicName);
```
@@ -66,7 +66,11 @@ This will return the whole Topic information, including the subscribers if havin
Adding subscribers to the topic is the main usecase of topic. A topic is like a group of subscribers. A notification can be sent to all subscribers of a topic at once
- Before adding subscribers to a topic, it's crucial to ensure that they are correctly identified in the Novu system. This identification is done using the [identify method](/subscribers/subscribers#create-a-subscriber) or API. When a subscriber is added to a topic, Novu uses the identification information to pick up the email or phone number associated with the subscriber.
+ Before adding subscribers to a topic, it's crucial to ensure that they are
+ correctly identified in the Novu system. This identification is done using the
+ [identify method](/subscribers/subscribers#create-a-subscriber) or API. When a
+ subscriber is added to a topic, Novu uses the identification information to
+ pick up the email or phone number associated with the subscriber.
```typescript
@@ -94,12 +98,11 @@ This call will return a response in the shape of:
The field `succeeded` will return the array of subscriber ids that have been correctly assigned to the topic. The field `failed` will show up only if there has been any subscriber that couldn't been assigned to the topic. This probably will happen if there is any typo in the given subscriberId or if the given subscriberId doesn't belong to the environment and the organization where the topic has been created.
-
### Create topic on the fly
-To facilitate flows we allow to create a topic on the fly when adding subscribers.
+To facilitate flows we allow to create a topic on the fly when adding subscribers.
-If the topic key used does not exist for the selected environment and organization, Novu will create a new topic with name `Autogenerated-` and the subscribers will be assigned to this newly created topic.
+If the topic key used does not exist for the selected environment and organization, Novu will create a new topic with name `Autogenerated-` and the subscribers will be assigned to this newly created topic.
After that, that topic created on the fly can be managed in the same ways as the ones created in the normal way.
@@ -108,19 +111,23 @@ After that, that topic created on the fly can be managed in the same ways as the
There would be times when it would be needed to verify if a certain subscriber belongs to a topic in order to decide what to do with that subscriber. The API call to achieve that is the following:
```typescript
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
-const externalSubscriberId = 'external-subscriber-id-1';
-const topicKey = 'posts:comment:12345';
+const externalSubscriberId = "external-subscriber-id-1";
+const topicKey = "posts:comment:12345";
-const response = await novu.topics.getSubscriber(topicKey, externalSubscriberId);
+const response = await novu.topics.getSubscriber(
+ topicKey,
+ externalSubscriberId
+);
```
-The subscriberId to use in this API call is the one used as subscriber identifier.
-The choice was made to make easier for the user to use this without making extra calls to Novu.
+ The subscriberId to use in this API call is the one used as subscriber
+ identifier. The choice was made to make easier for the user to use this
+ without making extra calls to Novu.
## Remove a subscriber from a Topic
@@ -146,17 +153,19 @@ Where `subscribers` will be an array of the subscriberIds we want to remove fr
An existing topic can be deleted using topic-key as topic-key is the unique identifier for a topic.
```typescript
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
-const key = 'unique-topic-identifier';
+const key = "unique-topic-identifier";
const result = await novu.topics.delete(key);
```
-A topic can only be deleted if it doesn't have any subscriber added. When trying to delete a topic with subscribers a conflict error will be returned. This is done to prevent accidental topic deletions.
+ A topic can only be deleted if it doesn't have any subscriber added. When
+ trying to delete a topic with subscribers a conflict error will be returned.
+ This is done to prevent accidental topic deletions.
## Trigger workflow to a topic
@@ -164,10 +173,10 @@ A topic can only be deleted if it doesn't have any subscriber added. When trying
A workflow can be triggered to a single subscriber and an array of subscribers. While doing so, one need to send subscriberIds in `to` field. In case of trigger, we have already stored subscriberIds in a topic, so a topic key can be used to trigger a workflow. Workflow will be triggered to all subscribers in the topic.
```typescript
-const topicKey = 'posts:comment:12345';
+const topicKey = "posts:comment:12345";
-await novu.trigger('', {
- to: [{ type: 'Topic', topicKey: topicKey }],
+await novu.trigger("", {
+ to: [{ type: "Topic", topicKey: topicKey }],
payload: {},
});
```
@@ -177,12 +186,12 @@ await novu.trigger('', {
Workflow can be triggered to multiple subscribers by using an array of topics.
```typescript
-const topicKey = '';
+const topicKey = "";
-await novu.trigger('', {
+await novu.trigger("", {
to: [
- { type: 'Topic', topicKey: topicKey },
- { type: 'Topic', topicKey: 'Another Topic Key' },
+ { type: "Topic", topicKey: topicKey },
+ { type: "Topic", topicKey: "Another Topic Key" },
],
payload: {},
});
@@ -193,12 +202,12 @@ await novu.trigger('', {
To exclude the actor responsible for the action of a triggered topic event, you must add the subscriberId of that actor when triggering that event.
```typescript
-const topicKey = 'posts:comment:12345';
+const topicKey = "posts:comment:12345";
-await novu.trigger('', {
- to: [{ type: 'Topic', topicKey: topicKey }],
+await novu.trigger("", {
+ to: [{ type: "Topic", topicKey: topicKey }],
payload: {},
- actor: { subscriberId: '' },
+ actor: { subscriberId: "" },
});
```
@@ -227,7 +236,7 @@ User X makes a comment, other users (A, B) who've already commented before shoul
color="#16a34a"
href="/api-reference/topics/subscribers-addition"
>
-
-
-
-
- No, adding subscribers into topic does not change subscriber's individual [subscriber preference](/subscribers/preferences). Topic is mainly used to group subscribers and fan out workflow triggered notifications to all subscribers at once.
+ No, adding subscribers into topic does not change subscriber's individual
+ [subscriber preference](/subscribers/preferences). Topic is mainly used to
+ group subscribers and fan out workflow triggered notifications to all
+ subscribers at once.
diff --git a/concepts/trigger.mdx b/concepts/trigger.mdx
new file mode 100644
index 00000000..46520967
--- /dev/null
+++ b/concepts/trigger.mdx
@@ -0,0 +1,52 @@
+---
+title: "Trigger"
+description: "Managing Trigger Events from Request to Processing"
+---
+
+## Trigger Request
+
+A trigger request is the initial step in handling a trigger event. It contains crucial details such as the template identifier, a list of subscribers who will receive the notification, the payload of the notification, and any overrides that need to be applied.
+
+## Trigger Endpoint
+
+Upon sending the request to the `/event/trigger` endpoint, a series of essential steps are initiated:
+
+1. **Subscriber Mapping and Validation:** The first step involves mapping and validating the subscribers for the specified event. This ensures that notifications are sent to the correct recipients.
+
+2. **Workflow Validation:** Following subscriber validation, the workflow associated with the event is validated. This validation process considers factors such as the active status to determine if it meets the necessary criteria for processing.
+
+3. **Attachment Upload:** Once the validation process is successfully completed, any attachments associated with the event are uploaded to the designated storage service.
+
+4. **Event Queuing:** The trigger event, now enriched with mapped subscribers and attachment links, is appended to the **trigger event queue**. This queuing mechanism optimizes response times, ensuring efficient event processing.
+
+## Trigger Event Processing
+
+When an event is picked up by the **trigger queue worker**, the processing phase begins. Here's what happens:
+
+- **Subscriber Upsert:** The worker validates the subscribers associated with the event and either creates or updates the subscriber with the information passed in the `to` object.
+- **Notification Entity Creation:** For each subscriber listed in the trigger event, a corresponding notification entity is created. This entity contains essential data related to the organization, template, subscriber, and event payload.
+- **Job Creation:** Based on the notification template's defined steps, jobs are generated. These jobs are responsible for carrying out specific tasks related to the event notification. Additionally, the notification entity is updated with a "channels" field generated from these steps, indicating the communication channels through which notifications will be sent.
+
+## Jobs
+
+Jobs play a crucial role in the trigger event lifecycle. They are created based on the steps outlined in the workflow.
+
+### Job Statuses
+
+| Status | Description |
+| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **PENDING** | This status is assigned to a job before it is added to the worker queue. It indicates that the job is waiting to be processed. |
+| **QUEUED** | After the initial validation and just before adding a job to the worker queue, it is set to `QUEUED`. This status signifies that the job is ready for processing but is awaiting its turn in the queue. |
+| **RUNNING** | When a job is picked up by a worker from the queue, its status is changed to `RUNNING`. This indicates that the job is currently being processed by a worker. |
+| **COMPLETED** | Once a job has been successfully executed and processed, its status is changed to `COMPLETED`. This signifies that the job has been successfully completed. |
+| **FAILED** | If a job encounters an issue during processing or execution, its status is changed to `FAILED`. This indicates that the job has not been successfully completed, and there may have been errors or problems during processing. |
+| **DELAYED** | The `DELAYED` status is applied to specific types of jobs, such as `digest` or `delay` jobs, to indicate that they are delayed and not immediately processed. For `digest` jobs, it means that the digesting process is running or scheduled for a later time. For `delay` jobs, it signifies that the job is set to be executed at a specified delay time. |
+| **CANCELED** | When a job is canceled for any reason, its status is set to `CANCELED`. This indicates that the job will not be processed further and is effectively removed from the processing queue. |
+| **MERGED** | The `MERGED` status is assigned to events that are part of a `digest`. It indicates that an event will be merged into the digesting event. In a digesting process, there is typically a primary or initial event that serves as the digesting event, and subsequent events are merged into it. Instead of having a separate `COMPLETED` status for these merged events, they are marked as `MERGED` to indicate their specific role in the digesting process. |
+| **SKIPPED** | The `SKIPPED` status is used in the context of backoff versions of digesting. In this scenario, the first event's digesting is skipped, and the second event takes on the digesting role. The `SKIPPED` status is applied to the first event's digesting, indicating that it was intentionally skipped in the digesting process. Subsequent events may be merged into the second event's digesting process, as explained with the `MERGED` status. The `SKIPPED` status helps differentiate the skipped event from others in the digesting sequence. |
+
+**Example:**
+
+
+ {" "}
+
diff --git a/concepts/workflows.mdx b/concepts/workflows.mdx
new file mode 100644
index 00000000..a92cc733
--- /dev/null
+++ b/concepts/workflows.mdx
@@ -0,0 +1,51 @@
+---
+title: "Workflows"
+description: "Workflows are at the core of responding to events in your system with notifications. Novu Framework enables you to declare type-safe, validated, and version-controlled Workflows with code."
+---
+
+A workflow holds the entire flow of steps (nodes) that are sent to the subscriber. This is where all the different channels are tied together under a single entity.
+
+## Structure
+
+A workflow acts as the blueprint for the notifications that will be sent. This is where all the different channels, filters, rules and actions are tied together under a single entity.
+
+
+
+## Workflow Components
+
+
+
+ Every workflow will have a name and an identifier that are used to uniquely identify each workflow.
+
+
+ The "Trigger" refers to an event or action that initiates the workflow. It signifies a call to the Novu API with a specified workflow ID, along with the necessary payload data that the workflow content will utilize.
+
+
+ Within the Novu framework, steps are categorized into various types, each of which is linked with at least one corresponding action:
+
+ #### Channel Steps
+ - **Email** (examples include Sendgrid, Postmark)
+ - **Inbox** (such as feeds, toasts, banners)
+ - **Push** (such as APNS, FCM)
+ - **SMS** (examples include Twilio, Telnyx)
+ - **Chat** (such as Slack, Microsoft Teams, and Discord)
+
+ #### Action Steps
+ - **Delay** (to pause the workflow for a specified duration)
+ - **Digest** (to group multiple notifications into a single message)
+ - **Custom** (to execute custom logic like calling an HTTP API, database query, etc.)
+
+
+
+
+## Execution of Workflow Steps
+
+Once a workflow is initiated by its trigger, the steps within the workflow are executed in a specific sequence. This sequential execution ensures that each step is completed before the next one begins, maintaining a controlled and orderly flow of the notification process. Here's what you need to know about this process:
+
+Each step in the workflow is activated one after the other, in the order they are listed within the workflow. This method ensures that each step is given the necessary attention and that dependencies or prerequisites of later steps are adequately met.
+Sequential execution provides a predictable and reliable workflow process, ensuring that messages are sent out in an orderly manner and that each step's output can appropriately influence subsequent steps.
+
+Read more about building workflows [here](/workflow/introduction).
\ No newline at end of file
diff --git a/content-creation-design/brand.mdx b/content-creation-design/brand.mdx
index 730be182..f4b826d8 100644
--- a/content-creation-design/brand.mdx
+++ b/content-creation-design/brand.mdx
@@ -1,14 +1,11 @@
---
-title: 'Brand'
-description: ''
-icon: 'sparkle'
+title: "Brand"
+description: ""
+icon: "sparkle"
---
Through Novu's web dashboard, you have the power to effortlessly tailor your brand settings, streamlining the process of creating notifications. Customize key elements such as your logo, which will be seamlessly integrated into your email communications.
For those utilizing Novu's In-App notification center, the ability to configure the primary font and its corresponding color awaits you. This empowers you to craft an experience for your users that resonates with your unique brand identity.
-
+
diff --git a/content-creation-design/handlebars-helpers.mdx b/content-creation-design/handlebars-helpers.mdx
index c183973a..6f9b7ff6 100644
--- a/content-creation-design/handlebars-helpers.mdx
+++ b/content-creation-design/handlebars-helpers.mdx
@@ -1,39 +1,39 @@
---
-title: 'Handlebars & Helpers'
-description: ''
-icon: 'brackets-curly'
+title: "Handlebars & Helpers"
+description: ""
+icon: "brackets-curly"
---
+
# Handlebars
-The Novu notification content editor relies on Handlebars.js to establish the logic and control flow of our workflows.
-For a deeper comprehension of Handlebars.js, you can refer to its [documentation](https://handlebarsjs.com/guide/#what-is-handlebars).
+The Novu notification content editor relies on Handlebars.js to establish the logic and control flow of our workflows.
+For a deeper comprehension of Handlebars.js, you can refer to its [documentation](https://handlebarsjs.com/guide/#what-is-handlebars).
This resource offers comprehensive insights into the utilization of Handlebars.js in crafting dynamic and adaptable notification content within the Novu platform.
-| Helper | Description | Example | Output |
-| --------------- | -------------------------------------------------------- | ------------------------------------------------ | ---------------------------------------------------- |
-| if | Conditionally renders a block. Falsy values won't be rendered. | `{{#if author}}
{{firstName}} {{lastName}}
{{/if}}` | Renders `
Yehuda Katz
` 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. |
-
-
+| Helper | Description | Example | Output |
+| --------------- | ------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------- |
+| if | Conditionally renders a block. Falsy values won't be rendered. | `{{#if author}}
{{firstName}} {{lastName}}
{{/if}}` | Renders `
Yehuda Katz
` 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`. |
+| 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.
@@ -78,8 +78,8 @@ This resource offers comprehensive insights into the utilization of Handlebars.j
-
### equals
+
`equals` helper allows you to perform comparisons, both for boolean expressions and string comparisons.
@@ -92,9 +92,10 @@ This resource offers comprehensive insights into the utilization of Handlebars.j
{{/equals}}
-
+
{{#equals 10 1}}
+
10 is equal to 1
{{else}}
10 is not equal to 1
@@ -117,6 +118,7 @@ This resource offers comprehensive insights into the utilization of Handlebars.j
### numberFormat
+
`numberFormat` helper is used to format numbers with specified decimal length, thousands separator, and decimal separator.
@@ -143,6 +145,7 @@ This resource offers comprehensive insights into the utilization of Handlebars.j
### 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
@@ -190,7 +193,7 @@ In this code, we iterate through the `step.events` array and conditionally displ
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
+### 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.
@@ -227,6 +230,10 @@ 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)
-
+
+ {" "}
+ 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
index aac84e8f..84a9ec8f 100644
--- a/content-creation-design/layouts.mdx
+++ b/content-creation-design/layouts.mdx
@@ -41,29 +41,33 @@ To override your assigned layout during a trigger event, use the `layoutIdentifi
The layout specified will be used for all emails in the context of that trigger event.
```ts
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
-const novu = new Novu('');
+const novu = new Novu("");
-novu.trigger('workflow-identifier', {
+novu.trigger("workflow-identifier", {
to: {
- subscriberId: '',
+ subscriberId: "",
},
payload: {
attachments: [
{
- file: fs.readFileSync(__dirname + '/data/test.jpeg'),
- name: 'test.jpeg',
- mime: 'image/jpg',
+ file: fs.readFileSync(__dirname + "/data/test.jpeg"),
+ name: "test.jpeg",
+ mime: "image/jpg",
},
],
},
overrides: {
- layoutIdentifier: 'your-layout-identifier',
+ layoutIdentifier: "your-layout-identifier",
},
});
```
- The override layout on trigger functionality is only available on v0.19.0.
+
+
+ {" "}
+ The override layout on trigger functionality is only available on v0.19.0.
+
#### Using SDK
@@ -171,4 +175,4 @@ const layouts = await novu.layouts.list({
## API Reference Links
-- [Layout Methods](/api-reference/layouts/layout-creation/)
\ No newline at end of file
+- [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
index 9bf1f27d..8d7132e5 100644
--- a/content-creation-design/notification-content-creation.mdx
+++ b/content-creation-design/notification-content-creation.mdx
@@ -8,18 +8,19 @@ To demonstrate the extensive range of possibilities, we've crafted a subscriber
```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
- }
+ 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,
+ },
};
```
@@ -42,19 +43,12 @@ Example: Send a personalized welcome email to a user by leveraging their propert
**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,
+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.
```
@@ -66,16 +60,10 @@ 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.
+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.
```
-Email Subject, Sender Name and Preheader field accepts system, payload variables and handlebar helpers
-[Explore how to manage Email layouts.](/content-creation-design/layouts)
+
+ Email Subject, Sender Name and Preheader field accepts system, payload
+ variables and handlebar helpers
+
+[Explore how to manage Email layouts.](/content-creation-design/layouts){" "}
## In-App
@@ -206,7 +197,9 @@ You have the ability to utilize all variables to craft dynamic and personalized
/>
## Push
+
Push channel has two fields `Push Message Title` and `Push Message Content` where user can write hard coded text content or use system, dynamic variables or handlebar helpers to customize notification content.
+
The feature is only available for **Novu Cloud** users with **Business** or **Enterprise** plans.
+
+ The feature is only available for **Novu Cloud** users with **Business** or
+ **Enterprise** plans.
+
## Introduction
@@ -23,21 +26,33 @@ Translation Group allows you to efficiently manage translations for diverse lang
To create the Translation Group navigate to the `Translations` page from the main navigation and click on the “Add group” button.
-
+
Before creating your first Translation Group you'll be prompted to specify the default locale for organization. This locale serves as a fallback option for localized messages in cases where the recipient hasn't defined a specific locale.
-
+
After selecting the default language, you can provide the essential details: the group name, group identifier, and select your target languages.
The group identifier is an important value that you will later use in the editor to localize your messages. This is a similar concept that we use across the app to identify the main parts.
-
+
After the group is created, you will land on the group details page on which you can see the list with the empty translations for the languages you choose.
-
+
## Translations
@@ -67,15 +82,24 @@ Translations are JSON files that contain the content of your messages in a speci
To upload your translations click on the “Upload files” button located at the top of the Translation Group details page.
-
+
Select the translation files and click “Open” button.
-
+
With each uploaded translation file, you must indicate the language it references. Additionally, you can verify the correctness of the uploaded file by previewing its contents.
-
+
Click on “Upload files” button. Congratulations you just uploaded the translation files and created the translation group! 🎉
@@ -88,9 +112,15 @@ Let’s take a look at the example: `{{i18n "marketing.welcome_message"}}`.
- `i18n` is the handlebar helper that tells Novu that you would like to use the Translations
- `"marketing.welcome_message"` is the path that is composed of the Translation Group identifier `marketing` and translation JSON file key `welcome_message`
-
+
-i18n variables can be used in `subject` and `preheader` fields of the email step.
+
+ i18n variables can be used in `subject` and `preheader` fields of the email
+ step.
+
## Subscribers Locale
The subscribers locale defines in which language the message should be delivered to that recipient. When the locale is not specified it will fallback to the default locale set for the organization. The locale format includes ISO language plus the region, for example `de_DE` language German and region Germany.
@@ -123,9 +153,9 @@ For example:
```json
{
- "friend": "A friend",
- "friend_male": "A boyfriend",
- "friend_female": "A girlfriend"
+ "friend": "A friend",
+ "friend_male": "A boyfriend",
+ "friend_female": "A girlfriend"
}
```
@@ -143,8 +173,8 @@ To distinguish between plural translation options.
```json
{
- "keyWithCount": "{{count}} item",
- "keyWithCount_plural": "{{count}} items",
+ "keyWithCount": "{{count}} item",
+ "keyWithCount_plural": "{{count}} items"
}
```
diff --git a/content-creation-design/variables.mdx b/content-creation-design/variables.mdx
index 82f0c6cf..143d4a5b 100644
--- a/content-creation-design/variables.mdx
+++ b/content-creation-design/variables.mdx
@@ -1,18 +1,18 @@
---
-title: 'Workflow Editor'
-description: ''
-icon: 'code'
+title: "Workflow Editor"
+description: ""
+icon: "code"
---
-Novu's content creation tools allow developers to utilize a wealth of variables when designing notification workflows.
+Novu's content creation tools allow developers to utilize a wealth of variables when designing notification workflows.
As developers construct workflows using Novu, certain status facets—results of batch functions and other steps in the workflow—are auto-generated and can be utilized to control the content displayed in notification templates.
-These variables offer dynamic and automated properties that hold subscriber information, such as first and last name, email, phone, and avatar.
+These variables offer dynamic and automated properties that hold subscriber information, such as first and last name, email, phone, and avatar.
For example, developers can insert a subscriber's first name into a workflow by using `{{ subscriber.firstName }}`.
-In addition to the subscriber's details, developers can use data payload variables that encapsulate dynamic data meant to be injected into the content of a workflow.
+In addition to the subscriber's details, developers can use data payload variables that encapsulate dynamic data meant to be injected into the content of a workflow.
For instance, in the code example the variables username and resetLink are data payload variables that would be adjusted based on the workflow's purpose.
@@ -20,59 +20,58 @@ For instance, in the code example the variables username and resetLink are data
## System Variables
-
### Subscriber Variables
-| Variable | Type | Description |
-| ------------- | -------- | ------------------------------------------------------ |
-| `subscriber` | `Object` | Represents someone who is intended to receive a notification. |
-| `firstName` | `String` | The first name of the subscriber. |
-| `lastName` | `String` | The last name of the subscriber. |
-| `email` | `String` | The subscriber's email address. |
-| `phone` | `String` | The phone number associated with the subscriber. |
-| `avatar` | `String` | A URL or reference to the subscriber’s avatar or profile picture. |
-| `locale` | `String` | The preferred locale or language of the subscriber. |
-| `subscriberId` | `String` | Unique identifier for the subscriber. |
-| `data` | `Object` | An additional object that can hold custom subscriber data as key-value pairs. |
+| Variable | Type | Description |
+| -------------- | -------- | ----------------------------------------------------------------------------- |
+| `subscriber` | `Object` | Represents someone who is intended to receive a notification. |
+| `firstName` | `String` | The first name of the subscriber. |
+| `lastName` | `String` | The last name of the subscriber. |
+| `email` | `String` | The subscriber's email address. |
+| `phone` | `String` | The phone number associated with the subscriber. |
+| `avatar` | `String` | A URL or reference to the subscriber’s avatar or profile picture. |
+| `locale` | `String` | The preferred locale or language of the subscriber. |
+| `subscriberId` | `String` | Unique identifier for the subscriber. |
+| `data` | `Object` | An additional object that can hold custom subscriber data as key-value pairs. |
### Actor Variables
-| Variable | Type | Description |
-| ------------- | -------- | ------------------------------------------------------ |
-| `actor` | `Object` | A subscriber who initiates actions triggering events. |
-| `firstName` | `String` | The first name of the actor. |
-| `lastName` | `String` | The last name of the actor. |
-| `email` | `String` | The actor's email address. |
-| `phone` | `String` | The phone number associated with the actor. |
-| `avatar` | `String` | A URL or reference to the actor’s avatar or profile picture. |
-| `locale` | `String` | The preferred locale or language of the actor. |
-| `subscriberId` | `String` | Unique identifier for the actor. |
-| `data` | `Object` | An additional object that can hold custom actor data as key-value pairs. |
+| Variable | Type | Description |
+| -------------- | -------- | ------------------------------------------------------------------------ |
+| `actor` | `Object` | A subscriber who initiates actions triggering events. |
+| `firstName` | `String` | The first name of the actor. |
+| `lastName` | `String` | The last name of the actor. |
+| `email` | `String` | The actor's email address. |
+| `phone` | `String` | The phone number associated with the actor. |
+| `avatar` | `String` | A URL or reference to the actor’s avatar or profile picture. |
+| `locale` | `String` | The preferred locale or language of the actor. |
+| `subscriberId` | `String` | Unique identifier for the actor. |
+| `data` | `Object` | An additional object that can hold custom actor data as key-value pairs. |
### Step Variables
-| Variable | Type | Description |
-| ------------- | -------- | ------------------------------------------------------ |
-| `step` | `Object` | A component in the execution of a workflow. |
-| `digest` | `Boolean` | Indicates whether digest mode is active or not. |
-| `events` | `Array` | An aggregated collection of events (that are stored when digest is active). |
-| `total_count` | `Number` | Represents the total number of events in the digest. |
+| Variable | Type | Description |
+| ------------- | --------- | --------------------------------------------------------------------------- |
+| `step` | `Object` | A component in the execution of a workflow. |
+| `digest` | `Boolean` | Indicates whether digest mode is active or not. |
+| `events` | `Array` | An aggregated collection of events (that are stored when digest is active). |
+| `total_count` | `Number` | Represents the total number of events in the digest. |
### Brand Variables
-| Variable | Type | Description |
-| --------- | -------- | ------------------------------------------------------ |
-| `branding` | `Object` | Enables customization of the notification's visual identity. |
-| `logo` | `String` | Insert the brand logo. |
+| Variable | Type | Description |
+| ---------- | -------- | --------------------------------------------------------------------------- |
+| `branding` | `Object` | Enables customization of the notification's visual identity. |
+| `logo` | `String` | Insert the brand logo. |
| `color` | `String` | Set the primary color of the notification based on the brand configuration. |
### Tenant Variables
-| Variable | Type | Description |
-| --------- | -------- | ------------------------------------------------------ |
-| `tenant` | `Object` | Group of users or an organization. |
-| `name` | `String` | Insert the brand logo. |
-| `data` | `Object` | An additional object that can hold custom tenant data as key-value pairs. |
+| Variable | Type | Description |
+| -------- | -------- | ------------------------------------------------------------------------- |
+| `tenant` | `Object` | Group of users or an organization. |
+| `name` | `String` | Insert the brand logo. |
+| `data` | `Object` | An additional object that can hold custom tenant data as key-value pairs. |
## Data Payload Variables
@@ -98,8 +97,8 @@ curl -L -X POST 'https://api.novu.co/v1/events/trigger' \
}'
```
-Within this code snippet, the variables `username` and `resetLink` are representative of data payload variables.
+Within this code snippet, the variables `username` and `resetLink` are representative of data payload variables.
Importantly, it's worth noting that the payload itself can encompass any serializable JSON object.
-Avoid use of system reserved variables as normal variables. For example don't use `email` as variable name because `{{subscriber.email}}` is a system reserved variable
\ No newline at end of file
+Avoid use of system reserved variables as normal variables. For example don't use `email` as variable name because `{{subscriber.email}}` is a system reserved variable
diff --git a/framework/deployment/actions.mdx b/deployment/actions.mdx
similarity index 100%
rename from framework/deployment/actions.mdx
rename to deployment/actions.mdx
diff --git a/framework/deployment/cli.mdx b/deployment/cli.mdx
similarity index 100%
rename from framework/deployment/cli.mdx
rename to deployment/cli.mdx
diff --git a/deployment/production.mdx b/deployment/production.mdx
new file mode 100644
index 00000000..bff043de
--- /dev/null
+++ b/deployment/production.mdx
@@ -0,0 +1,73 @@
+---
+title: "Going to Production"
+---
+
+Novu operates in a multi environment setup. Novu currently supports 2 environments:
+
+- **Development** - For creating, editing, and previewing workflows.
+- **Production** - For triggering workflows to your customers.
+
+## Sync changes to Novu Cloud
+
+Novu Framework operates in a GitOps model. This means that the source of truth for your workflows and configurations are located in your Git as Code.
+
+The general workflow for pushing changes to Novu Cloud is as follows:
+
+- Create a feature branch
+- Develop workflows locally in your bridge application
+- Sync changes to the Development environment to test e2e
+- Merge the feature branch to your `dev` branch
+ - This will trigger a CI/CD pipeline that will deploy the changes to the Development environment
+- Test the changes in the Development environment
+- Merge the `dev` branch to the `main` branch
+ - This will trigger a CI/CD pipeline that will deploy the changes to the Production environment
+
+## Networking
+
+Novu Cloud workers will need to be able to communicate with your [Bridge Endpoint](/concepts/endpoint). You will need to ensure that your firewall rules allow traffic from the internet.
+Due to the autoscaling nature of Novu Cloud, we don't have a set of IP Addresses that you can whitelist.
+
+## Security
+
+Novu Cloud workers are GDPR, SOC2 type II and ISO 27001 compliant. We take security very seriously and have implemented a number of security measures to ensure that your data is safe.
+Novu Framework has a builtin security mechanism that ensures that the requests are authentic from Novu Cloud using an HMAC signature.
+
+HMAC Verification is turned on by default
+
+```typescript
+export const client = new Client({
+ secretKey: process.env.NOVU_SECRET_KEY,
+ strictAuthentication: process.env.NODE_ENV !== "development", // set to true by default
+});
+```
+
+
+ For local development with Studio `strictAuthentication` should be set to
+ `false`.
+
+
+The `X-Novu-Signature` header included in each signed event contains a timestamp and one or more signatures that we verify.
+The timestamp is prefixed by `t=`, and each signature is prefixed by a scheme.
+Schemes start with `v`, followed by an integer. Currently, the only valid live signature scheme is v1.
+
+{/* todo add an example of the x-novu-signature header here */}
+
+Handling the signature verification is done by the Novu Framework, so you don't need to perform any action.
+
+## CI/CD Integrations
+
+Novu currently supports the following CI integrations:
+
+- **GitHub Actions** - [Direct Integration](/deployment/actions)
+- **GitLab CI** - Using our [CLI command](/deployment/cli)
+- **Jenkins** - Using our [CLI command](/deployment/cli)
+- **CircleCI** - Using our [CLI command](/deployment/cli)
+- **Bitbucket Pipelines** - Using our [CLI command](/deployment/cli)
+- **Azure DevOps** - Using our [CLI command](/deployment/cli)
+- **Travis CI** - Using our [CLI command](/deployment/cli)
+- **Other** - For any other CI/CD tool, you can use our [CLI command](/deployment/cli)
+
+
+ Direct integration with other CI/CD tools is on our roadmap. If you would like
+ to see a specific CI/CD tool integrated, please reach out to us.
+
diff --git a/echo-terminal.md b/echo-terminal.md
index 39c84b3f..e8049321 100644
--- a/echo-terminal.md
+++ b/echo-terminal.md
@@ -11,11 +11,22 @@ The JSDelivr URLs below point to the latest commit in the main branch, ensuring
The Echo terminal can be loaded via both JS and HTML.
### Loading with Javascript (preferred)
+
Use this method if you have access to custom JS.
```javascript
// Custom JS injection
-!function(e){if(!document.getElementById(e)){var t=document.createElement("script");t.src="https://cdn.jsdelivr.net/gh/novuhq/docs/echo-terminal.min.js",t.type="text/javascript",t.crossOrigin="anonymous",t.id=e;var n=document.getElementsByTagName("script")[0];n?n.parentNode.insertBefore(t,n):document.body.appendChild(t)}}("nv-echo-terminal-loader");
+!(function (e) {
+ if (!document.getElementById(e)) {
+ var t = document.createElement("script");
+ (t.src = "https://cdn.jsdelivr.net/gh/novuhq/docs/echo-terminal.min.js"),
+ (t.type = "text/javascript"),
+ (t.crossOrigin = "anonymous"),
+ (t.id = e);
+ var n = document.getElementsByTagName("script")[0];
+ n ? n.parentNode.insertBefore(t, n) : document.body.appendChild(t);
+ }
+})("nv-echo-terminal-loader");
```
```html
@@ -24,11 +35,17 @@ Use this method if you have access to custom JS.
```
### Loading with HTML
+
Use this method if you only have access to modify the `` element.
```html
-
+
diff --git a/framework/concepts/endpoint.mdx b/framework/concepts/endpoint.mdx
deleted file mode 100644
index 758fb7f2..00000000
--- a/framework/concepts/endpoint.mdx
+++ /dev/null
@@ -1,68 +0,0 @@
----
-title: "Bridge Endpoint"
----
-
-## Bridge Endpoint
-
-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.
-
-You can view the Bridge Endpoint as a webhook endpoint that Novu will call when it needs to retrieve contextual information for a given subscriber and notification.
-
-Using the `create-novu-app` command creates a Bridge application for you with a Bridge endpoint ready to go.
-
-## The `serve` function
-
-We offer framework specific wrappers in form of an exported `serve` function that abstracts away:
-
-- Parsing the incoming request for `GET`, `POST`, `PUT` and `OPTIONS` requests
-- HMAC header authentication
-- Framework specific response and error handling
-
-Currently, we offer `serve` functions for the following frameworks:
-- [Next.js](/framework/sdk/frameworks/nextjs)
-- [Express.js](/framework/sdk/frameworks/express)
-- [Nuxt](/framework/sdk/frameworks/nuxt)
-- [h3](/framework/sdk/frameworks/h3)
-- [Remix](/framework/sdk/frameworks/remix)
-- [Sveltekit](/framework/sdk/frameworks/sveltekit)
-
-## Writing a custom `serve` function
-
-If we currently don't support your framework, you can write a custom `serve` function like the following example:
-
-```ts
-import { type Request, type Response } from 'express';
-import { NovuRequestHandler, ServeHandlerOptions } from '@novu/framework';
-
-export const serve = (options: ServeHandlerOptions): any => {
- const requestHandler = new NovuRequestHandler({
- frameworkName: 'express',
- ...options,
- handler: (
- incomingRequest: Request,
- response: Response,
- ) => ({
- method: () => incomingRequest.method,
- headers: (key) => {
- const header = incomingRequest.headers[key];
- return Array.isArray(header) ? header[0] : header;
- },
- queryString: (key) => {
- const qs = incomingRequest.query[key];
- return Array.isArray(qs) ? qs[0] : qs;
- },
- body: () => incomingRequest.body,
- url: () => new URL(incomingRequest.url, `https://${incomingRequest.headers.get("host") || ""}`),
- transformResponse: ({ body, headers, status }) => {
- Object.entries(headers).forEach(([headerName, headerValue]) => {
- response.setHeader(headerName, headerValue);
- });
-
- return response.status(status).send(body);
- },
- }),
- });
-
- return requestHandler.createHandler();
-};
-```
diff --git a/framework/concepts/inputs.mdx b/framework/concepts/inputs.mdx
deleted file mode 100644
index d3469a88..00000000
--- a/framework/concepts/inputs.mdx
+++ /dev/null
@@ -1,77 +0,0 @@
----
-title: "Step Inputs"
-sidebarTitle: "Step Inputs"
----
-
-Inputs are defined using [JSON Schema](/framework/recipes/json-schema), providing a strong run-time validation system for your workflows.
-
-This ensures that you as the developer, and your non-technical peers are speaking the same language.
-Those responsible for styling and copy can edit with confidence, knowing their changes are tested in code.
-
-## Inputs vs Payload
-
-**Inputs** - For Non-Technical Peers and Developers. Managed in the Novu Web UI, defined by developers and used by non-technical peers.
-
- **Examples** - Color of a button, text of a button, should a section be shown, digest duration, static text content, the order of the email sections, and etc...
-
-
-**Payload Schema** - For Developers. Passed during the `novu.trigger` method, and controlled by the developer.
-
- **Examples** - User ID, Post ID, Comment, Order ID, 2FA token and etc...
-
-
-## Step Inputs
-
-[Step](/framework/concepts/steps) input schema is defining the input passed during the `step` method. Those inputs can be modified and persisted in the Novu Web UI.
-
-The snippet below shows configuration for the Workflow payload schema and the Step input schema. If you don’t provide a schema, Typescript will infer the data type to `unknown`, reminding you of the best practice to specify your schema.
-
-```tsx
-workflow('new-signup', async ({ step, payload }) => {
- await step.email(
- 'send-email',
- async (inputs) => {
- return {
- subject: inputs.subjectTitle,
- body: render(),
- }
- }, {
- // Learn about JSON Schema here: https://json-schema.org/specification
- inputSchema: {
- // Always `object`
- type: 'object',
- // Specify the properties to validate. Supports deep nesting.
- properties: {
- hideBanner: { type: 'boolean', default: false },
- subjectTitle: { type: 'string' },
- // Allowing no code control over the component in the Web UI
- components: {
- type: "array",
- items: {
- type: "string"
- },
- default: ["header", "cta-row", "footer"]
- }
- },
- // Specify the array of which properties are required.
- required: ['complianceFooter'],
- // 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,
- });
-});
-```
-
-Learn more about [JSON Schema here](https://json-schema.org/specification), including the powerful validation features to ensure your Content renders perfectly, every time.
-
-
- Other validators, including Zod and more, coming soon.
- Any validator that supports transformation to JSON Schema can be added.
-
-
-## JSON Schema Examples
-
-To Learn more about advanced examples, visit our [JSON Schema](/framework/recipes/json-schema) page.
diff --git a/framework/concepts/payload.mdx b/framework/concepts/payload.mdx
deleted file mode 100644
index 255c401c..00000000
--- a/framework/concepts/payload.mdx
+++ /dev/null
@@ -1,57 +0,0 @@
----
-title: "Payload"
----
-
-Workflow payload is the data passed during the `novu.trigger` method. This is useful for ensuring that the payload is correctly formatted and that the data is valid.
-
-## Payload Schema
-
-Payload schema is defining the payload passed during the `novu.trigger` method. This is useful for ensuring that the payload is correctly formatted and that the data is valid.
-
-```tsx
-workflow('comment-on-post', async ({ step, payload }) => {
- await step.email(
- 'send-email',
- async () => {
- return {
- subject: `You have a new comment from: ${payload.author_name}.`,
- body: render(),
- }
- });
- },
- {
- payloadSchema: {
- // Always `object`
- type: 'object',
- // Specify the properties to validate. Supports deep nesting.
- properties: {
- post_id: { type: 'number' },
- author_name: { type: 'string' },
- comment: { type: 'string', maxLength: 200 },
- },
- // Specify the array of which properties are required.
- required: ['post_id', 'comment'],
- // 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,
- },
-);
-```
-
-## Passing Payload
-
-Here is an example of the validated payload during trigger:
-
-```tsx
-novu.trigger('comment-on-post', {
- to: 'subscriber_id',
- payload: {
- post_id: 1234,
- author_name: 'John Doe',
- comment: 'Looks good!'
- }
-});
-```
diff --git a/framework/concepts/studio.mdx b/framework/concepts/studio.mdx
deleted file mode 100644
index fe9efdbd..00000000
--- a/framework/concepts/studio.mdx
+++ /dev/null
@@ -1,26 +0,0 @@
----
-title: "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`
-
-After successfully connecting the Studio to your local edge endpoint, you will be able to preview in real time any workflows and content defined in your code. This is ideal for quick prototyping, debugging, styling, and adjusting your workflows before syncing them to Novu Cloud.
-
-### Inputs and Payload forms
-
-You can quickly modify the step inputs and workflow payload to preview your workflow's different states and be generated with. This is helpful to quickly debug how the email will behave in case of a missing input, or iterate more complex content structures.
-
-### Syncing State
-
-Sync state to your Production or Development environment in Novu, is recommended to do via your CI pipeline. However, a sync can be made using the Dev Studio for quick experimentation.
-
-Click on the `Sync` button at the top right corner of the navigation bar, and a Diff will be generated between your local and the Novu Cloud environments.
-
-After inspecting the State Diff, and specifying the remote `Echo Url` Click on the `Deploy Changes` button.
-
-### **Debugging locally**
-
-To allow Novu to communicate with your local machine a tunnel will need to be generated. The quickest way to do it is with `localtunnel.` To Create a new tunnel in your terminal, type: `npx localtunnel --port ` . This command will return an https endpoint, which then can be used during the sync state flow described earlier.
diff --git a/framework/concepts/workflows.mdx b/framework/concepts/workflows.mdx
deleted file mode 100644
index 7beb8de0..00000000
--- a/framework/concepts/workflows.mdx
+++ /dev/null
@@ -1,145 +0,0 @@
----
-title: "Workflows"
-description: "Workflows are at the core of responding to events in your system with notifications. Novu Framework enables you to declare type-safe, validated, and version-controlled Novu Workflows with code."
----
-
-## Introduction
-The most basic Workflow to send a notification in response to an event looks like:
-
-```tsx
-import { workflow } from '@novu/framework';
-
-const myWorkflow = workflow('new-signup', async ({ step, payload }) => {
- // Send a welcome email
- await step.email('send-email', async () => {
- return {
- subject: `Welcome to Acme, ${payload.name}`,
- body: 'We look forward to helping you achieve mission.',
- }
- });
- // JSON Schema for validation and type-safety. Zod, and others coming soon.
-}, { payloadSchema: { properties: { name: { type: 'string' }}}} );
-```
-
-## Just-in-time data fetching
-You can add any custom logic into your steps that you need. Maybe you’d like to fetch some information about your new sign-up from somewhere else during the Workflow execution. You can achieve it with the following changes:
-
-```tsx
-const myWorkflow = workflow('new-signup', async ({ step, payload }) => {
- // Send a welcome email
- await step.email('send-email', async () => {
- // Fetch the user from your database
- const user = await db.getUser(payload.userId);
- return {
- subject: `Welcome to Acme ${user.productTier} tier, ${user.name}.`,
- // 'Welcome to Acme Business tier, John Doe.'
- body: 'We look forward to helping you achieve mission.',
- }
- });
- // Changing the schema from `name` -> `userId`, for type-safety.
- }, { payloadSchema: { properties: { userId: { type: 'string' }}}} );
-```
-
-We call this **just-in-time** notification data fetching. It allows you pull in data from the relevant sources during the Workflow execution, removing the need to store all of your subscriber data in Novu.
-
-## Multi-step workflow
-Now, what if you wanted to send another update to the same new user in 1 week? But, you don't want to send the follow-up if the User opted out. We can add more steps to the Workflow to achieve this.
-
-```tsx
-const myWorkflow = workflow(
- 'new-signup',
- async ({ step, payload }) => {
- await step.email('send-email', async () => {
- const user = await db.getUser(payload.userId);
- return {
- subject: `Welcome to Acme ${user.productTier} tier, ${user.name}.`,
- body: 'We look forward to helping you achieve mission.',
- };
- });
-
- // Wait for 1 week before continuing. After 1 week, Novu will continue
- // executing the Workflow from here.
- await step.delay('onboarding-follow-up', async () => ({
- amount: 1,
- type: 'regular',
- unit: 'weeks',
- }));
-
- // 1 week passed, let's follow up with an in-app notification.
- await step.inApp(
- 'onboarding-follow-up',
- async (inputs) => {
- const user = await db.getUser(payload.userId);
- // The `feedbackUrl` can be updated in Novu Web without changing code.
- // This helps you to create re-usable Workflow snippets.
- return {
- body: `Hey ${user.name}! How do you like the product?
-
- Let us know here
- if you have any questions.`,
- };
- },
- {
- // Don't follow up if the Subscriber opted out.
- skip: () => !payload.shouldFollowUp,
- // Add validation to ensure `feedbackUrl` provided in Web is a `uri`
- inputSchema: {
- type: 'object',
- properties: { feedbackUrl: { type: 'string', format: 'uri', default: 'https://acme.com/feedback' } },
- required: ['feedbackUrl'],
- additionalProperties: false,
- } as const,
- },
- );
- },
- {
- payloadSchema: {
- type: 'object',
- properties: {
- userId: { type: 'string' },
- shouldFollowUp: { type: 'boolean', default: true },
- },
- required: ['userId', 'shouldFollowUp'],
- additionalProperties: false,
- } as const,
- },
-);
-```
-
-With this simple Workflow, we:
-
-- Sent a new signup email
-- Waited 1 week
-- Sent an in-app follow-up notification
-
-You should now have a grasp of the flexibility that Novu Framework offers.
-
-Continue your reading in [Steps](/framework/concepts/steps) to find out the other channels and actions you can use with Novu Framework.
-
-## Workflow Interface
-
-```tsx
-workflow(
- // the Workflow name. Must be unique across your Bridge server.
- 'new-signup',
- // 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.
- inputSchema: { properties: { brandColor: { type: 'string' }}},
-});
-```
diff --git a/framework/deployment/production.mdx b/framework/deployment/production.mdx
deleted file mode 100644
index befc1d5b..00000000
--- a/framework/deployment/production.mdx
+++ /dev/null
@@ -1,68 +0,0 @@
----
-title: "Going to Production"
----
-
-Novu operates in a multi environment setup. Currently Novu Supports 2 environments:
-
-- **Development** - This is the environment where the development team works on workflows.
-- **Production** - This is the environment that is used to trigger workflows to your customers.
-
-## Pushing changes to Cloud
-
-Novu Framework operates in a GitOps model. This means that the source of truth for your workflows and configurations are located in your Git as Code.
-
-The general workflow for pushing changes to Cloud is as follows:
-- Create a feature branch
-- Develop workflows locally in your Bridge application
-- Sync changes to the Development environment to test e2e
-- Merge the feature branch to your `dev` branch
- - This will trigger a CI/CD pipeline that will deploy the changes to the Development environment
-- Test the changes in the Development environment
-- Merge the `dev` branch to the `main` branch
- - This will trigger a CI/CD pipeline that will deploy the changes to the Production environment
-
-## Networking
-
-Novu Cloud workers will need to be able to communicated with your Bridge Endpoint. You will need to ensure that your firewall rules allow traffic from the internet.
-Due to the autoscaling nature of Novu Cloud, we don't have a set of IP Addresses that you can whitelist.
-
-## Security
-
-Novu Cloud workers are GDPR, SOC2 type II and ISO 27001 compliant. We take security very seriously and have implemented a number of security measures to ensure that your data is safe.
-Novu Framework has a builtin security mechanism that ensures that the requests are authentic from Novu Cloud using an HMAC signature.
-
-HMAC Verification is turned on by default
-
-```typescript
-export const client = new Client({
- apiKey: process.env.NOVU_API_KEY,,
- strictAuthentication: process.env.NODE_ENV !== "development", // set to true by default
-});
-```
-
-
- For local development with Studio `strictAuthentication` should be set to `false`.
-
-
-The `X-Novu-Signature` header included in each signed event contains a timestamp and one or more signatures that we verify.
-The timestamp is prefixed by t=, and each signature is prefixed by a scheme.
-Schemes start with v, followed by an integer. Currently, the only valid live signature scheme is v1.
-
-Handling the signature verification is done by the Novu Framework, you don't need to perform any action.
-
-## CI/CD Integrations
-
-Novu currently supports the following CI integrations:
-- **GitHub Actions** - [Direct Integration](/framework/deployment/actions)
-- **GitLab CI** - Using our [CLI command](/framework/deployment/cli)
-- **Jenkins** - Using our [CLI command](/framework/deployment/cli)
-- **CircleCI** - Using our [CLI command](/framework/deployment/cli)
-- **Bitbucket Pipelines** - Using our [CLI command](/framework/deployment/cli)
-- **Azure DevOps** - Using our [CLI command](/framework/deployment/cli)
-- **Travis CI** - Using our [CLI command](/framework/deployment/cli)
-- **Other** - For any other CI/CD tool, you can use our [CLI command](/framework/deployment/cli)
-
-
- Direct integration with other CI/CD tools is on our roadmap. If you would like to see a specific CI/CD tool integrated, please reach out to us.
-
-
diff --git a/framework/non-developers/introduction.mdx b/framework/non-developers/introduction.mdx
deleted file mode 100644
index 6ef1b3f4..00000000
--- a/framework/non-developers/introduction.mdx
+++ /dev/null
@@ -1,40 +0,0 @@
----
-title: "No-Code Tools to control your Notification Flows"
-sidebarTitle: "Introduction"
-description: "Change notification content and behavior with confidence using Novu Web UI."
----
-
-Novu Framework was designed to bridge the gap between developers and on-developers in the team.
-
-- **Developers** - Define and abstract away complex logic, data manipulation and hydration, html and etc...
-- **Non-Developers** - Use the Novu Web UI to control the content and behavior of the notifications using [Inputs](/framework/concepts/inputs).
-
-## How to Modify Inputs?
-
-Inputs are modified directly on the [Novu Web UI](https://web.novu.co). Each Workflow editor page have an 'Inputs' tab where you can modify them.
-When Saving the changes, the new Input values will be used in the notification sent to your subscriber.
-
-## Common Input Usecases
-
-### Change Notification Content
-
-An input can be as broad as `content` or as specific as `2fa_code_title_color`. This allows you to change the content of the notification without needing to touch the code.
-
-
- Currently you cannot use Dynamic payload variables as part of the Input. Reach out to us if you need this capability.
-
-
-### Change Digest or Delay Frequency
-
-Inputs can be used for controlling any aspect of the step configuration, for example:
-
-- Digest Length
-- Delay Amount
-- Digest Type (Daily, Weekly, Monthly)
-- etc...
-
-### Control structure and layout
-
-Inputs can be used to show/hide or rearrange the layout of the notification.
-For example, you can have an input to show/hide a button, or change the position of a specific email section.
-
diff --git a/framework/quickstart.mdx b/framework/quickstart.mdx
deleted file mode 100644
index 71018bb9..00000000
--- a/framework/quickstart.mdx
+++ /dev/null
@@ -1,60 +0,0 @@
----
-title: "Quick Start"
-description: "Novu Framework, the Code-first notification workflow engine. Build advanced workflows while giving your non-technical teammates complete control over content and behavior."
----
-
-import { EchoTerminal } from '/snippets/echo-terminal.mdx';
-
-
- **Novu Framework is currently in public Alpha.** Need help? Have a suggestion? Join our [Discord community](https://discord.gg/novu).
-
-
-## Introduction to Novu Framework
-
-Novu Framework allows you to write notification workflows in your codebase. Workflows are functions that execute business logic and use your preferred libraries for email, SMS, and chat generation. You can use Novu Framework with [React.Email](https://react.email/), [MJML](https://mjml.io/), or any other template generator.
-
-
-
-## Try it now
-
-To create a new Bridge application that will allow you to define your workflow in code, open your terminal and execute the `create-novu-app` command.
-
-```shell
-npx create-novu-app@latest --api-key=
-```
-
-The command will ask you if you wish to install from a React.Email template or a clean project.
-
-## Core features
-
-
-
- Write the notification workflows as functions in your codebase, version, and manage them using Git.
-
-
- Use React.email, MJML, or fetch templates from Braze, Hubspot, Sendgrid, and more...
-
-
- Bring your own schemas for full, end-to-end validation and type safety.
-
-
- Sync your workflows with Novu Cloud and ease collaboration.
-
-
-
-
-## How it Works?
-
-Novu Framework introduces a new paradigm when working with Novu. Rather than defining workflows and templates at Novu Cloud, Novu Framework enables you to work in your application, use your own libraries and connect to your production environment during workflow execution over HTTPS.
-
-The Novu Framework exports the client you use to define and serve your workflows and their steps over HTTPS. The workflows can be added to your preferred framework. During workflow execution Novu Cloud makes HTTPS requests to your Bridge server for *just-in-time* Content and Subscribers resolution.
-
-
-
-
-
-## For Non-Technical Users
-
-Novu Framework was built with non-technical user in mind. Engineers can write complex workflows and expose a type-safe [Inputs](/framework/concepts/inputs) interface powered by JSON-Schema.
-This enables Non-Technical teammates to safely modify the workflow without breaking mission critical notifications.
-
diff --git a/framework/roadmap.mdx b/framework/roadmap.mdx
deleted file mode 100644
index 10d9a065..00000000
--- a/framework/roadmap.mdx
+++ /dev/null
@@ -1,25 +0,0 @@
----
-title: "Roadmap"
----
-
-This document outlines the roadmap for the Novu Framework project. It is a living document and will be updated as the project progresses.
-
-Our goal with Novu Framework is to create a Code-First but Product in-mind. Here you can see parts of our roadmap and future plans for it:
-
-Looking to add a feature request or upvote and existing feature? Head over to our [Public Roadmap](https://roadmap.novu.co).
-
-## Novu Framework, Now and Next
-- ✅ **Workflows**: the ability to create multi-step workflows and manage them using Code.
-- ✅ **CLI**: a command-line interface to interact with Novu Framework.
-- ✅ **Studio**: a visual front to preview your local work.
-- ✅ **Step Inputs**: JSON-Schema based interface for not technical users to modify the workflow content and behaviour.
-- ✅ **GitHub Actions**: sync your workflows using GitHub Actions.
-- ✅ **In App Seen/Read**: the ability to see the status of the in-app message.
-- ✅ **Custom Step**: the ability to create custom and execute custom code in the workflow. For example: custom provider, retrieving database information, and 3rd party service integration.
-- 🔜 **Zod Schema**: the ability to define the schema for the workflow and step inputs using Zod.
-- 🔜 **Define Integrations**: code-first approach of creating and managing your provider integrations
-- 🔜 **Email Reply Hook**: executing a custom logic code when a user replies to the email.
-- 🔜 **Webhook**: receive webhooks about the execution flow of a workflow in Novu Framework.
-- 🔜 **Eslint Plugin**: follow best practices and avoid common mistakes when writing code for Novu Framework.
-- 🔜 **Codegen**: use our community driven list of workflow templates to use out of the box.
-
diff --git a/framework/sdk/client.mdx b/framework/sdk/client.mdx
deleted file mode 100644
index 267c795d..00000000
--- a/framework/sdk/client.mdx
+++ /dev/null
@@ -1,36 +0,0 @@
----
-title: "Introduction"
----
-
-See the snippet below to learn how to configure your Bridge endpoint application.
-
-```tsx
-import { Client } from '@novu/framework';
-
-const client = new Client({
- /**
- * Specify a custom Novu API URL.
- * Defaults to 'https://api.novu.co', for EU use: https://eu.api.novu.co
- */
- apiUrl: 'https://api.novu.co',
- /**
- * Specify your Novu API key, to secure your Bridge API endpoint.
- * Novu communicates securely with your endpoint using a signed HMAC header,
- * ensuring that only trusted requests from Novu are actioned by your Bridge API.
- * The API key is used to sign the HMAC header.
- */
- apiKey: process.env.NOVU_API_KEY,
- /**
- * Explicitly use HMAC signature verification.
- * Setting this to `false` will enable Novu to communicate with your Bridge API
- * without requiring a valid HMAC signature.
- * This is useful for local development and testing.
- *
- * You are strongly encouraged to specify an `apiKey` and set this to `true` in production,
- * to ensure that only trusted requests from Novu are actioned by your Bridge API.
- *
- * Defaults to true.
- */
- strictAuthentication: process.env.NODE_ENV !== "development",
-});
-```
diff --git a/framework/sdk/frameworks/express.mdx b/framework/sdk/frameworks/express.mdx
deleted file mode 100644
index a68d3c14..00000000
--- a/framework/sdk/frameworks/express.mdx
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "Integrate Novu with Express.js"
-sidebarTitle: "Express"
----
-
-```tsx
-import { serve } from "@novu/framework/express";
-import { myWorkflow } from "../novu/workflows";
-
-app.use(express.json()); // Required for Novu POST requests
-app.use(
- "/api/novu",
- serve({ workflows: [myWorkflow] })
-);
-```
diff --git a/framework/sdk/frameworks/h3.mdx b/framework/sdk/frameworks/h3.mdx
deleted file mode 100644
index ba1fd866..00000000
--- a/framework/sdk/frameworks/h3.mdx
+++ /dev/null
@@ -1,23 +0,0 @@
----
-title: "Integrate Novu with H3"
-sidebarTitle: "H3"
----
-
-```tsx
-import { createApp, eventHandler, toNodeListener } from "h3";
-import { serve } from "@novu/framework/h3";
-import { createServer } from "node:http";
-import { myWorkflow } from "./novu/workflows";
-
-const app = createApp();
-app.use(
- "/api/novu",
- eventHandler(
- serve({
- workflows: [myWorkflow],
- })
- )
-);
-
-createServer(toNodeListener(app)).listen(process.env.PORT || 3000);
-```
diff --git a/framework/sdk/frameworks/nextjs.mdx b/framework/sdk/frameworks/nextjs.mdx
deleted file mode 100644
index be46b38b..00000000
--- a/framework/sdk/frameworks/nextjs.mdx
+++ /dev/null
@@ -1,29 +0,0 @@
----
-title: "Integrate Novu with Next.js"
-sidebarTitle: "Next.js"
----
-
-## App Router
-
-
-```ts app/api/novu/route.ts
-import { serve } from "@novu/framework/next";
-import { myWorkflow } from "../../novu/workflows";
-
-export const { GET, POST, PUT, OPTIONS } = serve({ workflows: [myWorkflow] });
-```
-
-
-
-## Pages Router
-
-
- ```ts pages/api/novu.ts
- import { serve } from "@novu/framework/next";
- import { myWorkflow } from '../../novu/workflows';
-
- export default serve({ workflows: [myWorkflow] });
- ```
-
-
-Check out a comprehensive [guide on sending notifications in Next.js with React email](/guides/framework-guides/framework-react-email).
diff --git a/framework/sdk/frameworks/nuxt.mdx b/framework/sdk/frameworks/nuxt.mdx
deleted file mode 100644
index 80f0ca90..00000000
--- a/framework/sdk/frameworks/nuxt.mdx
+++ /dev/null
@@ -1,19 +0,0 @@
----
-title: "Integrate Novu with Nuxt"
-sidebarTitle: "Nuxt"
----
-
-Novu Framework works out of the box with Nuxt.js. You can use the `@novu/framework/nuxt` package to serve your Bridge endpoint in your Nuxt.js application.
-
-For a boilerplate project with Vue Email, view: [Nuxt.js Boilerplate](https://github.com/novuhq/novu-framework-nuxt-example/)
-
-
-```ts API Routes
-import { serve } from "@novu/framework/nuxt";
-import { myWorkflow } from "../workflows";
-
-export default defineEventHandler(serve({ workflows: [myWorkflow] }));
-```
-
-
-Check out a comprehensive [guide on sending notifications in Nuxt with Vuemail](/guides/framework-guides/framework-nuxt-vuemail).
diff --git a/framework/sdk/frameworks/remix.mdx b/framework/sdk/frameworks/remix.mdx
deleted file mode 100644
index be68e636..00000000
--- a/framework/sdk/frameworks/remix.mdx
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: "Integrate Novu with Remix"
-sidebarTitle: "Remix"
----
-
-```tsx
-import { serve } from "@novu/framework/remix";
-import { myWorkflow } from "../novu/workflows";
-
-const handler = serve({
- workflows: [myWorkflow],
- });
-
-export { handler as action, handler as loader };
-```
-
-Check out a comprehensive [guide on sending notifications in Remix with React email](/guides/framework-guides/framework-remix).
-
diff --git a/framework/sdk/frameworks/sveltekit.mdx b/framework/sdk/frameworks/sveltekit.mdx
deleted file mode 100644
index b3bfcebc..00000000
--- a/framework/sdk/frameworks/sveltekit.mdx
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "Integrate Novu with SvelteKit"
-sidebarTitle: "SvelteKit"
----
-
-```tsx
-import { myWorkflow } from '../workflows';
-import { serve } from '@novu/framework/sveltekit';
-
-export const { GET, POST, PUT } = serve({ workflows: [myWorkflow] });
-```
-
-Check out a comprehensive [guide on sending notifications in Svelte with Svelte-email](/guides/framework-guides/framework-svelte).
-
diff --git a/framework/sdk/typescript.mdx b/framework/sdk/typescript.mdx
deleted file mode 100644
index 57553809..00000000
--- a/framework/sdk/typescript.mdx
+++ /dev/null
@@ -1,36 +0,0 @@
----
-title: "Typescript"
----
-
-import { EchoTerminal } from '/snippets/echo-terminal.mdx';
-
-Novu Framework was built and optimized for extreme focus on Developer Experience.
-Our `@novu/framework` SDK is written in Typescript, and we recommend using Typescript for your own projects as well.
-
-
-
-## Type Safe Workflow Payloads
-
-When defining a [workflow payload](/framework/concepts/payload) schema, our SDK will automatically infer it to a Typescript interface.
-
-```typescript
-import { workflow } from '@novu/framework';
-
-const myWorkflow = workflow('new-signup', async ({ step, payload }) => {
- await step.email('send-email', () => {
- return {
- subject: 'Hello World',
- // The payload object here is type-safe
- body: `Hi ${payload.name}, welcome to our platform!`
- }
- });
-}, {
- // JSON Schema for validation and type-safety. Zod, and others coming soon.
- // https://json-schema.org/draft-07/json-schema-release-notes
- payloadSchema: { properties: { name: { type: 'string' }}},
-});
-```
-
-## Type Safe Steps
-
-Similarly, when defining a [step](/framework/concepts/steps) schema, our SDK will automatically infer it to a Typescript interface.
diff --git a/framework/steps/chat.mdx b/framework/steps/chat.mdx
deleted file mode 100644
index a2cd3980..00000000
--- a/framework/steps/chat.mdx
+++ /dev/null
@@ -1,50 +0,0 @@
----
-title: "Chat Channel Step"
-sidebarTitle: "Chat"
----
-
-Use the chat channel step to send a message for providers like: Slack, WhatsApp, Discord and others.
-
-```tsx
-await step.chat('send-chat', async () => {
- return {
- body: 'A new post has been created',
- };
-});
-```
-
-## Provider Overrides
-
-Some providers offer a rich DSL for styling the messages. Novu Framework offers a robust API to leverage the provider specific capabilities using the step `providers` option object.
-
-Let's see an example of how to send a message to Slack using the `providers` option objet.
-
-```tsx
-await step.chat('send-chat', async () => {
- return {
- body: 'A new post has been created',
- };
-}, {
- providers: {
- slack: ({ inputs }) => ({
- text: 'A new post has been created',
- blocks: [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'A new post has been created',
- },
- },
- ],
- }),
- }
-});
-```
-
-Default chat `body` field is still specified as a fallback value in case a provider specific configuration is not used.
-
-
-
- Currently we only support `Slack` provider overrides. We are working on adding more providers.
-
diff --git a/framework/steps/custom.mdx b/framework/steps/custom.mdx
deleted file mode 100644
index 0ec8b724..00000000
--- a/framework/steps/custom.mdx
+++ /dev/null
@@ -1,84 +0,0 @@
----
-title: "Custom Action Step"
-sidebarTitle: "Custom"
-description: "Used to execute any custom code as a step in the workflow."
----
-
-A custom steps allows to execute any custom logic and persist in the durable execution context. The result of this step can be used in subsequent steps.
-
-## Common usecases
-
-- Making an API call to 3rd party service
-- Fetch data from a database to be used in subsequent steps
-- Execute a custom logic to transform data
-- Custom provider implementation
-
-## Custom Step Interface
-
-```tsx
-const stepResult = await step.custom('custom-step', async () => {
- return {
- item_name: 'A product name',
- item_price: 100,
- };
-}, {
- outputSchema: {
- type: 'object',
- properties: {
- item_name: { type: 'string' },
- item_price: { type: 'number' },
- },
- required: ['item_name', 'item_price'],
- }
-});
-```
-
-### Output Schema Definition
-
-This JSON Schema definition is used to validate the output of the custom step. If the output does not match the schema, the workflow will fail.
-Novu Framework will infer the Typescript interface from the JSON Schema definition.
-
-### Return Value
-
-The Custom Step function should return a valid serializable object. The return value will be persisted in the durable execution context.
-
-## Using the Custom Step Result
-
-The result can only be used in the `resolver` of the step/providers/skip functions of subsequent steps.
-
-```typescript
-workflow('hello-world-workflow', async ({ payload }) => {
- const task = await step.custom('fetch-db-data', async () => {
- const taskData = db.fetchTask(payload.task_id);
- return {
- task_id: taskData.id,
- task_title: taskData.title,
- complete: taskData.complete,
- };
- }, {
- outputSchema: {
- type: 'object',
- properties: {
- task_title: { type: 'string' },
- task_id: { type: 'string' },
- complete: { type: 'boolean' },
- },
- required: ['task_id', 'complete'],
- }
- });
-
- await step.email('send-email', () => {
- return {
- subject: `Task reminder for ${task.task_title}`,
- body: 'Task is not yet complete. Please complete the task.'
- }
- }, {
- // Only send the reminder E-mail if the task is not complete
- skip: () => !task.complete
- })
-});
-
-
-
-```
-
diff --git a/framework/steps/delay.mdx b/framework/steps/delay.mdx
deleted file mode 100644
index 83b17250..00000000
--- a/framework/steps/delay.mdx
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "Delay Action Step"
-sidebarTitle: "Delay"
----
-
-Use the delay action whenever you need to pause the execution of your workflow for a period of time.
-
-```tsx
-await step.delay('delay-1-week', async () => {
- return {
- unit: 'weeks', // 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months'
- amount: 1, // the number of units to delay workflow execution for
- };
-});
-```
-
diff --git a/framework/steps/digest.mdx b/framework/steps/digest.mdx
deleted file mode 100644
index be913513..00000000
--- a/framework/steps/digest.mdx
+++ /dev/null
@@ -1,45 +0,0 @@
----
-title: "Digest Action Step"
-sidebarTitle: "Digest"
----
-
-The digest engine is designed to streamline notifications by accumulating multiple trigger events into one coherent message before delivery to the subscriber.
-
-This function proves beneficial when a user needs to be alerted about numerous triggers, but it's important to minimize the frequency of notifications. Novu automates this process, batching incoming trigger events according to a unique subscriberId. There is also the option to include a digestKey, providing additional control over event digestion workflows.
-
-## Step Interface
-
-```tsx
-const digestResult = await step.digest('digest-3-days', async () => {
- return {
- unit: 'days', // 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months'
- amount: 3, // the number of units to digest events for
- };
-});
-```
-## Using the digested triggers
-
-The digest function returns an array of triggers that have been digested.
-You can use this array to perform any necessary actions on the digested triggers. Like Sending and email, or updating a database.
-
-```tsx
-const digestResult = await step.digest('digest-3-days', async () => {
- return {
- unit: 'days', // 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months'
- amount: 3, // the number of units to digest events for
- };
-});
-
-await step.email('send-email', async () => {
- return {
- subject: 'Digest Email',
- body: `You have ${digestResult.events.length} new events`,
- };
-});
-```
-
-The digest step returns an object with `events` array. Each event in the array has the following properties:
-
-- `id` - The `job id` of the digested event
-- `time` - The time when the event was triggered
-- `payload` - The original payload passed to the event
diff --git a/framework/steps/email.mdx b/framework/steps/email.mdx
deleted file mode 100644
index 9a990ef9..00000000
--- a/framework/steps/email.mdx
+++ /dev/null
@@ -1,20 +0,0 @@
----
-title: "Email Channel Step"
-sidebarTitle: "Email"
----
-
-E-mail expected to be an object with the following properties:
-
-- `subject` - The subject of the email
-- `body` - The HTML body of the email
-
-Any content generation framework like [React Email](/framework/integrations/react-email) can be used here to generate the HTML Content.
-
-```tsx
-await step.email('send-email', async (inputs) => {
- return {
- subject: 'You received a post',
- body: `A new post has been created`,
- };
-});
-```
diff --git a/framework/steps/in-app.mdx b/framework/steps/in-app.mdx
deleted file mode 100644
index 673be38b..00000000
--- a/framework/steps/in-app.mdx
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "In-App Channel Step"
-sidebarTitle: "In-App"
----
-
-Novu offers notification center component that can be easily embedded into your application. Read more about it [here](/notification-center/introduction).
-
-```tsx
-await step.inApp('send-in-app', async (inputs) => {
- return {
- body: `A new post has been created`,
- };
-});
-```
diff --git a/framework/steps/introduction.mdx b/framework/steps/introduction.mdx
deleted file mode 100644
index 1f39cb80..00000000
--- a/framework/steps/introduction.mdx
+++ /dev/null
@@ -1,90 +0,0 @@
----
-title: "Workflow Steps"
-sidebarTitle: "Introduction"
-description: "Steps control the execution flow of your workflow, whilst Novu provides the context of your notification delivery events back into the Workflow execution context."
----
-
-## Supported Steps
-
-Novu Supports Channel and Action steps to be used as part of the workflow execution.
-
-### Channel Steps
-- [E-mail](/framework/steps/email)
-- [Chat](/framework/steps/chat)
-- [SMS](/framework/steps/sms)
-- [Push](/framework/steps/push)
-- [In-App](/framework/steps/in-app)
-
-### Action steps
-- [Delay](/framework/steps/delay)
-- [Digest](/framework/steps/digest)
-
-## Channel Steps Interface
-
-Channel steps are used to send notifications to your Subscribers. Each channel can optionally configure the provider to customize content, enabling you to create enhanced content aligned with the specification of the provider. For example, you might like to use Slack blocks to send your Chat message.
-
-All channels follow the same interface:
-
-```tsx
-await step.email('new-post', async (inputs) => {
- return {
- subject: 'You received a post',
- body: `A new post has been created`,
- }
-}, options);
-```
-
-- `new-post` is the unique to the workflow identifier for this step. You cannot have 2 steps using the same identifier
-- `resolver` function, used to return the content of the channel.
-- `options` this is an optional configuration object that defines: [Input Schema](/framework/concepts/inputs), [Provider Overrides](#provider-overrides), skip and other configurations...
-
-## Provider Overrides
-
-Provider overrides are used to customize the content of the notification for a specific provider. For example, you might like to use Slack blocks to send your Chat message.
-
-Those overrides are mapped directly to the provider specific SDKs, so you can use the same properties and methods that you would use in the provider SDK.
-
-```tsx
-await step.chat('send-chat', async () => {
- return {
- body: 'A new post has been created',
- };
-}, {
- providers: {
- slack: ({ inputs }) => ({
- text: 'A new post has been created',
- blocks: [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'A new post has been created',
- },
- },
- ],
- }),
- }
-});
-```
-
-
- Currently we only support `Slack` provider overrides. We are working on adding more providers.
-
-
-When overriding a provider specific behavior, Novu still requires the default content to be returned from the resolver function.
-This is because the default content is used for the fallback provider, or when the provider override is not available.
-
-## Skip Step
-
-A step can be conditionally skipped by returning `true` from the resolver function. This is helpful when you want to use your existing user-preference system instead of Novu.
-Or conditionally skip a step if it's not relevant any more for delivery.
-
-```tsx
-await step.chat('send-chat', async () => {
- return {
- body: 'A new post has been created',
- };
-}, {
- skip: () => true,
-});
-```
diff --git a/framework/steps/push.mdx b/framework/steps/push.mdx
deleted file mode 100644
index 546718b8..00000000
--- a/framework/steps/push.mdx
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "Push Channel Step"
-sidebarTitle: "Push"
----
-
-```tsx
-await step.push('send-push', async () => {
- return {
- subject: 'You received a post',
- body: 'A new post has been created',
- };
-});
-```
diff --git a/framework/steps/sms.mdx b/framework/steps/sms.mdx
deleted file mode 100644
index f8c72e8d..00000000
--- a/framework/steps/sms.mdx
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "SMS Channel Step"
-sidebarTitle: "SMS"
----
-
-
-```tsx
-await step.sms('send-sms', async () => {
- return {
- body: 'A new post has been created',
- };
-});
-```
diff --git a/getting-started/how-novu-works.mdx b/getting-started/how-novu-works.mdx
index 2fbd55b0..c4a89ca4 100644
--- a/getting-started/how-novu-works.mdx
+++ b/getting-started/how-novu-works.mdx
@@ -1,21 +1,12 @@
---
-title: 'How Does Novu Work?'
-description: ''
-icon: 'map'
+title: "How Does Novu Work"
---
-Novu comprises two fundamental components: an API for data exchange and a dashboard for designing notifications and their accompanying logical rules.
+The [Novu Framework](/sdks/framework/typescript/overview) enables you to work in your application, use your own libraries, and connect to your production environment during workflow execution over HTTPS.
-This section provides a broad overview of Novu's functionality, delving into key concepts for your initial Novu journey. If you prefer to dive into development, explore our **[Quick Start guides](/quickstarts/overview)**.
+The framework exports the client you use to define and serve your workflows and their steps over HTTPS.
+The workflows can be added to your preferred framework. During workflow execution Novu Cloud makes HTTPS requests to your [Bridge Endpoint](/concepts/endpoint) for _just-in-time_ content and [Subscribers](/concepts/subscribers) resolution.
-## Architecture
-
-Novu's Object Communication Layer (OCL) is a structured framework that separates communication tasks into specialized components.
-Similar to microservices, these components handle specific roles like message passing and data management. By doing so, OCL enhances system maintenance and scalability, making it easier to integrate new functionalities.
-
-Novu's approach goes beyond this, optimizing communication protocols for seamless collaboration and adaptability. It's like providing a playbook for coordinating a dynamic game, ensuring all players are synchronized for any challenge.
-
-
+
+
+
diff --git a/getting-started/introduction.mdx b/getting-started/introduction.mdx
index 97a046ca..82d01bba 100644
--- a/getting-started/introduction.mdx
+++ b/getting-started/introduction.mdx
@@ -1,186 +1,40 @@
---
-title: "What is Novu?"
-description: "Novu is a full-stack (UI, API & GitOps) open source notification infrastructure tool and platform for building, managing, delivering, and monitoring all types of end-user notifications."
-icon: "arrow-right-to-arc"
+title: "What is Novu"
+description: "Novu is a full-stack (UI Components, API, and Framework) open source notification infrastructure platform for building, managing, delivering, and monitoring all types of end-user notifications."
---
-Novu supports a variety of common notification channels out-of-the-box, including **email**, **SMS**, **push**, **in-app**, and **chat**. Our platform is a developer-first product built for engineers that need to simplify the complexities of notification management, while working closely with product and marketing teams that need to provide, edit, and maintain notification content.
-
-
-
-
-
- Get started in minutes
-
-
-
- Embed a real-time notification center component in your React application.
-
-
- Embed a real-time notification center component in your Vue application.
-
-
- Embed a real-time notification center component in your Angular application.
-
-
-
-
-
-
-
-
-
-
- } color="#16a34a" href="/quickstarts/kotlin">
- Embed a real-time notification center component in your Kotlin application.
-
-
- } color="#16a34a" href="/quickstarts/php">
- Embed a real-time notification center component in your PHP application.
-
-
-
- }
- color="#16a34a"
- href="/quickstarts/ruby">
- Embed a real-time notification center component in your Ruby application.
-
-
-
+import { EchoTerminal } from "/snippets/echo-terminal.mdx";
-
-
-
- You can interface with Novu's API either over REST, or via libraries for certain languages. Below is a list of our official, supported libraries.
- ### Client Side
- The Client side libraries and components helps to add a fully functional notification center to your application.
-
-
- Embed a real-time notification center component in your React application.
-
-
- Embed a real-time notification center component in your Vue application.
-
-
- Embed a real-time notification center component in your Angular application.
-
-
- Embed a real-time notification center component in your JavaScript application.
-
-
- Embed a real-time notification center inside an iframe using our embedded script.
-
-
- Embed a notification system into any framework or vanilla JavaScript project, without being constrained by our default UI or dependencies.
-
-
+ Novu is a developer-first product built for engineers looking to deliver a notifications platform for products. Novu simplifies the complexities of notification management for developers who can then empower the product and marketing teams that need to edit and maintain notification content and copy. Novu supports a variety of common notification channels out-of-the-box, including **Email**, **SMS**, **Push**, **Inbox**, and **Chat**.
-### Server Side
-
-The Server Side libraries help to trigger notifications and interact with all of Novu’s API seamlessly.
-
-
-
- } color="#ea5a0c" href="/sdks/nodejs">
- Connect your Node app to Novu via the Node.js SDK.
-
-
- }color="#0285c7" href="/sdks/go">
- Connect your Golang app to Novu via the Go SDK.
-
-
- } color="#16a34a" href="/sdks/php">
- Connect your PHP app to Novu via the PHP SDK.
-
-
- Connect your Laravel app to Novu via the Laravel SDK.
-
-
- } color="#dc2626" href="/sdks/dotnet">
- Connect your C#/.NET app to Novu via the .NET SDK.
-
-
-
- }
- color="#dc2626"
- href="/sdks/ruby"
-
->
-
- Connect your Ruby app to Novu via the Ruby SDK.
-
-
-
- } color="#dc2626" href="/sdks/java">
- Connect your Java app to Novu via the Java SDK.
-
-
-
-
-
-
-
-
-
-
-
- }
- color="#16a34a"
- href="/sdks/kotlin"
- >
- Connect your Kotlin app to Novu via the Kotlin SDK.
-
-
- }color="#dc2626" href="/sdks/python">
- Connect your Python app to Novu via the Python SDK.
-
-
+The [Novu Cloud Platform](https://dashboard.novu.co) provides an intuitive internal user interface, embeddable UI end-user components, and a code-first workflow capability.
+
+
-
-
+## Quick start
-The [Novu Cloud SaaS](https://web.novu.co) platform provides an intuitive internal user interface, embeddable UI end-user components, and a hybrid code-first workflow capability.
+Start building with Novu by following our Quick Start guides. These guides provide step-by-step instructions for integrating Novu into your application.
-Novu eliminates the significant burden of building, hosting, and managing a notifications infrastructure that all modern software businesses need in order to notify and engage staff, end users, and customers.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
## Notification types
@@ -199,77 +53,53 @@ Novu supports different notification types, including user-generated and machine
- Typically transactional, such as order updates, password resets, account verifications, or login/OTP codes.
- Can also be used to provide product updates, such as new features or bug fixes.
-### Promotional notifications
-
-- Centered on promoting products, services, or events.
-- Can be used to generate leads, increase sales, or drive engagement.
-
-### Key Differences
+### Key differences
- Product notifications are triggered by user activity, while promotional notifications are sent at the discretion of the marketer.
- Product notifications are typically more transactional in nature, while promotional notifications are more marketing-oriented.
- Product notifications are often sent to all subscribers, while promotional notifications can be targeted to specific audiences.
-## Notification channels
-Novu supports all major notification channels, and integrates with multiple delivery providers for each one. Each channel can use the same source notification content, as desired.
-- [Email](/channels-and-providers/email/overview)
-- [Push](/channels-and-providers/push/overview)
-- [SMS](/channels-and-providers/sms/overview)
-- [Chat](/channels-and-providers/chat/overview)
-- [In-App](/channels-and-providers/in-app/introduction)
-
## Who is Novu for?
-How you use and get started with Novu depends on your role. While it’s implemented initially by engineering and development teams, Novu unifies everyone in an organization that authors, creates, sends, manages and measures results from notifications being sent to end users. Novu empowers engineers to deliver notification platforms for product teams.
+How you use and get started with Novu depends on your role. While it’s initially implemented by engineering and development teams, Novu unifies everyone in an organization that authors, creates, sends, manages, and measures results from notifications being sent to end users. Novu empowers engineers to deliver notification platforms for product teams.
-### Novu for developers and engineering teams
+### Novu for engineers
-Novu empowers developers and engineering teams to quickly deliver a fully extensible notifications platform for product teams to create captivating notification experiences.
+Novu empowers developers and engineering teams to quickly deliver a fully extensible notifications platform for product teams to create captivating notification experiences.
-We provide the following proven stack for developers to simply integrate into their products:
+We provide the following proven stack for developers to simply integrate notifications into their products:
-- **[Unified API](/api-reference/overview) & [SDK clients](/sdks/introduction)** for managing all channels and platforms across multiple programming languages.
-- **[Prebuilt, customisable UI components](/notification-center/introduction#ui-libraries)** for in-app user notification feeds and preference experiences.
-- **[Integration with multiple delivery providers](/channels-and-providers/introduction)**, allowing you to continue using your preferred vendors with Novu.
-- **[Scalable, reliable Novu Cloud SaaS infrastructure](https://web.novu.co)** developed from scratch to meet the demands of high-volume notification delivery and storage (think hundreds of millions of notifications).
-- **[Observability](/activity-feed/introduction)** for delving into the lifecycle of notification’s success or failure. Eliminate guesswork of how, when, and why a user receives a notification.
+- **[Code-first Notification Framework](/sdks/framework/typescript/overview)** Opinionated, yet flexible, Framework for building and managing notification workflows.
+- **[JSON Schema Based](/api-reference/overview)** Controls to craft a no-code visual editor to enable non-technical team members to modify content and behaviour.
+- **[Prebuilt, customisable UI components](/inbox/introduction)** for in-app user notification feeds and preference experiences.
+- **[Integration with multiple delivery providers](/integrations/providers/introduction)**, allowing you to continue using your preferred vendors with Novu.
+- **[Scalable, reliable Novu Cloud SaaS infrastructure](https://dashboard.novu.co)** developed from scratch to meet the demands of high-volume notification delivery and storage (think hundreds of millions of notifications).
+- **Observability** for delving into the lifecycle of a notification's success or failure. Eliminate guesswork of how, when, and why a user receives a notification.
- **Comprehensive documentation**, implementation guides, recipes and illustrative examples.
- **Compliance and security** for safely managing your data.
-- **Open source** based provides trust, generates significant community input, and enables you to deploy and self-host a Novu Project instance into any environment of your choosing.
-
-Notification content can be written in a variety of common content tooling, including [React](/framework/integrations/react-email), [Vue-email](/framework/integrations/vue-email), [MJML](/guides/framework-guides/framework-mjml), and more. Content can also be customized and hydrated using any datasource.
+- **Open source** provides transparency you can trust, cultivates community contributions for fast improvement, and enables you to deploy and self-host a Novu instance into any environment of your choosing.
+Notification content can be written in a variety of common content tooling, including [React](/integrations/react-email), [Vue-email](/integrations/vue-email), MJML, and more. Content can also be customized and hydrated using any datasource.
### Novu for product teams
-We are well aware of the friction that often exists between engineering and product teams, and have built features that allow product teams to customize notification experiences easily and safely—without risking disrupting or breaking important integrations and logic.
+We are well aware of the friction that often exists between engineering and product teams, and have built features that allow product teams to customize notification experiences easily and safely—without the risk of breaking important integrations and logic.
-Product teams can craft beautiful notification content and campaigns in any content framework of their choice.
+Product teams can craft beautiful notification content and campaigns in any content framework of their choice.
-- They can modify and manage notification UIs that engineers have built via Novu workflows.
-- They gain valuable insights into user engagement with notifications via logs and analytics.
-- They can use their preferred notification content editors.
-- They can focus on crafting impactful notification content while engineers
+{/* Since we're speaking to both engineering and product in this section of the documentation, we should address product teams directly instead of using third-person "them" */}
+- Modify and manage notification UIs that engineers have built via the Novu Framework.
+- Gain valuable insights into user engagement with notifications via logs and analytics.
+- Use your preferred notification content editors.
+- Craft impactful notification messaging, verbiage, and cadences.
+- Run experiments to improve user experience without requiring engineering effort.
### Novu for end users
-When implemented, most end users will not be aware that it’s Novu behind the scenes, other than that they now receive notifications where and when they expect them.
-
-The [Novu Notification Center](/notification-center/introduction) is an embeddable component that when included in your app, enables users to view and set their own notification preferences, including channel, preferred language, and more.
-
-Novu ensures fast delivery and beautiful notification experiences for end users regardless of the channels involved.
-
-With Novu, your app users receive instant notifications via **email**, **in-app alerts**, **SMS**, **push notifications**, and **chat**.
+Once implemented, most end users will not be aware that it’s Novu behind the scenes, other than that they now receive notifications where and when they expect them.
-## Use Cases
+The [Inbox Component](/inbox/introduction) is an embeddable component that, when included in your app, enables users to view and set their own notification preferences--such as channel, language, timezone, and more.
-Novu is heavily customizable, and can tackle nearly any notification requirement, no matter how simple or complex. These are some of the more common use cases:
+Novu ensures fast delivery and beautiful notification experiences for end users regardless of the channels involved.
-- **Manage multiple notification providers:** Novu empowers you to manage all your notification delivery providers across email, SMS, push and chat in one place. Developers can add new notification providers across different channels without changing the app codebase.
-- **Centralize legacy notification systems:** Reduce notification complexity, unify management and visibility into one platform.
-- **Centralized debugging of notifications across multiple channels**: Novu allows you understand and debug notifications sent across different channels in one place.
-- **In-app Notification Center:** Novu provides a real-time embedded notification center widget that can simply be dropped into any web application to enable end users to manage their own notification preferences.
-- **Notification personalization:** Novu provides a user preferences feature that gives your end users a say in how they want to receive notifications.
-- **Notification content management:** Novu provides the ability to integrate any content framework and tool of your choice to manage notification content across teams.
-- **Send notifications in users language of choice**: Novu allows you to send notifications in preferred users language. App and notification internalization increases users engagement and retention in your product.
-- **Reduce notification alert fatigue**: Novu prevents notification fatigue by providing the ability to batch multiple notifications and send as one to subscribers (end users). Leverage Novu in digesting multiple notification events.
+With Novu, your app users receive instant notifications via **email**, **Inbox alerts**, **SMS**, **push notifications**, and **chat**.
diff --git a/getting-started/non-technical.mdx b/getting-started/non-technical.mdx
new file mode 100644
index 00000000..6d36cecb
--- /dev/null
+++ b/getting-started/non-technical.mdx
@@ -0,0 +1,41 @@
+---
+title: "No-Code tools to manage your notifications"
+sidebarTitle: "For Non-Developers"
+description: "Change notification messaging, verbiage, and cadence without requiring engineering's help by using the Novu Dashboard UI."
+---
+
+Novu Framework was designed to bridge the gap between developers and non-developers in the team.
+
+- **Developers** - Define and abstract away complex logic, data manipulation, hydration, html, and etc...
+- **Non-Developers** - Use the Novu Dashboard UI to control the content and behavior of the notifications using [Controls](/concepts/controls).
+
+## How to modify Controls?
+
+Controls are modified directly in the [Novu Dashboard UI](https://dashboard.novu.co), under the 'Controls' tab of the Workflow editor page.
+Upon saving the changes, the new Control values will be used in the notification sent to your subscribers.
+
+## Dynamic payload data
+
+Dynamic data passed as part of the trigger payload can be easily used inside of the Controls. For example, you can pass a `user_name` as part of the payload and use it in the controls as `{{user_name}}` to personalize the notification.
+
+## Common usecases
+
+### Change notification content
+
+A control can be as broad as `content` or as specific as `2fa_code_title_color`. This allows you to change the content of the notification without needing to touch the code.
+
+### Change Digest or Delay frequency
+
+Controls can be used for controlling any aspect of the step configuration, for example:
+
+- Delay amount
+- Digest length
+- Digest type (Daily, Weekly, Monthly)
+- etc...
+
+Read more about [digest strategies and how to prevent notification fatigue.](https://novu.co/blog/digest-notifications-best-practices-example/)
+
+### Control structure and layout
+
+Controls can be used to show/hide or rearrange the layout of the notification.
+For example, you can have an input to show/hide a button, or change the position of a specific email section.
diff --git a/getting-started/novu-sign-up.mdx b/getting-started/novu-sign-up.mdx
deleted file mode 100644
index cc4f24c9..00000000
--- a/getting-started/novu-sign-up.mdx
+++ /dev/null
@@ -1,36 +0,0 @@
----
-title: 'Sign Up on Novu Cloud'
-description: 'Sign up to our managed service'
-icon: 'user-plus'
----
-
-## Introduction
-
-Novu’s aim is to simplify sending notifications across platforms. As such, we provide simple components, APIs, SDKs and more to help you manage product communication across channels.
-
-This comprehensive guide will help you kickstart your journey with Novu and get your hands dirty!
-
-Everything you need to get up and running successfully can be found here. Let’s begin!
-
-## Signing up to Novu Cloud
-
-Novu Cloud is our managed service that lets you oversee all aspects of your product communication from a user-friendly web dashboard. With Novu Cloud, you can handle various communication channels, create and manage workflows, switch organizations and monitor your activity, ensuring that you get comprehensive control over your product communication and that your message reaches your customers effectively.
-
-To be able to do this and a lot more, you need to sign up for Novu Cloud:
-
-1. Head to [Novu Cloud](https://web.novu.co/auth/signup?utm_campaign=docs-gs-signup). You’ll see this:
-
-2. To sign up, you can either use your email and password or sign up using Github. Choose what you wish to proceed with, read the terms and conditions, check its checkbox and click the sign-up button.
-
-3. You’ll then be asked to create an Organization. Organizations help you segregate communication between your different products. You can learn more about organisations here. Simply enter your organization name and click on the ‘create’ button:
-
-4. On creating an organization, you’ll be greeted with the get started page:
-
-This gives you access to a lot of options:
-
-1. Accessing support
-2. Managing your account
-3. Configuring different channels
-4. Navigating to any other sections of the dashboard
-
-From here, you can navigate to any part of the web dashboard. Let’s now see Novu in action!
\ No newline at end of file
diff --git a/getting-started/send-your-first-notification.mdx b/getting-started/send-your-first-notification.mdx
deleted file mode 100644
index 6d4f2d7a..00000000
--- a/getting-started/send-your-first-notification.mdx
+++ /dev/null
@@ -1,299 +0,0 @@
----
-title: 'Send Your First Notification'
-sidebarTitle: 'Send First Notification'
-description: 'Learn how to send your first notification via the Novu Cloud dashboard.'
-icon: 'bell'
----
-
-Sending the first notification is fairly simple, and can be done from within the web dashboard. To send your first notification, follow these steps:
-
-## Workflow for Email notifications
-
-1. Navigate to the workflow section from the left sidebar:
-
-
-
-
-
-2. Click on the `Blank Workflow` button to create an empty workflow:
-
-
-
-
-
-3. You are now in the workflow editor. Here you can add steps to your workflow. We’ll just drag the email node from the right sidebar to our workflow as illustrated below:
-
-
-
-
-
-4. Now, simply click on the email node, and add the subject and the notification
- text in the email node editor:
-
-
-
-
-
-5. Now, update the workflow and save it as shown in the image below:
-
-
-
-
-
-6. Now, to execute this workflow, click on the `get snippet` button from the workflow editor:
-
-
-
-
-
-7. From the `run a test` tab, you can change the email to which you want the notification. Once you’ve done that, simply click on the `Run Trigger` button on the bottom right:
-
-
-
-
-
-8. Now, go to the inbox and you’ll see the email notification there. Don’t forget also to check spam as it may sometimes land in there:
-
-
-
-
-
-9. This gif below captures the entire process:
-
-
-
-
-
-## Workflow for In-App notifications
-
-Creating workflows for sending in-app notifications is pretty straightforward. Just follow the following steps and you'll be good to go:
-
-1. Head to `workflows` on the [Novu web dashboard](https://web.novu.co/workflows?utm_campaign=docs-gs-sendfirstnotification).
-
-
-
-
-
-2. Click on the Blank Workflow button to create a workflow from scratch.
-
-
-
-
-
-
- If you want to avoid creating a workflow from scratch, then instead of
- choosing `Blank Workflow`, select `All Templates` and you'll find a bunch of
- workflow templates that you can customize and use:
-
-
-
-
-
-
-
-
-
-3. You'll now end up in the workflow editor. Workflow editor, as the name suggests, is the place from where you can edit workflows. You can select which [channels](/channels-and-providers/introduction#channels) you want to send notifications in, add [digest](/guides/add-digest-to-inapp-notifications) to your in-app notifications and more.
-
-
-
-
-
-4. For your use case here, we'll simply add an `in-app` node to our workflow.
-
-
- Don't forget to rename your workflow to an appropriate name.
-
-
-
-
-
-5. Now, the `in-app` node has a lot of options for you to configure:
-
-
-
-
-
-- **Preview**: This shows you a glimpse of what each notification item will look like in the Notification Center UI.
-- **Avatar:** If turned on, each notification item will show the avatar of the subscriber.
-- **Action:** With this, you can add a primary and secondary call to action button to each notification item.
-- **Notification Feeds:** This displays a stream of specific notifications. You can have multiple feeds to show specific notifications in multiple tabs.
-- **Redirect URL** - This is the URL to which a subscriber can be directed when they click on a notification item.
-- **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.
-
-6. In this editor, you need to plug in the variable that your backend is expecting in the payload:
-
-
-
-
-
-7. You can even use [handlebars](/content-creation-design/handlebars-helpers) to further customise this.
-
-8. Once you're done configuring it, simply click the `update` button on the top right corner.
-
-
-
-
-
-9. Now, simply click on the `Get Snippet` button to get the trigger code snippet.
-
-
-
-
-
-10. You'll get the code that you need to plug into your backend to be executed whenever an event fires.
-
-
-
-
-
-
- Don't forget to use your actual `API_KEY` and `subscriberId`.
-
-
-That's it, you've successfully built a workflow for sending in-app notifications!
-
-## Workflow for SMS notifications
-
-SMS workflows are not very different from [email](/getting-started/send-your-first-notification#workflow-for-email-notifications) and [in-app](localhost:3001/getting-started/send-your-first-notification#workflow-for-in-app-notifications) workflows we've created above. Let's take a look at it:
-
-1. Head to `Workflows` on the [Novu web dashboard.](https://web.novu.co/workflows?utm_campaign=docs-gs-sendfirstnotification)
-
-
-
-
-
-2. Click on the `Blank Workflow` button to create a workflow from scratch.
-
-
-
-
-
-
- If you want to avoid creating a workflow from scratch, then instead of
- choosing `Blank Workflow`, select `All Templates` and you'll find a bunch of
- workflow templates that you can customize and use:
-
-
-
-
-
-
-
-
-
-3. You'll now end up in the workflow editor. Workflow editor, as the name suggests, is the place from where you can edit workflows. You can select which [channels](/channels-and-providers/introduction#channels) you want to send notifications in, add [digest](/guides/add-digest-to-inapp-notifications) to your in-app notifications and more.
-
-
-
-
-
-4. Since we're creating a workflow for SMS notifications, we'll drag the `SMS` step to our workflow, as shown in this picture below:
-
-
-
-
-
-5. If you hover over the SMS node, you will get a message saying 'Required - SMS content`. Click on the SMS node and add a message to it. This is what will be sent as a notification in the SMS.
-
-
-
-
-
-
- Instead of having static messages, you can have your notifications be
- dynamic by using `handlebars`. Take a look
- [here](/content-creation-design/handlebars-helpers) for more. If your
- backend is expecting data in the payload, plug that variable here in double
- braces.
-
-
-6. Once you’re done configuring it, simply click the update button on the top right corner.
-
-
-
-
-
-7. Now, simply click on the Get Snippet button to get the trigger code snippet.
-
-
-
-
-
-8. You’ll get the code that you need to plug into your backend to be executed whenever an event fires.
-
-
-
-
- Don’t forget to use your actual API_KEY and subscriberId.
- That’s it, you’ve successfully built a workflow for sending in-app
- notifications!
-
-## Workflow for Chat notifications
-
-Chat workflows are quite similar to [email](/getting-started/send-your-first-notification#workflow-for-email-notifications), [in-app](localhost:3001/getting-started/send-your-first-notification#workflow-for-in-app-notifications), and [SMS workflows](/getting-started/send-your-first-notification#workflow-for-sms-notifications) workflows we've created above. Let's take a look at it in detail:
-
-1. Head to `Workflows` on the [Novu web dashboard.](https://web.novu.co/workflows?utm_campaign=docs-gs-sendfirstnotification)
-
-
-
-
-
-2. Click on the `Blank Workflow` button to create a workflow from scratch.
-
-
-
-
-
-
- If you want to avoid creating a workflow from scratch, then instead of
- choosing `Blank Workflow`, select `All Templates` and you'll find a bunch
- of workflow templates that you can customize and use:
-
-
-
-
-
-
-
-
-
-3. You'll now end up in the workflow editor. Workflow editor, as the name suggests, is the place from where you can edit workflows. You can select which [channels](/channels-and-providers/introduction#channels) you want to send notifications in, add [digest](/guides/add-digest-to-inapp-notifications) to your in-app notifications and more.
-
-
-
-
-
-4. Just add this `Chat` node to the workflow.
-
-
-
-
-
-5. In the `Chat` node, you can enter the notification message. This is what will get sent to the [subscriber](/subscribers/subscribers) as a notification. If you're sending dynamic messages, use the variable that is expected in your payload in double braces here. Using [handlebars](/content-creation-design/handlebars-helpers), you can further extend this functionality.
-
-
-
-
-
-6. Once you’re done configuring it, simply click the update button on the top right corner.
-
-
-
-
-
-7. Now, simply click on the Get Snippet button to get the trigger code snippet.
-
-
-
-
-
-8. You’ll get the code that you need to plug into your backend to be executed whenever an event fires.
-
-
-
-
- Don’t forget to use your actual API_KEY and subscriberId.
- That’s it, you’ve successfully built a workflow for sending chat notifications!
-
-Don't forget to check out our [guides](/guides/add-digest-to-inapp-notifications) and [demo apps](/demos/introduction) for more information on specific features.
\ No newline at end of file
diff --git a/guides/demos/introduction.mdx b/guides/demos/introduction.mdx
deleted file mode 100644
index eb340072..00000000
--- a/guides/demos/introduction.mdx
+++ /dev/null
@@ -1,79 +0,0 @@
----
-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/guides/framework-guides/framework-remix.mdx b/guides/framework-guides/framework-remix.mdx
deleted file mode 100644
index e8c1ef5d..00000000
--- a/guides/framework-guides/framework-remix.mdx
+++ /dev/null
@@ -1,319 +0,0 @@
----
-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_API_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),
- };
- }, {
- inputSchema: {
- 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 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://web.novu.co) or [code](/quickstarts/react#trigger-a-notification).
-
-```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](/guides/framework-guides/product) on how to empower product teams to manage notification workflows.
\ No newline at end of file
diff --git a/guides/framework-guides/otp.mdx b/guides/framework-guides/otp.mdx
deleted file mode 100644
index d0acde68..00000000
--- a/guides/framework-guides/otp.mdx
+++ /dev/null
@@ -1,316 +0,0 @@
----
-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 create-novu-app@latest --api-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_API_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),
- };
- }, {
- inputSchema: {
- 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](/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!
\ No newline at end of file
diff --git a/guides/how-to-integrate-segment-with-novu.mdx b/guides/integrations/segment.mdx
similarity index 76%
rename from guides/how-to-integrate-segment-with-novu.mdx
rename to guides/integrations/segment.mdx
index cdb2ce78..049d8b68 100644
--- a/guides/how-to-integrate-segment-with-novu.mdx
+++ b/guides/integrations/segment.mdx
@@ -1,13 +1,13 @@
---
-title: 'How To Integrate Segment With Novu'
-description: ''
+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
+## Examples Use Case
**Enhancing Customer Engagement and Conversion Rates**
@@ -16,12 +16,12 @@ If this is your first time working with the tool, consider consulting the 'Get S
- 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.
-
@@ -30,15 +30,18 @@ If this is your first time working with the tool, consider consulting the 'Get S
- 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.
@@ -62,7 +65,6 @@ frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media
-
**Outcome:**
- Enhanced customer engagement through personalized and timely notifications.
@@ -78,17 +80,26 @@ As of today Segment doesn’t have
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.
+
+ 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.
+
+ {" "}
+ 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.
@@ -105,7 +116,7 @@ Destination functions can define handlers for each message type in the Segment s
Each of the functions above accepts two arguments:
-`event` - Segment event object, where fields and values depend on the event type.
+`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.
@@ -113,26 +124,28 @@ The example below shows a destination function that listens for “Track” even
```javascript
async function onTrack(event) {
- await fetch('https://example-service.com/api', {
- method: 'POST',
+ await fetch("https://example-service.com/api", {
+ method: "POST",
headers: {
- 'Content-Type': 'application/json'
+ "Content-Type": "application/json",
},
body: JSON.stringify({
event_name: event.event,
event_properties: event.properties,
- timestamp: event.timestamp
- })
- })
+ timestamp: event.timestamp,
+ }),
+ });
}
```
-To change which event type the handler listens to, you can rename it to the name of the message type.
+
+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!
+ 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
@@ -148,54 +161,56 @@ To successfully send a payload to Novu, triggering the appropriate [workflow](/g
```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}`);
- }
- }
+ 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).
@@ -216,6 +231,7 @@ Now, while configuring the function, Add these three variables to be then used i
#### Test the destination function
+
You can test your code directly from the editor in two ways:
**1. Use sample events for testing**
@@ -235,6 +251,7 @@ You can also manually include your own JSON payload of a Segment event, instead
**Here is the the event example JSON we will use**
+
```JSON
{
"type": "track",
@@ -258,21 +275,14 @@ We will now execute the function based on the manual event input we've provided.
-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://web.novu.co/activities?utm_campaign=docs-guides-segment).
+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.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/guides/novu-fcm-web.mdx b/guides/novu-fcm-web.mdx
deleted file mode 100644
index 7cbb35f5..00000000
--- a/guides/novu-fcm-web.mdx
+++ /dev/null
@@ -1,218 +0,0 @@
----
-title: 'How to send web push notifications with FCM and Novu'
-description: 'Send FCM push notifications in a React app using Novu'
----
-
-## Introduction
-In this guide, we'll learn how to send FCM push notifications in a web app using Novu. But before exploring the actual code, let’s understand what a push notification is and how it works.
-You can find the [frontend code](https://github.com/novuhq/fcmWebPushFE) as well as [backend code](https://github.com/novuhq/FCMWebPushBE) for the app on Github.
-
-Push notifications are notifications that are sent to a user's devices whether the user is using the app or not. We'll be using Firebase Cloud Messaging (FCM) integration of Novu to send these notifications. This guide will be broken down into three parts:
-1. Setting up Novu.
-2. Setting up Firebase.
-3. Adding Firebase to the Frontend.
-4. Adding Novu to the Backend.
-
-## Setting up Firebase
-1. Create a Firebase account if you don't already have one. Then, create a new project and all the relevant details.
-
-2. Once your project has been created, you'll be greeted with this welcome screen and asked to add Firebase to your app, so let's do that.
-
-3. We'll choose the web option because we're creating a web app.
-
-4. Give your app a name and click on the 'Register' button.
-
-5. We're done with the Firebase setup! Now, we'll set up Novu and finally proceed to add both (Novu and FCM) to our app.
-
-## Setting up Novu
-We'll need a workflow to trigger notifications to our user's devices. Follow the steps below to create one to ensure we are on the path to make FCM work as expected:
-1. Head over to the [Integrations Store](https://web.novu.co/integrations?utm_campaign=docs-guides-fcm-web) on the Novu Web Dashboard and make sure that you've turned on the 'Firebase Cloud Messaging' integration.
-
-If you're doing this for the first time, you'll need to get your service account key from the [Firebase Console](https://console.firebase.google.com/). Read more about it in our [FCM provider docs.](https://docs.novu.co/channels-and-providers/push/fcm)
-2. Now, we need to create a workflow that we'll trigger from our app to send notifications. Head over to [workflows in the Novu Web Dashboard](https://web.novu.co/workflows?utm_campaign=docs-guides-fcm-web) and click on the 'Add a workflow' button.
-
-3. Choose the 'blank workflow' option from the dropdown menu.
-
-3. Drag and drop the 'Push' node below the Workflow Trigger node.
-
-4. If you hover over the newly added 'Push' node, you'll see an error saying 'Message content and title are missing'.
-
-5. We're going to use the identifiers `title` and `body` for the title and the content of notifications, so let's add them in the 'Push message title' and the 'Push message content' fields respectively. So, add them and give your workflow a suitable name.
-
-6. Now, click on the 'get snippet' button to get the trigger code.
-
-
-## Adding Firebase to the frontend
-1. In your project, add Firebase using the following command:
-```bash
-npm install firebase
-```
-2. Create a new file called `firebase.js` and add the following to it:
-```jsx
-import { initializeApp } from "firebase/app";
-import { getMessaging, onMessage } from "firebase/messaging";
-
-//from firebase console
-// Your web app's Firebase configuration
-const firebaseConfig = {
- apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
- authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
- projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
- storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
- messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
- appId: import.meta.env.VITE_FIREBASE_APP_ID,
-};
-
-// Initialize Firebase
-export const app = initializeApp(firebaseConfig);
-
-// Initialize Firebase Cloud Messaging and get a reference to the service
-export const messaging = getMessaging(app);
-
-export const onMessageListener = () =>
- new Promise((resolve) => {
- onMessage(messaging, (payload) => {
- console.log("payload", payload)
- resolve(payload);
- });
- });
-```
-3. Now, we need to generate tokens using the `getToken` method provided by Firebase. But we want to use this only when the user has allowed notifications on their end. So let's request notification permission from the user and if granted, we'll generate the token. Add this to your root module:
-```jsx
- async function requestPermission() {
- const permission = await Notification.requestPermission()
- if (permission === 'granted') {
- // get token
- const token = await getToken(messaging, { vapidkey: import.meta.env.VITE_VAPID_KEY })
- } else if (permission === 'denied') {
- alert('Persmission denied!')
- }
- }
- useEffect(() => {
- requestPermission();
- }, [])
-```
-4. To use the `getToken` method, you need a Voluntary Application Server Identification or `VAPID key`. Go to your Project Settings -> Cloud Messaging -> Generate key pair (under Web Push Certificates):
-
-5. In order for Firebase's background listener service to work, you need a service worker. Make sure you've created a service worker file `firebase-messaging-sw.js` and add the following to it:
-```jsx
-importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js");
-importScripts(
- "https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js"
-);
-
-const firebaseConfig = {
- apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
- authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
- projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
- storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
- messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
- appId: import.meta.env.VITE_FIREBASE_APP_ID,
-};
-
-firebase.initializeApp(firebaseConfig);
-const messaging = firebase.messaging();
-messaging.onBackgroundMessage((payload) => {
- console.log(
- "notif incoming",
- payload
- );
- const notificationTitle = JSON.parse(JSON.parse(payload.notification)).title
- // payload.notification.title;
- const notificationOptions = {
- body: payload.notification.body,
- icon: payload.notification.image,
- };
-
- self.registration.showNotification(notificationTitle, notificationOptions);
-});
-
-
-```
-
-## Adding Novu to the backend
-In your app's backend, add Novu using the following command:
-```bash
-npm install @novu/node
-```
-Now, create a route that you want to hit when called from the front end. In our app, this is the route:
-```jsx
-import express from "express";
-import { createNotif } from '../controller/notif.js'
-
-const router = express.Router();
-
-router.post('/create', createNotif)
-
-export default router;
-```
-
-Now, we need a controller function to 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 { inAppNotification } from "../novu/novu.js";
-
-export const createNotif = async (req, res) => {
-
- const { title, body } = req.body
- try {
- await inAppNotification(title, body);
- res.status(201).json({ message: 'success', title: title, body: body });
- } 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 `createNotif`.
-
-If you’re following the guide, you should already have the trigger function. But before we can add it to our app, we need one key thing - **Subscribers.**
-
-[Subscribers](https://docs.novu.co/subscribers/subscribers) are entities to which the notifications are sent. You can see a list of subscribers in the [Novu dashboard](https://web.novu.co/subscribers?utm_campaign=docs-guides-fcm-web) as well.
-
-We'll create a subscriber in our app. Our backend will be written in Node.js, but we also have backend [SDKs in PHP, .NET, Go, Ruby, Python, and Kotlin](/sdks/introduction). The recommended way to create a subscriber in NodeJS is as follows:
-```jsx
- await novu.subscribers.identify(process.env.NOVU_SUB_ID, {
- firstName: "pushSubscriber"
- });
-```
-Here, we're creating a subscriber with the `subscriberID` of whatever value the `env` file contains for the identifier `NOVU_SUB_ID`. You can read more about subscribers [in our docs.](/subscribers/subscribers).
-
-Back in our app, before we can now add the trigger function, we need to set device identifiers using the [setCredential method](https://docs.novu.co/channels-and-providers/push/fcm#set-device-token):
-```jsx
-await novu.subscribers.setCredentials(process.env.NOVU_SUB_ID, PushProviderIdEnum.FCM, {
- deviceTokens: [process.env.DEVICE_TOKEN],
- });
-```
-
-You'll need to pass the `subscriberID` and the `deviceTokens` in the `setCredentials` method.
-
-Finally, we can add the trigger code:
-```jsx
-import { Novu, PushProviderIdEnum } from '@novu/node';
-
-export const inAppNotification = async (title, body) => {
-
- const novu = new Novu(process.env.NOVU_API_KEY);
- await novu.subscribers.identify(process.env.NOVU_SUB_ID, {
- firstName: "pushSubscriber"
- });
-
- await novu.subscribers.setCredentials(process.env.NOVU_SUB_ID, PushProviderIdEnum.FCM, {
- deviceTokens: [process.env.DEVICE_TOKEN],
- });
-
- novu.trigger(process.env.NOVU_WORKFLOW_ID, {
- to: {
- subscriberId: process.env.NOVU_SUB_ID
- },
- payload: {
- title: title,
- body: body
- },
- });
-};
-```
-
-We're done with the app. You can find the [frontend code](https://github.com/novuhq/fcmWebPushFE) as well as [backend code](https://github.com/novuhq/FCMWebPushBE) for the app on Github.
-
-Congratulations on following the guide up until this point. If you’ve done everything as recommended, you’ll end up with an app that uses Firebase Cloud Messaging to send notifications to your users using Novu.
\ No newline at end of file
diff --git a/guides/slack-guide.mdx b/guides/slack-guide.mdx
deleted file mode 100644
index 10e23479..00000000
--- a/guides/slack-guide.mdx
+++ /dev/null
@@ -1,187 +0,0 @@
----
-title: 'How to use Novu to send notifications to a Slack channel'
-description: 'Learn to send Slack notifications swiftly with Novu (manually managed)'
----
-
-# Introduction
-
-In this guide, you'll learn how to use Novu to send notifications directly to a Slack channel. But before coding anything up, we first need to go through a setup process.
-The corresponding docs for this guide are available on our [docs](https://docs.novu.co/channels-and-providers/chat/slack).
-The entire code of this app (frontend as well as backend) can be found [here](https://github.com/novuhq/slack-app).
-
-So let's begin!
-
-# Create a Slack App
-Creating a Slack app is fairly simple. Follow these steps to create your app:
-1. Go to [Slack's app dashboard](https://api.slack.com/apps) and click on the 'Create new App' button, as shown in the image:
-
-2. Choose 'From Scratch' from the following dialog:
-
-3. Choose a name for your app and select the Slack workspace in which you want to send notifications:
-
-4. Once you're done, simply click the 'Create App' button:
-
-5. Once done, you'll be greeted with the screen shown below. We'll make a couple of changes here and it'll be ready to go.
-
-6. We'll need `Client Id` from the [Slack Developer's Dashboard](https://api.slack.com/apps) for configuring Slack Integration in the [Novu Web Dashboard](https://web.novu.co/integrations?utm_campaign=docs-guides-slack) later, so keep it handy.
-
-
-# Create a workflow in the Novu Web Dashboard
-1. To create a workflow, head to the workflow section in the [Novu Web Dashboard](https://web.novu.co/workflows?utm_campaign=docs-guides-slack).
-2. Click on the 'Add a workflow' button and select 'Blank workflow' from the dropdown.
-
-3. Once there, give your workflow a name and drag and drop the 'chat' option below the 'workflow trigger' step.
-
-4. 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.
-5. Make sure that you've turned on the Slack integration in the [Integrations Store](https://web.novu.co/integrations?utm_campaign=docs-guides-slack).
-
-6. To turn the Slack integration on, you'll need `Client Id`. You should have it already but if you don't, you can obtain it from the [Slack Developer's Dashboard](https://api.slack.com/apps).
-
-7. Once you have it, you need to plug it into the respective field in the [Slack Integration Settings](https://web.novu.co/integrations?utm_campaign=docs-guides-slack) on the Novu Web Dashboard.
-
-
-# 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. We'll also need to add it to our Slack app (discussed below). 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) {
- 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) => {
- const novu = new Novu(process.env.YOUR_NOVU_API_KEY_HERE);
- await novu.subscribers.identify(process.env.SUB_ID, {
- firstName: 'newSubForSlackChat',
- });
-
- await novu.trigger('slack', {
- to: {
- subscriberId: process.env.SUB_ID
- },
- payload: {
- chatMsg: chatMsg
- }
- });
-}
-```
-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. You can find the trigger workflow by clicking on the 'Get Snippet' button on the workflow:
-
-
-
-# Configure the Slack app
-
-There are two ways to configure the Slack app. One is the Novu managed option and another the manually managed option.
-Since the Novu managed is fairly straightforward, I'll demonstrate the manual method here. Follow along to set it up!
-
-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, add the code below to the backend trigger functionality. Using this code, we are specifying what `webhookUrl` Novu will use to authenticate when using the Slack provider.
-
-
-
-```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"
-}'
-```
-
-
-
-In our case, we'll add it to the `Novu.js` file we created earlier so that the final file becomes :
-```jsx
-import { Novu, ChatProviderIdEnum } from '@novu/node';
-
-export const chat = async (chatMsg) => {
- const novu = new Novu(process.env.YOUR_NOVU_API_KEY_HERE);
- await novu.subscribers.identify(process.env.SUB_ID, {
- firstName: 'newSubForSlackChat',
- });
-
- await novu.subscribers.setCredentials(process.env.SUB_ID, ChatProviderIdEnum.Slack, {
- webhookUrl: process.env.SLACK_WEBHOOK_URL,
- });
-
- await novu.trigger('slack', {
- to: {
- subscriberId: process.env.SUB_ID
- },
- payload: {
- chatMsg: chatMsg
- }
- });
-}
-```
-6. Finally, we'll add the route we'd created earlier to the redirect URL section, as shown:
-
-For demonstration purposes, I've added both the local as well as the deployed URL. You only need one depending on whether you're running this locally or have a deployed version.
-Now, our backend is all done, our Slack is all setup and all we need to do is hit the URL
-
-# 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/slack-app/tree/main/frontend).
-And here's our app in all its glory!
-
-
-
-This is how we send Slack notifications using Novu!
\ No newline at end of file
diff --git a/guides/usecases/introduction.mdx b/guides/usecases/introduction.mdx
deleted file mode 100644
index 8fa7c2e5..00000000
--- a/guides/usecases/introduction.mdx
+++ /dev/null
@@ -1,28 +0,0 @@
----
-title: "Learn by usecase"
-description: "Learn Novu's Use Cases"
----
-
-Novu is built to empower engineering teams in integrating rich product notification experiences seamlessly without re-inventing the wheel.
-
-It has been thoroughly and beautifully crafted to help individuals, teams, businesses and organizations focus on what truly matters: creating exceptional user experiences and driving engagement through smooth and swift notifications delivery.
-
-The common use cases for using Novu are highlighted below:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/guides/usecases/multiple-delivery-providers.mdx b/guides/usecases/multiple-delivery-providers.mdx
deleted file mode 100644
index f6d6893c..00000000
--- a/guides/usecases/multiple-delivery-providers.mdx
+++ /dev/null
@@ -1,21 +0,0 @@
----
-title: "Managing multiple delivery providers in one place"
-description: "Learn to manage many delivery providers across different channels in one dashboard"
----
-
-[Novu's dashboard](https://web.novu.co/integrations?utm_campaign=docs-usecases-multipledelivery) empowers you to manage all your notification delivery providers across Email, Sms, Push and Chat in one place.
-
-You can activate, deactivate, modify settings, set primary and secondary active providers as you wish from the dashboard.
-
-
-### Integrations Store
-
-
-
-
-
-### Add a new Delivery Provider
-
-
-
-
diff --git a/guides/workflows/feedback-reviews.mdx b/guides/workflows/feedback-reviews.mdx
new file mode 100644
index 00000000..a6ed0203
--- /dev/null
+++ b/guides/workflows/feedback-reviews.mdx
@@ -0,0 +1,66 @@
+---
+title: "Feedback & Reviews"
+description: "Grow your business faster by asking users to leave a positive review"
+---
+
+## Intro
+
+Feedback and reviews are the lifeblood of any business. Setting up an automated workflow to do so however, is unnecessarily complicated by the need to implement notification logic like delayed send.
+
+[Explore the source code on GitHub](https://github.com/novuhq/examples/tree/main/novu-workflows/react/feedback-reviews)
+
+## Preview
+
+
+
+## Code Example
+
+```javascript
+import { workflow } from '@novu/framework';
+import { renderFeedbackEmail } from '../emails/feedback';
+import { zodControlSchema, zodDelayControlSchema, zodPayloadSchema } from './schemas';
+
+export const AirbnbReview = workflow(
+ "Airbnb Review",
+ async ({ step, payload }) => {
+ /**
+ * Delay Step
+ */
+ await step.delay(
+ 'delay-1-week',
+ async (controls) => {
+ return {
+ type: "regular",
+ unit: controls.unit, // 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months'
+ amount: controls.amount, // the number of units to delay workflow execution for
+ };
+ },
+ {
+ controlSchema: zodDelayControlSchema
+ }
+ );
+
+ /**
+ * Email Step
+ */
+ await step.email(
+ "send-email",
+ async (controls) => {
+ return {
+ subject: controls.emailSubject,
+ body: renderFeedbackEmail(controls, payload),
+ };
+ },
+ {
+ controlSchema: zodControlSchema
+ }
+ );
+ },
+ {
+ payloadSchema: zodPayloadSchema
+ },
+);
+```
\ No newline at end of file
diff --git a/guides/workflows/introduction.mdx b/guides/workflows/introduction.mdx
new file mode 100644
index 00000000..ae0af365
--- /dev/null
+++ b/guides/workflows/introduction.mdx
@@ -0,0 +1,34 @@
+---
+title: "Overview"
+description: "You shouldn't have to reinvent the wheel. Here we share how to implement several real-world use cases of notifications workflows."
+---
+
+## Workflow Examples
+
+This directory consists of drop-in working projects of different types of notification workflows you can use.
+
+Each directory is a batteries-included Novu Nextjs app that you can simply clone, install and run!
+
+
+
+
+ Send One-Time Passwords (OTP) without worrying about email reputation scores.
+
+
+ Let users "Reset Password" or "Forgot Username"
+
+
+ Suspicious activity? Inform your users of recent login attempts
+
+
+ Send invoices or receipts after a transaction is processed.
+
+
+ Let buyers know when their order has shipped, complete with tracking number.
+
+
+ Reviews are the lifeblood of any business. Remind and incentivize your buyers to leave a review
+
+
+
+
diff --git a/guides/workflows/invoice-receipt.mdx b/guides/workflows/invoice-receipt.mdx
new file mode 100644
index 00000000..d59e6d7f
--- /dev/null
+++ b/guides/workflows/invoice-receipt.mdx
@@ -0,0 +1,50 @@
+---
+title: "Invoice Receipt"
+description: "Send invoices or receipts immediately after a user purchases"
+---
+
+## Intro
+
+Invoices and receipts require custom fields such as the order number, billing details, and objects purchased which must be dynamically fetched from the database. The use of step controls and the payload schema simplifies the fetching of that unique data.
+
+[Explore the source code on GitHub](https://github.com/novuhq/examples/tree/main/novu-workflows/react/invoice-receipts)
+
+## Preview
+
+
+
+
+## Code Example
+
+```javascript
+import { workflow } from '@novu/framework';
+import { renderAppleReceiptEmail } from '../emails/apple-receipt';
+import { zodControlSchema, jsonSchema, zodPayloadSchema } from './schemas';
+
+/**
+ * Apple Receipt Workflow
+ */
+export const appleReceipt = workflow(
+ "Apple Receipt",
+ async ({ step, payload }) => {
+ await step.email(
+ "send-email",
+ async (controls) => {
+ return {
+ subject: controls.receiptSubject,
+ body: renderAppleReceiptEmail(controls, payload),
+ };
+ },
+ {
+ controlSchema: zodControlSchema
+ },
+ );
+ },
+ {
+ payloadSchema: zodPayloadSchema
+ }
+);
+```
\ No newline at end of file
diff --git a/guides/workflows/otp.mdx b/guides/workflows/otp.mdx
new file mode 100644
index 00000000..1058251c
--- /dev/null
+++ b/guides/workflows/otp.mdx
@@ -0,0 +1,81 @@
+---
+title: "OTP (One-Time Password)"
+description: "Send OTPs without setting up your own infrastructure"
+---
+
+## Intro
+
+Sending One-Time Passwords (OTP) is often unnecessarily complicated, requiring engineering teams to waste valuable development cycles setting up SMS infrastructure and getting email reputation satisfactory for sending six digit passcodes. This three channel workflow example shows how to send an email, push notification, or SMS OTP.
+
+[Explore the source code on GitHub](https://github.com/novuhq/examples/tree/main/novu-workflows/react/otp)
+
+## Preview
+
+Send an email
+
+
+Send a mobile push notification
+
+
+Send an SMS notification
+
+
+
+## Code Sample
+
+```javascript
+import { workflow } from '@novu/framework';
+import { renderOtpEmail } from '../emails/slack-otp';
+import { zodControlSchema, zodPayloadSchema, zodPushControlSchema, zodSmsControlSchema } from './schemas';
+
+export const SlackVerificationOTP = workflow(
+ "Slack Verify OTP",
+ async ({ step, payload }) => {
+ await step.email(
+ "send-email",
+ async (controls) => {
+ return {
+ subject: controls.emailSubject,
+ body: renderOtpEmail(controls, payload),
+ };
+ },
+ {
+ controlSchema: zodControlSchema
+ });
+
+ // -----------------------------------push flow-------------------------------------------------------------------------
+ await step.push('send-push', async (controls) => {
+ return {
+ subject: controls.pushNotificationSubject,
+ body: `Your verification code from Slack is ${payload.validationCode}`,
+ };
+ },
+ {
+ controlSchema: zodPushControlSchema
+ });
+
+ // -----------------------------------sms flow-------------------------------------------------------------------------
+ await step.sms('send-sms', async (controls) => {
+ return {
+ subject: controls.smsSubject,
+ body: `Your verification code from Slack is ${payload.validationCode}`,
+ };
+ },
+ {
+ controlSchema: zodSmsControlSchema
+ });
+ },
+ {
+ payloadSchema: zodPayloadSchema
+ },
+);
+```
diff --git a/guides/workflows/password-reset.mdx b/guides/workflows/password-reset.mdx
new file mode 100644
index 00000000..53edd773
--- /dev/null
+++ b/guides/workflows/password-reset.mdx
@@ -0,0 +1,48 @@
+---
+title: "Password Reset"
+description: "Help users reclaim access to their account via the 'Password Reset' or 'Forgot Username' functions"
+---
+
+## Intro
+
+To help users re-establish access to their account securely, a password reset email should be succint and have a unique password reset URL that expires after a given time. This example uses the payload schema to fetch the unique expiring password reset link.
+
+[Explore the source code on GitHub](https://github.com/novuhq/examples/tree/main/novu-workflows/react/password-reset)
+
+## Preview
+
+
+
+
+## Code Example
+
+```javascript
+import { workflow } from '@novu/framework';
+import { renderPasswordResetEmail } from '../emails/password-reset';
+import { zodControlSchema, zodPayloadSchema } from './schemas';
+
+export const DropboxPasswordResetEmail = workflow(
+ "Dropbox Password Reset",
+ async ({ step, payload }) => {
+ await step.email(
+ "send-email",
+ async (controls) => {
+ return {
+ subject: controls.emailSubject,
+ body: renderPasswordResetEmail(controls, payload),
+ };
+ },
+ {
+ controlSchema: zodControlSchema
+ }
+ );
+ },
+ {
+ payloadSchema: zodPayloadSchema
+ }
+);
+```
+
diff --git a/guides/workflows/recent-login.mdx b/guides/workflows/recent-login.mdx
new file mode 100644
index 00000000..fd245c08
--- /dev/null
+++ b/guides/workflows/recent-login.mdx
@@ -0,0 +1,66 @@
+---
+title: "Recent Login"
+description: "Notify users of recent login activity"
+---
+
+## Intro
+
+Sending recent logins is a great way to inform users of possible unusal activity and verify their usage. This workflow example leverages the payload schema to display the login IP, and notifies users through both email and a push notification.
+
+[Explore the source code on GitHub](https://github.com/novuhq/examples/tree/main/novu-workflows/react/recent-login)
+
+## Preview
+
+
+
+
+## Code Example
+
+```javascript
+import { workflow } from '@novu/framework';
+import { renderLoginEmail } from '../emails/yelp-recent-login';
+import { zodControlSchema, zodPayloadSchema, zodPushControlSchema } from './schemas';
+
+export const YelpRecentLogin = workflow(
+ "Yelp Recent Login",
+ async ({ step, payload }) => {
+ /**
+ * Email Flow
+ */
+ await step.email(
+ "send-email",
+ async (controls) => {
+ return {
+ subject: "Recent login to your Account",
+ body: renderLoginEmail(controls, payload),
+ };
+ },
+ {
+ controlSchema: zodControlSchema
+ },
+ );
+
+ /**
+ * Push Flow
+ */
+ await step.push(
+ "send-push",
+ async (controls) => {
+ return {
+ subject: controls.pushNotificationSubject,
+ body: `Hi ${payload.userFirstName}, we noticed a recent login to your Yelp account. If this was you, there's nothing else you need to do. If this wasn't you or please see our support page.`,
+ };
+ },
+ {
+ controlSchema: zodPushControlSchema
+ }
+ );
+ },
+ {
+ payloadSchema: zodPayloadSchema
+ },
+);
+```
diff --git a/guides/workflows/scaffold.mdx b/guides/workflows/scaffold.mdx
new file mode 100644
index 00000000..bc6da167
--- /dev/null
+++ b/guides/workflows/scaffold.mdx
@@ -0,0 +1,129 @@
+---
+title: ""
+description: ""
+---
+
+## Intro
+
+
+[Explore the source code on GitHub](https://github.com/novuhq/examples/tree/main/novu-workflows/react/otp)
+
+## Preview
+
+
+
+
+
+## Code Example
+
+```javascript
+import { Client, workflow } from "@novu/framework";
+import { renderOtpEmail } from "./emails/slack-otp";
+
+
+export const client = new Client({
+ /**
+ * Enable this flag only during local development
+ */
+ strictAuthentication: false,
+});
+
+export const SlackVerificationOTP = workflow(
+ "Slack Verify OTP",
+ async ({ step, payload }) => {
+ await step.email(
+ "send-email",
+ async (inputs) => {
+ return {
+ subject: inputs.emailSubject,
+ body: renderOtpEmail(inputs, payload),
+ };
+ },
+ {
+ inputSchema: {
+ type: "object",
+ properties: {
+ emailSubject: {
+ title: "Email Subject",
+ type: "string",
+ default: "Verify your Slack OTP!"
+ },
+ confirmAddressHeader: {
+ type: "string",
+ default: "Confirm your email address",
+ title: "Confirm Address Header"
+ },
+ majorBodyText: {
+ type: "string",
+ default: "Your confirmation code is below - enter it in your open browser window and we'll help you get signed in.",
+ title: "Major Body Text"
+ },
+ showMagicLink: {
+ type: "boolean",
+ default: false,
+ title: "Show Magic Link"
+ },
+ linkText: {
+ type: 'string',
+ default: 'Click this link if the OTP does not work for you!',
+ title: 'Magic link Text'
+ },
+ showOTP: {
+ type: "boolean",
+ default: true,
+ title: "Show OTP"
+ },
+ },
+ },
+ });
+
+ // -----------------------------------push flow-------------------------------------------------------------------------
+ await step.push('send-push', async () => {
+ return {
+ subject: 'You received a Slack OTP',
+ body: `Your verification code from Slack is ${payload.validationCode}`,
+ };
+ });
+
+ // -----------------------------------sms flow-------------------------------------------------------------------------
+ await step.sms('send-sms', async () => {
+ return {
+ subject: 'You received a Slack OTP',
+ body: `Your verification code from Slack is ${payload.validationCode}`,
+ };
+ });
+ },
+ {
+ payloadSchema: {
+ type: "object",
+ properties: {
+ validationCode: {
+ type: "string",
+ default: "123456",
+ title: "OTP",
+ },
+ magicLinkURL: {
+ type: "string",
+ default: "https://slack.com/magic/link",
+ title: "Magic Link URL"
+ }
+ },
+ },
+ },
+);
+
+```
+
+## Installation
+
+```
+npm run dev
+```
+
+
+ If you're ready to start integrating in your .NET app, jump straight to
+ our [.NET quickstart.](/quickstarts/.NET)
+
diff --git a/guides/workflows/shipping-confirmation.mdx b/guides/workflows/shipping-confirmation.mdx
new file mode 100644
index 00000000..be8ab583
--- /dev/null
+++ b/guides/workflows/shipping-confirmation.mdx
@@ -0,0 +1,51 @@
+---
+title: "Shipping Confirmation"
+description: "Let buyers know their order is on the way!"
+---
+
+## Intro
+
+What delights the dopamine receptors more than an email confirming their order's delivery date? Reward your buyers by letting them know their order is confirmed and on the way, complete with tracking info fetched by leveraging the payload schema.
+
+[Explore the source code on GitHub](https://github.com/novuhq/examples/tree/main/novu-workflows/react/shipping-order-confirmation)
+
+## Preview
+
+
+
+
+## Code Example
+
+```javascript
+import { workflow } from '@novu/framework';
+import { renderShippingOrderEmail } from '../emails/shipping-order-confirmation';
+import { zodControlSchema, zodPayloadSchema, jsonControlSchema, jsonPayloadSchema } from './schemas';
+
+export const AmazonShippingOrderConfirmation = workflow(
+ "Amazon Shipping Order",
+ async ({ step, payload }) => {
+ await step.email(
+ "send-email",
+ async (controls) => {
+ return {
+ subject: controls.emailSubject,
+ body: renderShippingOrderEmail(controls, payload),
+ };
+ },
+ {
+ controlSchema: zodControlSchema
+ }
+ );
+ },
+ {
+ payloadSchema: zodPayloadSchema
+ },
+);
+```
+
+
+ PROTIP: Delight users by sending their tracking info - leverage the payload schema to do this.
+
diff --git a/help/channels/chat.mdx b/help/channels/chat.mdx
index 5de7eac6..2e16defb 100644
--- a/help/channels/chat.mdx
+++ b/help/channels/chat.mdx
@@ -7,6 +7,7 @@ icon: "comment"
import ContactSupportSnippet from "/snippets/contact-support.mdx";
### Can I send a message to a specific user on Slack?
+
While installing the Slack app, you will be asked the User or Channel to which the message needs to be sent. On selecting a user, a webhookUrl for that user will be generated and Novu will use that webhookUrl to send a message to that specific user.
-
\ No newline at end of file
+
diff --git a/help/channels/email.mdx b/help/channels/email.mdx
index 4ec4f89c..d032ce48 100644
--- a/help/channels/email.mdx
+++ b/help/channels/email.mdx
@@ -7,31 +7,39 @@ icon: "envelope"
import ContactSupportSnippet from "/snippets/contact-support.mdx";
### How to override default values of Email?
+
All values (from, to, subject, body, etc.) can be overridden by using the `overrides` option while triggering the workflow. Please see our [email overrides documentation](/channels-and-providers/email/overview#sending-email-overrides) for more details.
### Sending HTML as the value of a variable
+
HTML content as a value of step variable can be sent by replacing the double curly braces `{{}}` variable with triple curly braces `{{{}}}` variable. For example, `{{{htmlContent}}}`.
### I have multiple Email Providers or integrations active, how do I associate them to a Workflow?
+
There can be more than one active email integrations of same or different providers. However only one email integration can be primary at one time per environment. To use a different email integration than your primary integration, the integrationIdentifier field of email overrides can be used. Read about using [different email integration](/channels-and-providers/email/overview#using-different-email-integration) for more details.
### Why am I getting the error “message content could not be generated”?
+
This error occurs when the HTML content is not properly formatted. Make sure the HTML content is properly formatted and does not contain any syntax errors. Make sure Step Variables are properly formatted and are not missing opening or closing curly braces.
### Can email or phone be used as step variables?
+
Novu recommends not to use subscriber attributes as step variables. Instead, use the subscriber attributes directly in the step. For example, use `{{subscriber.email}}` instead of `{{email}}` as your step variable. Novu will select the email from subscriber attributes and inject the value in the content.
### How to use Provider templates in place of email content?
+
Currently, we support external Provider template support for [sendgrid](/channels-and-providers/email/sendgrid#using-sendgrid-template) and [mailersend](/channels-and-providers/email/mailersend#using-mailersend-template) only.
### Can I retrieve only Email content?
+
Novu does not have a separate API to retrieve email content. However, email content can be retrieved from the email step of the workflow. The email step contains the email content in the `content` field of [get worklfow api](/api-reference/workflows/get-workflow) response.
### How to send inline images in email?
+
Inline images can be sent using `` tag in the email content. PNG, JPEG, GIF are supported. SVGs are not supported as inline images by most of email clients like gmail, outlook.
### How to add unsubscribe link in emails?
Add `{{unsubscribe}}` variable in email step content editor and send url value of this variable in payload. Create a simple html page to [fetch preferences](https://docs.novu.co/api-reference/subscribers/get-subscriber-preferences) and then use [update preference api](https://docs.novu.co/api-reference/subscribers/update-subscriber-preference) to update.
-
\ No newline at end of file
+
diff --git a/help/channels/in-app.mdx b/help/channels/in-app.mdx
index e779ade4..f286118f 100644
--- a/help/channels/in-app.mdx
+++ b/help/channels/in-app.mdx
@@ -7,19 +7,23 @@ icon: "bell"
import ContactSupportSnippet from "/snippets/contact-support.mdx";
### Creating two In-App Notification Centers in one account
+
To configure your In-App notifications, you must use the In-App integration from our integration store.
-To display in-app notifications to users, any SDKs in our [client library](/notification-center/introduction) can be used. Every library requires `applicationIdentifier` and `subscriberId` to fetch notifications. Currently, only one `applicationIdentifier` is supported per environment per organization.
+To display in-app notifications to users, any SDKs in our [client library](/notification-center/introduction) can be used. Every library requires `applicationIdentifier` and `subscriberId` to fetch notifications. Currently, only one `applicationIdentifier` is supported per environment per organization.
Feel free to reach out to us at support@novu.co if you have speicific requirements of multiple `applicationIdentifier` per organization.
### Issues with a redirect URL
+
To redirect to specified redirect url on clicking the in-app notification, notification click event should be handled in client side code. Here is an example in [React](/notification-center/client/react/get-started#onnotificationclick).
### Changing the default colors of the Notification Center
-Styling of your In-App Notification Center can be customized using the [styles](/notification-center/client/react/customization#customization-using-styles-prop) prop. If you want to customize only a single component, you can use [available](/notification-center/client/react/customization#popovernotificationcenter-customization) props.
+
+Styling of your Inbox can be customized using the [styles](/notification-center/client/react/customization#customization-using-styles-prop) prop. If you want to customize only a single component, you can use [available](/notification-center/client/react/customization#popovernotificationcenter-customization) props.
### Additional Security for In-App Notifications
+
To add an extra layer of security, we recommend using our HMAC encryption feature to eliminate subscriber impersonation Checkout [HMAC](/notification-center/client/react/get-started#hmac-encryption) section for more details.
-
\ No newline at end of file
+
diff --git a/help/channels/push.mdx b/help/channels/push.mdx
index d128b709..a024a4d3 100644
--- a/help/channels/push.mdx
+++ b/help/channels/push.mdx
@@ -7,17 +7,22 @@ icon: "mobile"
import ContactSupportSnippet from "/snippets/contact-support.mdx";
### Can I send a Desktop Push notification?
+
Yes, Desktop Push Notifications can be sent by using a Web Push Notification. It is supported with almost all [push channel](/channels-and-providers/push/overview) providers.
### Why am I getting the error “unexpected provider” with FCM?
+
The possible reasons for this error are:
+
- Invalid FCM credentials.
- Invalid or stale FCM token.
### Why am I getting the error “Sending message failed due to Requested entity was not found” with FCM?
+
- This error occurs when the FCM token is invalid or stale. You can fix this by updating the FCM device token.
### Can I store device tokens for particular FCM integration if I have multiple FCM providers active?
+
- Device tokens for particular FCM integration can be stored using the `integrationIdentifier` field of [update subscriber credentials api](/api-reference/subscribers/update-subscriber-credentials). `integrationIdentifier` is the unique identifier of the integration which is similar to `providerIdentifier`. It can be copied from the integration form.
-
\ No newline at end of file
+
diff --git a/help/channels/sms.mdx b/help/channels/sms.mdx
index e83565e3..e29b0146 100644
--- a/help/channels/sms.mdx
+++ b/help/channels/sms.mdx
@@ -7,12 +7,13 @@ icon: "message-sms"
import ContactSupportSnippet from "/snippets/contact-support.mdx";
### Why am I getting the error “ subscriber does not have a configured channel”?
+
This error occurs when a Subscriber is missing `phone` attribute. To fix this error, you need to update the subscriber and set the `phone` attribute with a valid phone number.
### How to change the default sender name for SMS?
-First, ensure a custom sendername (sender id or from) is allowed with your Provider. Some countries expect to verify the sender name before using it.
-You can change the default sender name for SMS by using [overrides](/channels-and-providers/sms/overview#sending-sms-overrides) field while triggering the workflow.
+First, ensure a custom sendername (sender id or from) is allowed with your Provider. Some countries expect to verify the sender name before using it.
+You can change the default sender name for SMS by using [overrides](/channels-and-providers/sms/overview#sending-sms-overrides) field while triggering the workflow.
-
\ No newline at end of file
+
diff --git a/help/content-management.mdx b/help/content-management.mdx
index f4b34e78..7831c123 100644
--- a/help/content-management.mdx
+++ b/help/content-management.mdx
@@ -7,18 +7,23 @@ icon: "file-pen"
import ContactSupportSnippet from "/snippets/contact-support.mdx";
### What is a Layout and how can I use them?
+
Layout is similar to a style container for email templates. Layouts can be used for your organization’s branding and style. It can be used to define the structure of the email template such as the header, footer, and other common elements. It must have a `{{{body}}}` variable which will be replaced by the actual email template content.
### Can Layouts be used across all channels?
+
Layouts are specific to Emails.
### Can MJML templates be used in content editors?
+
Only HTML templates can be used in content editors. We support [handlebar helpers](/content-creation-design/handlebars-helpers) for common use cases like iteration, conditions etc. If you need any specific Handlebar Helpers, please reach out to us at support@novu.co.
### Can the content of one Step be used in another?
+
Currently each Step has content that is unique to it and can not be reused. If this is important to you, please send us a note at support@novu.co.
### Which Translation Language will be used if the Subscriber’s locale field does not match with translation language files?
-If the Subscriber's locale field does not match with Translation locale files, or it is not available, then the defaul language of the translation group will be used. If a default is not set, the automatic fallback is English.
-
\ No newline at end of file
+If the Subscriber's locale field does not match with Translation locale files, or it is not available, then the defaul language of the translation group will be used. If a default is not set, the automatic fallback is English.
+
+
diff --git a/help/observability.mdx b/help/observability.mdx
index 5bdf6b84..527cde9a 100644
--- a/help/observability.mdx
+++ b/help/observability.mdx
@@ -7,13 +7,15 @@ description: "Analyzing your Triggered Events and Notification execution logs"
import ContactSupportSnippet from "/snippets/contact-support.mdx";
### My Subscribers have preferences set, but the Activity Feed is showing Triggers as being sent.
+
The Activity Feed is a place each event (Workflow Trigger) is listed. If a Subscriber has a preference to not receive notifications through a certain channel, Novu’s system will adhere to that. However, this is still a valid Trigger as the fanout occurs before preferences are accommodated.
### What does "step filtered by subscriber preferences" mean in the logs?
+
It means that the Subscriber has set preferences configured and the step was filtered based on that preference. If the subscriber has disabled a step Channel then, the step will be filtered and notification will not be sent to the subscriber.
### How to export Activity Feed data?
-Currently, we don't have any option to export activity feed data. But you can use our [API](/api-reference/notification/get-notifications) to fetch the data. If there is a specific system you’re looking to integrate with, please send us a note at support@novu.co.
+Currently, we don't have any option to export activity feed data. But you can use our [API](/api-reference/notification/get-notifications) to fetch the data. If there is a specific system you’re looking to integrate with, please send us a note at support@novu.co.
-
\ No newline at end of file
+
diff --git a/help/orchestration.mdx b/help/orchestration.mdx
index 9766af68..db562b72 100644
--- a/help/orchestration.mdx
+++ b/help/orchestration.mdx
@@ -7,21 +7,25 @@ import ContactSupportSnippet from "/snippets/contact-support.mdx";
## Digest
### New event triggers are merging an active Digest with an old duration..
-When a Digest is created with a set duration and an event is triggered, the Digest stays active ( and will batch the events) until the configured duration is over.
-If you change the duration before the initial time period has completed , the previous digest will still be active and the new duration is merged with the old duration Digest until the previous duration is complete.
+When a Digest is created with a set duration and an event is triggered, the Digest stays active ( and will batch the events) until the configured duration is over.
+
+If you change the duration before the initial time period has completed , the previous digest will still be active and the new duration is merged with the old duration Digest until the previous duration is complete.
To remove the previous Digest, use [event cancel api](/api-reference/events/cancel-triggered-event) to cancel all event triggers that are still pending and are merged in active Digests.
### Can I dynamically make the Digest inactive??
+
Yes, Digest supports conditions and can be applied to your Digest step. If the Triggered Event passes the set conditions, then it will be active or inactive based on the condition.
### Can a Subscriber control the Digest duration and time?
-Not currently. The Digest duration can be changed at the Workflow level only and is applied to all subscribers that Workflow is triggered to. If you have an identified use case for this, please let us know at support@novu.co.
+
+Not currently. The Digest duration can be changed at the Workflow level only and is applied to all subscribers that Workflow is triggered to. If you have an identified use case for this, please let us know at support@novu.co.
## Delay
### What happens if the delay scheduled date and time is in the past?
+
If the delay scheduled date and time is in the past, the delay step will fail. Based on the step configuration, workflow will either continue to the next step or workflow will be failed
-
\ No newline at end of file
+
diff --git a/help/others.mdx b/help/others.mdx
index f209bbea..fb05f60f 100644
--- a/help/others.mdx
+++ b/help/others.mdx
@@ -3,7 +3,9 @@ icon: "crystal-ball"
---
### Workkflows changes are not showing on the changes
+
If some changes are pending to promote for the same workflow, then Novu merges subsequent changes into the existing change item.
### Getting CORS error with the API
-Novu APIs are developed to be used on the server side. If you are using the API from the browser, you will get a CORS error. You can use the API from the server side or checkout our [client-side libraries](/notification-center/introduction) to fetch in-app notifications.
\ No newline at end of file
+
+Novu APIs are developed to be used on the server side. If you are using the API from the browser, you will get a CORS error. You can use the API from the server side or checkout our [client-side libraries](/notification-center/introduction) to fetch in-app notifications.
diff --git a/help/overview.mdx b/help/overview.mdx
index 6b07179f..819d5d52 100644
--- a/help/overview.mdx
+++ b/help/overview.mdx
@@ -8,7 +8,12 @@ icon: "bolt"
At our Help Center, we're dedicated to provide comprehensive support to ensure your experience with our products and services is seamless and enjoyable. Whether you're a new user looking for guidance or a seasoned customer seeking assistance, we're here to help. Help Center is organized as per our product architecture and is divided into the following sections:
-
+
Manage your account and access your data.
- Explore orchestration digest, delay, conditions and more.
+ Explore orchestration digest, delay, conditions and more.
- Content management, layouts, templates, and more.
+ Content management, layouts, templates, and more.
- Observability, metrics, analytics, and more.
+ Observability, metrics, analytics, and more.
-
- Others help topics.
+
+ Others help topics.
Read frequently asked questions
-
-
\ No newline at end of file
+
+
+
diff --git a/help/user-management.mdx b/help/user-management.mdx
index a1544392..f767c4fa 100644
--- a/help/user-management.mdx
+++ b/help/user-management.mdx
@@ -7,31 +7,39 @@ icon: "users"
## Subscribers
### What is a Subscriber?
+
A subscriber is an entity to which notifications are sent. It is a Novu term similar to a user in your system. As in your system, a user is identified by a unique id, similarly in Novu, a subscriber is identified by a unique id called `subscriberId`. We recommend that the existing value you use in your system as a `userId` to be used as `subscriberId` in Novu. Read more about subscribers on [subscribers documentation page](/subscribers/subscribers).
### Is it necessary to use subscriberId as same as userId?
+
No, it is not necessary to use subscriberId as same as userId. You can use any unique id as subscriberId. We recommend using userId as subscriberId to avoid any confusion. Some of our customers use a pattern like `auth0|userId` as a value for `subscriberId`.
### Can notification be sent without adding a Subscriber?
+
No, a notification cannot be sent without adding a subscriber. A subscriber is an entity to which notifications are sent. You need to add a subscriber to Novu before triggering the workflow or inline of trigger. Read more about subscribers on [subscribers documentation page](/subscribers/subscribers).
### What is the right approach to add Subscribers?
-Subscribers can be added either [ahead of trigger](/subscribers/subscribers#1-ahead-of-trigger) or [inline of trigger](/subscribers/subscribers#2-inline-of-trigger). One way to add a subscriber using inline of trigger is to create a new subscriber in Novu as soon as they sign up or register in your system.
+
+Subscribers can be added either [ahead of trigger](/subscribers/subscribers#1-ahead-of-trigger) or [inline of trigger](/subscribers/subscribers#2-inline-of-trigger). One way to add a subscriber using inline of trigger is to create a new subscriber in Novu as soon as they sign up or register in your system.
You can add your existing users as subscribers in Novu using [bulk create subscriber creation method](/subscribers/subscribers#bulk-subscriber-creation).
### Can Subscriber credentials be added while creating a new Subscriber?
-Subscriber credentials for Push and Chat channel providers cannot be added while creating a new subscriber. Subscriber credentials for Push and Chat channel providers can be added using the [update subscriber credentials api](/api-reference/subscribers/update-subscriber-credentials) or corresponding sdk methods.
+
+Subscriber credentials for Push and Chat channel providers cannot be added while creating a new subscriber. Subscriber credentials for Push and Chat channel providers can be added using the [update subscriber credentials api](/api-reference/subscribers/update-subscriber-credentials) or corresponding sdk methods.
SMS and Email channels are a bit different because all providers can work with the same value, so `email` and `phone` [attributes](/subscribers/subscribers#subscriber-attributes) can be added while creating a new Subscriber.
### Can Subscriber preferences be updated while adding a new Subscriber?
+
Subscriber preference cannot be updated while adding a new subscriber. Novu sets all channels as true by default for new subscribers. You can modify preferences at any time. Read more about [subscriber preferences](/subscribers/preferences).
### Can two subscribers with different `subscriberId`s have the same email address?
+
Yes, it is possible for two subscribers to have the same email address in our system. This is because the `subscriberId` is the unique identifier that distinguishes one subscriber from another. Even if two subscribers share the same email address, they will have different `subscriberId`s, which allows our system to identify and manage them separately.
## Topics
### Can a Subscriber be added to multiple topics at once?
-Currently, Novu supports adding a subscriber to only one topic at a time. You can add a subscriber to multiple topics by calling the [add subscriber to topic api](/api-reference/topics/subscribers-addition) multiple times with a particular topic key
\ No newline at end of file
+
+Currently, Novu supports adding a subscriber to only one topic at a time. You can add a subscriber to multiple topics by calling the [add subscriber to topic api](/api-reference/topics/subscribers-addition) multiple times with a particular topic key
diff --git a/images/how-to/feedback-review.png b/images/how-to/feedback-review.png
new file mode 100644
index 00000000..a438114a
Binary files /dev/null and b/images/how-to/feedback-review.png differ
diff --git a/images/how-to/invoice-receipt.png b/images/how-to/invoice-receipt.png
new file mode 100644
index 00000000..dfc55725
Binary files /dev/null and b/images/how-to/invoice-receipt.png differ
diff --git a/images/how-to/otp-email.png b/images/how-to/otp-email.png
new file mode 100644
index 00000000..40160da7
Binary files /dev/null and b/images/how-to/otp-email.png differ
diff --git a/images/how-to/otp-push.png b/images/how-to/otp-push.png
new file mode 100644
index 00000000..10432873
Binary files /dev/null and b/images/how-to/otp-push.png differ
diff --git a/images/how-to/otp-sms.png b/images/how-to/otp-sms.png
new file mode 100644
index 00000000..f29131b3
Binary files /dev/null and b/images/how-to/otp-sms.png differ
diff --git a/images/how-to/otp.png b/images/how-to/otp.png
new file mode 100644
index 00000000..fb33c715
Binary files /dev/null and b/images/how-to/otp.png differ
diff --git a/images/how-to/password-reset.png b/images/how-to/password-reset.png
new file mode 100644
index 00000000..e67ee34d
Binary files /dev/null and b/images/how-to/password-reset.png differ
diff --git a/images/how-to/recent-login-email.png b/images/how-to/recent-login-email.png
new file mode 100644
index 00000000..3a60f6bf
Binary files /dev/null and b/images/how-to/recent-login-email.png differ
diff --git a/images/how-to/recent-login-push.png b/images/how-to/recent-login-push.png
new file mode 100644
index 00000000..5d914d64
Binary files /dev/null and b/images/how-to/recent-login-push.png differ
diff --git a/images/how-to/recent-login.png b/images/how-to/recent-login.png
new file mode 100644
index 00000000..9f722a79
Binary files /dev/null and b/images/how-to/recent-login.png differ
diff --git a/images/how-to/shipping-confirmation.png b/images/how-to/shipping-confirmation.png
new file mode 100644
index 00000000..68e4b1ab
Binary files /dev/null and b/images/how-to/shipping-confirmation.png differ
diff --git a/images/how-to/shipping-order-confirmation.png b/images/how-to/shipping-order-confirmation.png
new file mode 100644
index 00000000..fb6a39ed
Binary files /dev/null and b/images/how-to/shipping-order-confirmation.png differ
diff --git a/notification-center/backend/methods.mdx b/inbox/backend/methods.mdx
similarity index 100%
rename from notification-center/backend/methods.mdx
rename to inbox/backend/methods.mdx
diff --git a/notification-center/client/angular.mdx b/inbox/client/angular.mdx
similarity index 87%
rename from notification-center/client/angular.mdx
rename to inbox/client/angular.mdx
index ae763798..dcbcc9da 100644
--- a/notification-center/client/angular.mdx
+++ b/inbox/client/angular.mdx
@@ -11,15 +11,9 @@ The `@novu/notification-center-angular` package provides an Angular component
Novu supports Angular version 15 and higher.
-```bash pnpm
-pnpm i @novu/notification-center-angular
-```
-```bash npm
-npm i @novu/notification-center-angular
-```
-```bash yarn
-yarn add @novu/notification-center-angular
-```
+ ```bash pnpm pnpm i @novu/notification-center-angular ``` ```bash npm npm i
+ @novu/notification-center-angular ``` ```bash yarn yarn add
+ @novu/notification-center-angular ```
## Example usage
@@ -71,7 +65,8 @@ Component HTML template:
The `notification-center-component` accepts the same set of props as the [web component](/notification-center/client/web-component).
- You may need to add `"allowSyntheticDefaultImports": true` in tsconfig.json for the web component's React imports to work correctly.
+ You may need to add `"allowSyntheticDefaultImports": true` in tsconfig.json
+ for the web component's React imports to work correctly.
## Example
diff --git a/notification-center/client/iframe.mdx b/inbox/client/iframe.mdx
similarity index 97%
rename from notification-center/client/iframe.mdx
rename to inbox/client/iframe.mdx
index aa172f78..17770824 100644
--- a/notification-center/client/iframe.mdx
+++ b/inbox/client/iframe.mdx
@@ -198,7 +198,7 @@ Then pass the created HMAC to your client side application forward it to the emb
- We use font awesome bell icon. Make sure you have added the font awesome CSS cdn link in the head tag.
+We use font awesome bell icon. Make sure you have added the font awesome CSS cdn link in the head tag.
```html
```
-
+
-
\ No newline at end of file
+
diff --git a/notification-center/client/vue.mdx b/inbox/client/vue.mdx
similarity index 73%
rename from notification-center/client/vue.mdx
rename to inbox/client/vue.mdx
index 317a5810..14bb6965 100644
--- a/notification-center/client/vue.mdx
+++ b/inbox/client/vue.mdx
@@ -92,19 +92,16 @@ You can pass the custom bell button component as the default slot to the `Notif
```
## Example
-
+
- [Vue Notification Center Example](https://github.com/novuhq/examples/tree/main/vue-notification-center-example)
- [CodeSandBox Link 🔗](https://codesandbox.io/p/sandbox/novu-vue-in-app-88p8vx)
-
## Props
The `NotificationCenterComponent` accepts the same set of props as the [Web Component](./web-component#properties).
It also accepts an extra prop
-
-| Prop | Type | Description |
-| ----------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| triggers | string[] | This is an Array of events that controls the underlying popper component's trigger. [Read more here](https://floating-vue.starpad.dev/api/#triggers)
-
+| Prop | Type | Description |
+| -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
+| triggers | string[] | This is an Array of events that controls the underlying popper component's trigger. [Read more here](https://floating-vue.starpad.dev/api/#triggers) |
diff --git a/notification-center/client/web-component.mdx b/inbox/client/web-component.mdx
similarity index 99%
rename from notification-center/client/web-component.mdx
rename to inbox/client/web-component.mdx
index 7d648f69..fe7a364e 100644
--- a/notification-center/client/web-component.mdx
+++ b/inbox/client/web-component.mdx
@@ -90,7 +90,7 @@ If you are using TypeScript, then you might want to check the `NotificationCent
| socketUrl | string | Custom WebSocket Service location in case of self-hosted version of Novu. |
| subscriberId | string | The subscriberId is a custom identifier used when identifying your users within the Novu platform. |
| applicationIdentifier | string | Is a public identifier used to identify your application, can be found in the Novu Admin panel. |
-| subscriberHash | string | The hashed subscriber id. [Read more about hmac encryption](/notification-center/client/react/get-started#hmac-encryption). |
+| subscriberHash | string | The hashed subscriber id. [Read more about hmac encryption](/notification-center/client/react/get-started#hmac-encryption). |
| stores | object[] | The array of the store items that are bound with the feed, it's used together with tabs property if you would like to have separate feeds in the notification center. [Read more here](/notification-center/client/react/multiple-tabs) |
| |
| tabs | object[] | The array of items that do describe the tabs/feeds, they are bound with the stores property. [Read more here](/notification-center/client/react/multiple-tabs). |
@@ -101,7 +101,7 @@ If you are using TypeScript, then you might want to check the `NotificationCent
| theme | [INovuTheme](/notification-center/client/react/api-reference#the-theme-interface) | The object defining the the light/dark styles of the Notification Center component. We discourage you to use this prop to do the styling, instead it's recommended to use the styles property. |
| styles | [NotificationCenterStyles](/notification-center/client/react/api-reference#styles-interface) | The object allows you to define the custom CSS code. |
| colorScheme | string | The prop defines which color version of the styles the component should set. The options are light and dark. |
-| i18n | object | The object allowing to [customize the UI language](/notification-center/client/react/customization#customize-the-ui-language). |
+| i18n | object | The object allowing to [customize the UI language](/notification-center/client/react/customization#customize-the-ui-language). |
| onLoad | function | The callback function that is called when the session is successfully initiated. It receives the first argument object with the organization property. There is a sibling property sessionLoaded that might be used in environments that do not allow to use properties with the prefix on, like in Angular. |
| onNotificationClick | function | The callback function that is called when the user has clicked on the notification. The first argument it receives is the notification object. There is a sibling property notificationClicked. |
| onUnseenCountChanged | function | The callback function that is called when the unseen notifications count changes. The first argument it receives is the number of unseen notifications count. There is a sibling property unseenCountChanged. |
diff --git a/notification-center/client/headless/api-reference.mdx b/inbox/headless/api-reference.mdx
similarity index 98%
rename from notification-center/client/headless/api-reference.mdx
rename to inbox/headless/api-reference.mdx
index 9ad99f73..c4b63d9b 100644
--- a/notification-center/client/headless/api-reference.mdx
+++ b/inbox/headless/api-reference.mdx
@@ -195,15 +195,15 @@ headlessService.fetchNotifications({
);
},
page: pageNumber,
- query: {
- feedIdentifier: "feedId",
- read: false,
- seen: true,
+ query: {
+ feedIdentifier: "feedId",
+ read: false,
+ seen: true,
// payload sent while triggering the workflow
payload: {
- message : "Notification message",
+ message: "Notification message",
type: "product",
- }
+ },
},
storeId: "storeId",
});
@@ -399,7 +399,6 @@ interface IMarkNotificationsAs {
}
```
-
## removeNotification
Removes a single notification using the message id.
@@ -442,9 +441,7 @@ Removes multiple notifications using array of message ids (limit of 100).
```typescript
headlessService.removeNotifications({
- listener: (
- result: UpdateResult
- ) => {
+ listener: (result: UpdateResult) => {
console.log(result);
},
onSuccess: (message: IMessage) => {
@@ -453,7 +450,7 @@ headlessService.removeNotifications({
onError: (error: unknown) => {
console.error(error);
},
- messageIds: ["message_id_1", "message_id_2" ],
+ messageIds: ["message_id_1", "message_id_2"],
});
```
diff --git a/notification-center/client/headless/get-started.mdx b/inbox/headless/get-started.mdx
similarity index 88%
rename from notification-center/client/headless/get-started.mdx
rename to inbox/headless/get-started.mdx
index a7d8010b..15125461 100644
--- a/notification-center/client/headless/get-started.mdx
+++ b/inbox/headless/get-started.mdx
@@ -85,7 +85,10 @@ headlessService.fetchNotifications({
});
```
-fetchNotifications and other methods of the headless service should be used after initializing the session using headlessService.initializeSession
+
+ fetchNotifications and other methods of the headless service should be used
+ after initializing the session using headlessService.initializeSession
+
## HMAC Encryption
@@ -126,7 +129,8 @@ headlessService.listenUnreadCountChange({
```
-If you're ready to start using the Headless Notification Center, check out our [guide!](/guides/headless-notification-center-guide)
+ If you're ready to start using the Headless Notification Center, check out our
+ [guide!](/guides/headless-notification-center-guide)
[Explore Implementation of the Headless Library in an App](https://github.com/novuhq/novu-headless-demo-app)
@@ -139,11 +143,12 @@ If you're ready to start using the Headless Notification Center, check out our [
We have `headless.initializeSession` method to generate token and initialize the session. If user log out and new user login, then calling again this method with second user subscriberId will generate new token and new session.
+
- Currently, headless can not be used with react native and flutter. Checkout the progress on mobile platform support on github issue [#4499](https://github.com/novuhq/novu/issues/4499).
-
+Currently, headless can not be used with react native and flutter. Checkout the progress on mobile platform support on github issue [#4499](https://github.com/novuhq/novu/issues/4499).
+
diff --git a/notification-center/introduction.mdx b/inbox/introduction.mdx
similarity index 69%
rename from notification-center/introduction.mdx
rename to inbox/introduction.mdx
index a4ce4565..8c41a944 100644
--- a/notification-center/introduction.mdx
+++ b/inbox/introduction.mdx
@@ -1,24 +1,29 @@
---
-title: "Introduction to Notification Center"
-description: "Learn more about Novu's Notification Center."
-icon: "house"
+title: "Introduction"
+description: "Learn more about Novu's Inbox Component."
---
-The notification center is a component, also sometimes referred to as a widget that furnishes your web application with a beautiful and smooth In-App notification experience for users.
+The Inbox component, also sometimes referred to as a widget that furnishes your web application with a beautiful and smooth Inbox notification experience for users.
-In-App notifications are different from push notifications in the sense that In-App notifications are consumed by the user in your app itself, whether push notifications are shown on the device level. Read more about [push channel and supported providers.](/channels-and-providers/push/overview)
+In-App notifications are different from push notifications in the sense that Inbox notifications are consumed by the user in your app itself, whether push notifications are shown on the device level. Read more about [push channel and supported providers.](/channels-and-providers/push/overview)
Novu provides a pre-built, ready-to-use, and customizable UI component. It also allows you to bring your own UI via a headless component which can be used to add In-App notifications to any platform.
-
+
## Example
[![Edit kind-nova-xv6s9g](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/kind-nova-xv6s9g?fontsize=14&hidenavigation=1&theme=dark)
-## Why use the Novu notification center?
+## Why use the Novu Inbox?
-- Users can manage subscriber preferences from the notification center itself.
+- Users can manage subscriber preferences from the Invox component.
- You want to notify about any product activity related to the user.
- Prebuilt UI component so no need to build UI from scratch.
- Highly customizable as per your product design system.
diff --git a/notification-center/client/react/api-reference.mdx b/inbox/react/api-reference.mdx
similarity index 90%
rename from notification-center/client/react/api-reference.mdx
rename to inbox/react/api-reference.mdx
index d066ccf9..0bd532ed 100644
--- a/notification-center/client/react/api-reference.mdx
+++ b/inbox/react/api-reference.mdx
@@ -22,10 +22,10 @@ It's responsible for establishing the notification center session, managing the
| socketUrl | string (optional) | The custom socket URL, your own deployed instance of the WS app. The default is https://ws.novu.co/. |
| applicationIdentifier | string | The app id is taken from the Novu Settings -> API Keys tab. |
| subscriberId | string | The unique user id from your system. |
-| subscriberHash | string (optional) | The HMAC encrypted subscriberId. Read about [hmac encryption](/notification-center/client/react/get-started#hmac-encryption) |
+| subscriberHash | string (optional) | The HMAC encrypted subscriberId. Read about [hmac encryption](/notification-center/client/react/get-started#hmac-encryption) |
| stores | [IStore](#store-interface) (optional) | The connection object between feed and notification center tab. |
| i18n | [ITranslationEntry \| ITranslationContent](#i18nlanguage-interface) (optional) | The prop allows to configure the UI language. |
-| styles | [NotificationCenterStyles](#styles-interface) (optional) | The prop allowing to style the notification center. It's based on the CSSInterpolation object from the [@emotion/css](https://emotion.sh/docs/@emotion/css#object-styles) package. |
+| styles | [NotificationCenterStyles](#styles-interface) (optional) | The prop allowing to style the notification center. It's based on the CSSInterpolation object from the [@emotion/css](https://emotion.sh/docs/@emotion/css#object-styles) package. |
| initialFetchingStrategy | [IFetchingStrategy](#fetching-strategy-interface) (optional) | The fetching strategy. By default notifications feed and user preferences are not fetched until the notification center is opened. You might need to tweak this configuration when building a custom UI and if you need to fetch notifications right away. Also it's possible to change it when some action happens using the useNovuContext hook and setFetchingStrategy prop. |
| children | object | The ReactNode object type, the "consumer" of the NovuProvider context. |
| onLoad | [function](#props-interface) (optional) | The function that is called with an organization object after the notification center session is initialized. |
@@ -60,7 +60,7 @@ interface IStoreQuery {
feedIdentifier?: string | string[];
seen?: boolean;
read?: boolean;
- limit?: number;
+ limit?: number;
payload?: Record;
}
```
@@ -173,6 +173,7 @@ type ObjectWithRoot = T & {
root: CSSFunctionOrObject;
};
```
+
To use the Styles Interface, you need to identify the property you need to modify to achieve your desired look and pass it as an object in the `styles` prop.
@@ -200,6 +201,7 @@ Now, that we know which property needs to change, all we need to do is pass an o
{({ unseenCount }) => }
+
```
This gives us the desired result:
@@ -376,12 +378,13 @@ interface ISvgStopColor {
stopColorOffset?: string;
}
```
+
## Hooks
### useNotifications
This hook that allows you to get the notifications feed data and unseen notifications count. The notifications are fetched only when the `fetchingStrategy.fetchNotifications` is set to true interface, check the `initialFetchingStrategy` prop on the [NovuProvider](#novuprovider) component.
-
+
```typescript
const result = useNotifications();
```
@@ -413,31 +416,31 @@ interface INotificationsContext {
removeAllMessages: (feedId?: string) => void;
}
```
-Description of the `useNotifications` hook return interface properties
-| Prop | Type | Description |
-| --- | --- | --- |
-| storeId | string | active `storeId` |
-| stores | [IStore[]](#store-interface) | array of [IStore](#store-interface) passed to the [NovuProvider](#novuprovider). |
-| unseenCount | number | unseen notifications (messages) count. |
-| notifications | [IMessage[]](#the-notification-imessage-model) | The feed notifications array. |
-| hasNextPage | boolean | flag indicating if the next notifications page to fetch is available. |
-| isLoading | boolean | flag indicating if the initial notifications fetch request is on the fly. |
-| isFetching | boolean | flag indicating if the notifications are fetching including initial fetch. |
-| isFetchingNextPage | boolean | flag indicating if the next notifications page request in on the fly. |
-| setStore | function | function used to change the current notifications [IStore](#store-interface) |
-| fetchNextPage | function | function that fires the fetch request for the next notifications page. |
-| refetch | function | function used to refetch all the notifications, when multiple page requests were made it will refetch all of them. |
-| markNotificationAsRead | function | function takes the notification (message) `messageId` as an argument and marks that notification (message) as read. |
-| markNotificationAsUnRead | function | function takes the notification (message) `messageId` as an argument and marks that notification (message) as unread. |
-| markNotificationAsSeen | function | function takes the notification (message) `messageId` as an argument and marks that notification (message) as seen. |
-| markFetchedNotificationsAsRead | function | function marks all the fetched notifications as read. |
-| markFetchedNotificationsAsSeen | function | function allowing you to mark all the fetched notifications as seen. |
-| markAllNotificationsAsRead | function | function allowing you to mark all notifications as read. |
-| markAllNotificationsAsSeen | function | function allowing you to mark notifications as seen. |
-| removeMessage | function | function takes the notification (message) `messageId` as an argument and delete a notification. |
-| removeAllMessages | function | The function allowing you to delete all notifications or a specific feed's (store's) notifications at once. |
+Description of the `useNotifications` hook return interface properties
+| Prop | Type | Description |
+| ------------------------------ | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
+| storeId | string | active `storeId` |
+| stores | [IStore[]](#store-interface) | array of [IStore](#store-interface) passed to the [NovuProvider](#novuprovider). |
+| unseenCount | number | unseen notifications (messages) count. |
+| notifications | [IMessage[]](#the-notification-imessage-model) | The feed notifications array. |
+| hasNextPage | boolean | flag indicating if the next notifications page to fetch is available. |
+| isLoading | boolean | flag indicating if the initial notifications fetch request is on the fly. |
+| isFetching | boolean | flag indicating if the notifications are fetching including initial fetch. |
+| isFetchingNextPage | boolean | flag indicating if the next notifications page request in on the fly. |
+| setStore | function | function used to change the current notifications [IStore](#store-interface) |
+| fetchNextPage | function | function that fires the fetch request for the next notifications page. |
+| refetch | function | function used to refetch all the notifications, when multiple page requests were made it will refetch all of them. |
+| markNotificationAsRead | function | function takes the notification (message) `messageId` as an argument and marks that notification (message) as read. |
+| markNotificationAsUnRead | function | function takes the notification (message) `messageId` as an argument and marks that notification (message) as unread. |
+| markNotificationAsSeen | function | function takes the notification (message) `messageId` as an argument and marks that notification (message) as seen. |
+| markFetchedNotificationsAsRead | function | function marks all the fetched notifications as read. |
+| markFetchedNotificationsAsSeen | function | function allowing you to mark all the fetched notifications as seen. |
+| markAllNotificationsAsRead | function | function allowing you to mark all notifications as read. |
+| markAllNotificationsAsSeen | function | function allowing you to mark notifications as seen. |
+| removeMessage | function | function takes the notification (message) `messageId` as an argument and delete a notification. |
+| removeAllMessages | function | The function allowing you to delete all notifications or a specific feed's (store's) notifications at once. |
### useFetchNotifications
@@ -447,8 +450,8 @@ Description of the `useNotifications` hook return interface properties
const query: IStoreQuery = {
limit: 10,
payload: {
- key: "value"
- }
+ key: "value",
+ },
};
const onSuccess = (data: IPaginatedResponse) => {};
@@ -474,7 +477,6 @@ interface IUseFetchNotificationsArgs {
onError?: (error: Error) => void;
// ... many more from the react-query useInfiniteQuery hook
}
-
```
`useFetchNotifications` hook return interface
@@ -507,7 +509,10 @@ const onSuccess = ({ count }: ICountData) => {};
const onError = (error: Error) => {};
-const { data, isLoading, isError, error } = useUnseenCount({ onSuccess, onError });
+const { data, isLoading, isError, error } = useUnseenCount({
+ onSuccess,
+ onError,
+});
```
`useUnseenCount` hook args interface
@@ -593,7 +598,7 @@ interface ICountData {
}
const query: IStoreQuery = {
- feedIdentifier: "product-updates"
+ feedIdentifier: "product-updates",
};
const onSuccess = (data: ICountData) => {};
@@ -636,7 +641,7 @@ interface IOrganizationEntity {
members: {
_id: string;
_userId?: string;
- user?: Pick;
+ user?: Pick;
roles: MemberRoleEnum[];
invite?: IMemberInvite;
memberStatus: MemberStatusEnum;
@@ -647,7 +652,7 @@ interface IOrganizationEntity {
fontColor: string;
fontFamily: string;
contentBackground: string;
- direction: 'ltr' | 'rtl';
+ direction: "ltr" | "rtl";
};
}
@@ -736,10 +741,11 @@ const onSuccess = (data: IUserPreferenceSettings) => {};
const onError = (error: Error) => {};
-const { updateUserPreferences, isLoading, isError, error } = useUpdateUserPreferences({
- onSuccess,
- onError,
-});
+const { updateUserPreferences, isLoading, isError, error } =
+ useUpdateUserPreferences({
+ onSuccess,
+ onError,
+ });
```
`useUpdateUserPreferences` hook args interface
@@ -779,7 +785,10 @@ const onSuccess = (data: IMessage) => {};
const onError = (error: Error) => {};
-const { updateAction, isLoading, isError, error } = useUpdateAction({ onSuccess, onError });
+const { updateAction, isLoading, isError, error } = useUpdateAction({
+ onSuccess,
+ onError,
+});
```
`useUpdateAction` hook args interface
@@ -820,10 +829,11 @@ const onSuccess = (data: IMessage[]) => {};
const onError = (error: Error) => {};
-const { markNotificationsAs, isLoading, isError, error } = useMarkNotificationsAs({
- onSuccess,
- onError,
-});
+const { markNotificationsAs, isLoading, isError, error } =
+ useMarkNotificationsAs({
+ onSuccess,
+ onError,
+ });
```
`useMarkNotificationsAs` hook args interface
@@ -863,10 +873,12 @@ const onSuccess = (data: IMessage) => {};
const onError = (error: Error) => {};
-const { removeNotification, isLoading, isError, error } = useRemoveNotification({
- onSuccess,
- onError,
-});
+const { removeNotification, isLoading, isError, error } = useRemoveNotification(
+ {
+ onSuccess,
+ onError,
+ }
+);
```
`useRemoveNotification` hook args interface
@@ -906,10 +918,11 @@ const onSuccess = (data: IMessage) => {};
const onError = (error: Error) => {};
-const { removeNotifications, isLoading, isError, error } = useRemoveNotifications({
- onSuccess,
- onError,
-});
+const { removeNotifications, isLoading, isError, error } =
+ useRemoveNotifications({
+ onSuccess,
+ onError,
+ });
```
`useRemoveNotifications` hook args interface
@@ -947,10 +960,11 @@ const onSuccess = (data: IMessage) => {};
const onError = (error: Error) => {};
-const { removeAllNotifications, isLoading, isError, error } = useRemoveAllNotifications({
- onSuccess,
- onError,
-});
+const { removeAllNotifications, isLoading, isError, error } =
+ useRemoveAllNotifications({
+ onSuccess,
+ onError,
+ });
```
`useRemoveAllNotifications` hook args interface
@@ -1150,11 +1164,12 @@ customization properties
| subscriber | [SubscriberProps](#subscriberprops) | Subscriber object that contains information about the subscriber |
### SubscriberProps
-| Property | Type | Description |
-| ------------ | --------------------------------- | -------------------------------------------------------------------- |
-| _id | string | Auto-generated identifier for the subscriber entity in the database |
-| firstName | string | First name of the subscriber |
-| subscriberId | string | identifier of the subscriber entity in the Novu Web Dashboard |
+
+| Property | Type | Description |
+| ------------ | ------ | ------------------------------------------------------------------- |
+| \_id | string | Auto-generated identifier for the subscriber entity in the database |
+| firstName | string | First name of the subscriber |
+| subscriberId | string | identifier of the subscriber entity in the Novu Web Dashboard |
### IMessageButton
diff --git a/notification-center/client/react/customization.mdx b/inbox/react/customization.mdx
similarity index 99%
rename from notification-center/client/react/customization.mdx
rename to inbox/react/customization.mdx
index 8a43a1fb..cd8be39c 100644
--- a/notification-center/client/react/customization.mdx
+++ b/inbox/react/customization.mdx
@@ -241,8 +241,8 @@ export const styles = {
color: "#AFE1AF",
fill: "white",
minWidth: "20px",
- minHeight: "20px"
- }
+ minHeight: "20px",
+ },
},
dot: {
rect: {
@@ -251,14 +251,13 @@ export const styles = {
width: "3px",
height: "3px",
x: 10,
- y: 2
- }
- }
- }
-}
+ y: 2,
+ },
+ },
+ },
+};
```
-
```javascript
const primaryColor = "white";
@@ -457,10 +456,9 @@ export const styles = {
[![Edit custom-styles-novu-nc](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/custom-styles-novu-nc-2jd46m?fontsize=14&module=%2Fsrc%2Fstyles.js&moduleview=1&theme=dark)
-
## Customization Using Hooks
If you don't want to use our pre built component then, you can build your own notification center using hooks. `@novu/notification-center` react package provides many hooks like `useNotifications`, `useFetchNotifications`, `useUpdateUserPreferences`. Checkout all available [hooks](/notification-center/client/react/api-reference#hooks). All the hooks should be defined inside the [NovuProvider](/notification-center/client/react/api-reference#novuprovider) component. Most of the hooks are based on the `@tanstack/react-query` library.
Checkout below example on how to use `useNotifications` and `useFetchNotifications` hook
-[![Edit useNotifications-useFetchNotifications-hook](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/usenotifications-usefetchnotifications-hook-2t6sgz?fontsize=14&hidenavigation=1&theme=dark)
\ No newline at end of file
+[![Edit useNotifications-useFetchNotifications-hook](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/usenotifications-usefetchnotifications-hook-2t6sgz?fontsize=14&hidenavigation=1&theme=dark)
diff --git a/notification-center/client/react/get-started.mdx b/inbox/react/get-started.mdx
similarity index 76%
rename from notification-center/client/react/get-started.mdx
rename to inbox/react/get-started.mdx
index 1a7b1352..8715f30c 100644
--- a/notification-center/client/react/get-started.mdx
+++ b/inbox/react/get-started.mdx
@@ -40,7 +40,6 @@ function Novu() {
Go to this react app browser tab, there will be a bell icon. On clicking that bell icon, you will see a notification component popover
-
@@ -77,19 +76,18 @@ function Novu() {
```
## Notification center without bell
+
If you don't want to show the bell icon, you can directly render the notification center component without passing the bell, use `` component in place of ``
+
```jsx
-import {
- NovuProvider,
- NotificationCenter,
-} from "@novu/notification-center";
+import { NovuProvider, NotificationCenter } from "@novu/notification-center";
-
+;
```
## HMAC Encryption
@@ -130,7 +128,11 @@ const hmacHash = createHmac("sha256", process.env.NOVU_API_KEY)
```
-If HMAC encryption is active in In-App provider settings and `subscriberHash` along with `subscriberId` is not provided, then notification center will not load
+
+ If HMAC encryption is active in In-App provider settings and `subscriberHash`
+ along with `subscriberId` is not provided, then notification center will not
+ load
+
## Notification Actions
@@ -186,7 +188,6 @@ import {
} from "@novu/notification-center";
export default function Novu() {
-
const CustomNotificationCenter = () => {
const { updateAction } = useUpdateAction();
@@ -232,43 +233,6 @@ export default function Novu() {
CTA buttons text and redirect url field supports dynamic variables
-
-## Avatar Icons
-
-Avatar images can be shown with in-app notifications. To do so, enable `Add an Avatar` option in in-app step editor as shown below
-
-
-
-
-
-**There are 3 ways to show the avatar images in the notifications:**
-
-
-
-
-
-### User Avatar
-This option will show the avatar of the actor user. actor field can be sent while triggering the worklfow. Each subscriber has `avatar` field. For this option to work actor should have `avatar` field set with valid publicly accessible image URL. If the actor doesn't have `avatar` field, then the default avatar will be shown. Worklfow trigger example with avatar
-
-```javascript
-await novu.trigger('', {
- to: {
- subscriberId: 'subscriberId_1',
- },
- payload: {
- "key": "value"
- },
- actor: "subscriberId_2"
-});
-```
-Here subscriberId_2 is used as actor and workflow is triggered to subscriberId_1
-
-### Static Avatar Url
-This option can be used if you want to show same, static and custom avatar icon for each in-app notification of this workflow in-app step. Make sure to toggle off **User Avatar** option to enable this. This is a input field where only valid publicly accessible image URL can be entered. Currently variables are not supported in this field.
-
-### System Avatar Icons
-Novu supports 6 system avatar icons. These are default icons that can be selected as avatar icon. Once selected, same icon will be used as avatar icons for all notifications of this in-app step.
-
## Realtime sockets
Novu provides a real-time socket API for you to consume and get updates about new notifications added to the user's feed. To use the socket connection you can use the `useSocket` hook provided by the `@novu/notification-center` library. Let's see an example of that:
@@ -322,53 +286,51 @@ Novu does not have a native taost component. However, if your project is using a
socket.on("notification_received", (data) => {
console.log(data);
// set received notification content as toast content
- setToastContent(data.content)
+ setToastContent(data.content);
// open the toast
- openToast(true)
+ openToast(true);
});
```
-
## Example
[![Edit kind-nova-xv6s9g](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/kind-nova-xv6s9g?fontsize=14&hidenavigation=1&theme=dark)
-
## Frequently Asked Questions
- Possible reasons for the notification center not loading properly:
+Possible reasons for the notification center 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)
-
+
- The notification center should be wrapped in ``
-
+The notification center should be wrapped in ``
+
- The redirect URL is for the entire notification item, When the user clicks the notification, the user will be routed to that url. CTA are two call-to-action buttons. `onNotificationClick` function prop is used for redirecting url and the `onActionClick` function prop is used for CTA.
-
+The redirect URL is for the entire notification item, When the user clicks the notification, the user will be routed to that url. CTA are two call-to-action buttons. `onNotificationClick` function prop is used for redirecting url and the `onActionClick` function prop is used for CTA.
+
-
+
- Bell icon and notification center in Novu dashboard is only for receiving system related notifications like user you invited has joined, password reset request sent. It can not to used to test notification center. Consider using our [codesandbox example](https://codesandbox.io/s/kind-nova-xv6s9g?fontsize=14&hidenavigation=1&theme=dark) instead.
-
+Bell icon and notification center in Novu dashboard is only for receiving system related notifications like user you invited has joined, password reset request sent. It can not to used to test notification center. Consider using our [codesandbox example](https://codesandbox.io/s/kind-nova-xv6s9g?fontsize=14&hidenavigation=1&theme=dark) instead.
+
Our notification center is configures for all hosts. Please disable root level `withCredentials` config in axios or fetch http requests.
-
+
diff --git a/notification-center/client/react/multiple-tabs.mdx b/inbox/react/multiple-tabs.mdx
similarity index 92%
rename from notification-center/client/react/multiple-tabs.mdx
rename to inbox/react/multiple-tabs.mdx
index c10acf1f..e063c580 100644
--- a/notification-center/client/react/multiple-tabs.mdx
+++ b/inbox/react/multiple-tabs.mdx
@@ -30,16 +30,16 @@ To create multiple stores you can use the prop `stores` on the `NovuProvider`
Using the `query` object multiple fields can be passed for feed API:
-- `feedIdentifier` - Can be configured and created on the WEB UI
+- `feedIdentifier` - Can be configured and created on the Dashboard UI
- `seen` - Identifies if the notification has been seen or not
After specifying the `stores` prop, you can use the `storeId` property to interact with the store.
-### Managing feeds on the web UI
+### Managing feeds on the Dashboard UI
1. How to add a new feed or select existing feed for In-App step?
-To add a new feed, enable *Use Feeds* checkbox in In-App editor. Select from existing feeds or create a new feed by writing in the input field and then clicking on plus icon in the right side.
+To add a new feed, enable _Use Feeds_ checkbox in In-App editor. Select from existing feeds or create a new feed by writing in the input field and then clicking on plus icon in the right side.
@@ -54,7 +54,8 @@ To copy `feedIdentifier` (`storeId`) click on the feed name of existing feeds. c
-By specifying only a storeId, without a query, you could get all notifications.
+ By specifying only a storeId, without a query, you could get all
+ notifications.
### Using `tabs` prop on the notification center
diff --git a/notification-center/client/react/preference.mdx b/inbox/react/preference.mdx
similarity index 100%
rename from notification-center/client/react/preference.mdx
rename to inbox/react/preference.mdx
diff --git a/framework/integrations/react-email.mdx b/integrations/content/react-email.mdx
similarity index 84%
rename from framework/integrations/react-email.mdx
rename to integrations/content/react-email.mdx
index b47fed7d..840aefbd 100644
--- a/framework/integrations/react-email.mdx
+++ b/integrations/content/react-email.mdx
@@ -1,8 +1,16 @@
---
-title: "React E-mail"
+title: "React Email"
---
-Integrating Novu Framework with [React.Email](https://react.email/) for your Next.js application can be done in three steps. If you don't have an app, you can create one with the `create-novu-app` command.
+Integrating Novu Framework with [React.Email](https://react.email/) for your Next.js application can be done in three steps.
+
+ If you don't have an app, you can create one with the `create-novu-app` command.
+
+```bash
+npx create-novu-app@latest --api-key=
+```
+
+
@@ -12,6 +20,7 @@ Integrating Novu Framework with [React.Email](https://react.email/) for your Nex
```bash
npm i @react-email/components react-email
```
+
Create a new `sample-email.tsx` file for your email template.
@@ -37,7 +46,7 @@ Integrating Novu Framework with [React.Email](https://react.email/) for your Nex
return render();
}
```
-
+
Define your Workflow using the above template
@@ -55,5 +64,6 @@ Integrating Novu Framework with [React.Email](https://react.email/) for your Nex
});
});
```
+
diff --git a/framework/integrations/remix-react-email.mdx b/integrations/content/remix-react-email.mdx
similarity index 98%
rename from framework/integrations/remix-react-email.mdx
rename to integrations/content/remix-react-email.mdx
index 3e1c552c..b68f68b1 100644
--- a/framework/integrations/remix-react-email.mdx
+++ b/integrations/content/remix-react-email.mdx
@@ -1,5 +1,5 @@
---
-title: "Remix w/ React E-mail"
+title: "Remix & React Email"
---
Integrating Novu Framework with [React email](https://react.email/) for your Remix application can be done in three steps. If you don't have an app, you can [clone our Remix example](https://github.com/novuhq/novu-framework-remix-example).
@@ -11,6 +11,7 @@ Integrating Novu Framework with [React email](https://react.email/) for your Rem
```bash
npm i @react-email/components react-email
```
+
Create an `emails` folder in the `app` directory of your Remix app.
@@ -38,6 +39,7 @@ Integrating Novu Framework with [React email](https://react.email/) for your Rem
return render();
}
```
+
Define your Workflow using the above template
@@ -55,5 +57,6 @@ Integrating Novu Framework with [React email](https://react.email/) for your Rem
});
});
```
+
diff --git a/framework/integrations/svelte-email.mdx b/integrations/content/svelte-email.mdx
similarity index 99%
rename from framework/integrations/svelte-email.mdx
rename to integrations/content/svelte-email.mdx
index f9cfdbfd..4ddf505c 100644
--- a/framework/integrations/svelte-email.mdx
+++ b/integrations/content/svelte-email.mdx
@@ -1,5 +1,5 @@
---
-title: "Svelte E-mail"
+title: "Svelte Email"
---
Integrating Novu Framework with [Svelte email](https://react.email/) for your Svelte application can be done in three steps. If you don't have an app, you can [clone our Svelte example](https://github.com/novuhq/novu-svelte-email).
@@ -11,6 +11,7 @@ Integrating Novu Framework with [Svelte email](https://react.email/) for your Sv
```bash
npm i svelte-email
```
+
Create an `emails` folder in the `src/lib` directory of your Svelte app.
@@ -99,6 +100,7 @@ Integrating Novu Framework with [Svelte email](https://react.email/) for your Sv
```
+
Define your Workflow using the above template
@@ -126,5 +128,6 @@ Integrating Novu Framework with [Svelte email](https://react.email/) for your Sv
}
);
```
+
diff --git a/framework/integrations/vue-email.mdx b/integrations/content/vue-email.mdx
similarity index 99%
rename from framework/integrations/vue-email.mdx
rename to integrations/content/vue-email.mdx
index 3eeb4c5d..6dc853c9 100644
--- a/framework/integrations/vue-email.mdx
+++ b/integrations/content/vue-email.mdx
@@ -1,5 +1,5 @@
---
-title: "Vue E-mail"
+title: "Vue Email"
---
You can integrate Novu Framework with [Vue Email](https://vuemail.net/) in a few simple steps. This guide will walk you through the process of creating a new email template using Vue Email and Nuxt.
@@ -93,6 +93,7 @@ For a Quickstart Boilerplate project using Nuxt.js, and Vue Email, check out the
});
```
+
## Learn More
diff --git a/channels-and-providers/chat/discord.mdx b/integrations/providers/chat/discord.mdx
similarity index 92%
rename from channels-and-providers/chat/discord.mdx
rename to integrations/providers/chat/discord.mdx
index 9443fedb..12d76b20 100644
--- a/channels-and-providers/chat/discord.mdx
+++ b/integrations/providers/chat/discord.mdx
@@ -1,6 +1,6 @@
---
-title: 'Discord'
-description: 'Learn about how to use Discord provider for chat notifications'
+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:
@@ -19,7 +19,7 @@ To get started with using Novu’s Discord Webhook integration, you need a ‘we
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
@@ -31,12 +31,13 @@ import {
const novu = new Novu("");
await novu.subscribers.setCredentials('subscriberId', ChatProviderIdEnum.Discord, {
- webhookUrl: "",
+webhookUrl: "",
});
-```
+
+````
-```bash
+```bash
curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
@@ -48,13 +49,15 @@ curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials'
},
"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.
\ No newline at end of file
+
+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/channels-and-providers/chat/mattermost.mdx b/integrations/providers/chat/mattermost.mdx
similarity index 66%
rename from channels-and-providers/chat/mattermost.mdx
rename to integrations/providers/chat/mattermost.mdx
index fb5baf66..41339639 100644
--- a/channels-and-providers/chat/mattermost.mdx
+++ b/integrations/providers/chat/mattermost.mdx
@@ -1,6 +1,6 @@
---
-title: 'Mattermost'
-description: 'Learn about how to use Mattermost provider for chat notifications'
+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:
@@ -8,7 +8,6 @@ When using Mattermost, you will have to store the integration credentials within
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:
@@ -20,26 +19,27 @@ To integrate Mattermost with your application using the Mattermost Webhook integ
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';
+import { Novu, ChatProviderIdEnum } from "@novu/node";
const novu = new Novu("");
-await novu.subscribers.setCredentials('subscriberId', ChatProviderIdEnum.Mattermost, { webhookUrl: '', });
+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!'
- },
- }
-);
+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.
@@ -47,20 +47,24 @@ To integrate Mattermost with your application using the Mattermost Bot integrati
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';
+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: '' });
+await novu.subscribers.setCredentials(
+ "subscriberId",
+ ChatProviderIdEnum.Mattermost,
+ { botApiToken: "" }
+);
// Send a notification to Mattermost using the bot API token.
-await novu.trigger('', {
+await novu.trigger("", {
to: {
- subscriberId: '',
+ subscriberId: "",
},
payload: {
- message: 'This is a notification from my application!',
+ message: "This is a notification from my application!",
},
});
```
diff --git a/channels-and-providers/chat/ms-teams.mdx b/integrations/providers/chat/ms-teams.mdx
similarity index 82%
rename from channels-and-providers/chat/ms-teams.mdx
rename to integrations/providers/chat/ms-teams.mdx
index 73defcf0..35980b47 100644
--- a/channels-and-providers/chat/ms-teams.mdx
+++ b/integrations/providers/chat/ms-teams.mdx
@@ -1,9 +1,9 @@
---
-title: 'MS Teams'
-description: 'Learn about how to use MS Teams provider for chat notifications'
+title: "MS Teams"
+description: "Learn about how to use MS Teams provider for chat notifications"
---
-import ProviderImplementation from '/snippets/provider-implementation.mdx';
+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
@@ -13,7 +13,9 @@ Similar to [Discord](https://www.notion.so/Additional-Resources-65ef4aca5d0f4115
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
@@ -33,15 +35,16 @@ import {
const novu = new Novu("");
await novu.subscribers.setCredentials(
- 'subscriberId',
- ChatProviderIdEnum.MsTeams, // providerId
- { webhookUrl: "" },
- 'msteams-MnGLxp8uy' // integration identifier
+'subscriberId',
+ChatProviderIdEnum.MsTeams, // providerId
+{ webhookUrl: "" },
+'msteams-MnGLxp8uy' // integration identifier
);
-```
+
+````
-```bash
+```bash
curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
@@ -53,7 +56,8 @@ curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials'
},
"integrationIdentifier": "msteams-MnGLxp8uy"
}'
-```
+````
+
@@ -63,5 +67,4 @@ Checkout the [API reference](/api-reference/subscribers/update-subscriber-creden
- `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](https://docs.novu.co/api/update-subscriber-credentials/).
-
-
\ No newline at end of file
+
diff --git a/channels-and-providers/chat/overview.mdx b/integrations/providers/chat/overview.mdx
similarity index 70%
rename from channels-and-providers/chat/overview.mdx
rename to integrations/providers/chat/overview.mdx
index 8fe9daea..f8f30c00 100644
--- a/channels-and-providers/chat/overview.mdx
+++ b/integrations/providers/chat/overview.mdx
@@ -1,22 +1,27 @@
---
-title: 'Chat Channel Overview'
-sidebarTitle: 'Overview'
-description: 'Learn the process of configuring and using chat providers with Novu'
+title: "Chat Channel Overview"
+sidebarTitle: "Overview"
+description: "Learn the process of configuring and using chat providers with Novu"
---
import { MissingProvider } from "/snippets/missing-provider.mdx";
Novu can be used to deliver chat messages to your customers using a unified delivery API. You can easily integrate your favorite chat provider using the built-in integration store.
-
+
## Configuring chat providers
-To configure a chat provider, you need to add a new integration to your Novu account. You can do this by navigating to the integration store and clicking on the **Add a provider** button and then select the chat provider you want to configure. You can find the [integration store](https://web.novu.co/integrations?utm_campaign=docs-chat-overview) in the left sidebar of the Novu dashboard.
+To configure a chat provider, you need to add a new integration to your Novu account. You can do this by navigating to the integration store and clicking on the **Add a provider** button and then select the chat provider you want to configure. You can find the [integration store](https://dashboard.novu.co/integrations?utm_campaign=docs-chat-overview) in the left sidebar of the Novu dashboard.
Each chat provider requires defferent type of credentials. There are few providers which does not require any credentials example: `Discord`
-
## Sending chat message
Steps to send a chat message using Novu:-
@@ -26,7 +31,7 @@ Steps to send a chat message using Novu:-
> Step 2 can be skipped if you already have a subscriber. You can use the `subscriberId` of an existing subscriber.
-3. [Update](/channels-and-providers/chat/overview#update-credential-webhookurl) the subscriber credential `webhookUrl` for this provider and integration.
+3. [Update](/channels-and-providers/chat/overview#update-credential-webhookurl) the subscriber credential `webhookUrl` for this provider and integration.
4. Create a new [worklow](/workflows/notification-workflows) or use an existing workflow. Add chat channel and [write content](/content-creation-design/notification-content-creation#chat) for the message.
@@ -47,12 +52,13 @@ import {
const novu = new Novu("");
await novu.subscribers.setCredentials('subscriberId', ChatProviderIdEnum.Slack, {
- webhookUrl: "",
+webhookUrl: "",
});
-```
+
+````
-```bash
+```bash
curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
@@ -64,26 +70,31 @@ curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials'
},
"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.
+
+ {" "}
+ 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.
+ - 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).
+ - `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.
+ - if subscriber have credentials set but integration is either not active or deleted for this credential.
-
+
-
diff --git a/channels-and-providers/chat/slack.mdx b/integrations/providers/chat/slack.mdx
similarity index 63%
rename from channels-and-providers/chat/slack.mdx
rename to integrations/providers/chat/slack.mdx
index c815a4eb..cf284f43 100644
--- a/channels-and-providers/chat/slack.mdx
+++ b/integrations/providers/chat/slack.mdx
@@ -1,6 +1,6 @@
---
-title: 'Slack'
-description: 'Learn about how to use Slack provider for chat notifications'
+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.
@@ -9,7 +9,10 @@ This guide will walk you through the steps needed to obtain the `webhookUrl` t
We will provide the basic flow that the user needs to perform, to successfully send notifications via the Slack integration.
-We've a [dedicated guide](/guides/slack-guide) on integrating Novu in a Slack app.
+
+ We've a [dedicated guide](/guides/slack-guide) on integrating Novu in a Slack
+ app.
+
### Creating application
@@ -28,21 +31,27 @@ If you use this approach, then Novu will manage the OAuth flow and store the cre
1. Configure your Slack application as mentioned [below](#configuring-slack-application).
2. You need to make a network request to the `Shareable URL` to perform authentication.
-3. You can find the `Shareable URL` in the [Integration Store](https://web.novu.co/integrations?utm_campaign=docs-integrations-slack)
-
-4. You can either add the `Add to Slack` button or use the `Shareable URL` directly, in the application you'll be using Novu in.
-The network request to the 'Shareable URL' will happen when the user clicks the 'Add to Slack' button.
+3. You can find the `Shareable URL` in the [Integration Store](https://dashboard.novu.co/integrations?utm_campaign=docs-integrations-slack)
+
+ {" "}
+
+4. You can either add the `Add to Slack` button or use the `Shareable URL` directly, in the application you'll be using Novu in.
+
+ The network request to the 'Shareable URL' will happen when the user clicks
+ the 'Add to Slack' button.
+
5. This is to request permission for access (scope: incoming-webhook).
-6. You can use the generated `Shareable URL` that is found under the Slack integration in the [Integration Store](https://web.novu.co/integrations?utm_campaign=docs-integrations-slack). The `Shareable URL` should have the following format:
+6. You can use the generated `Shareable URL` that is found under the Slack integration in the [Integration Store](https://dashboard.novu.co/integrations?utm_campaign=docs-integrations-slack). The `Shareable URL` should have the following format:
+
```bash
https://api.novu.co/v1/subscribers//credentials/slack/oauth?environmentId=&integrationIdentifier=.
```
- `SUBSCRIBER_ID` is a custom identifier used when identifying your users within the Novu platform.
-- `ENVIRONMENT_ID` is a context of an environment you can locate your environment id in the setting in the [dashboard settings](https://web.novu.co/settings?utm_campaign=docs-integrations-slack).
-- `PROVIDER_ID` (optional) is a unique identifier of the integration and is required when you have multiple slack integrations in Novu. You can locate your integration identifier in the [Integration Store](https://web.novu.co/integrations?utm_campaign=docs-integratons-slack). When not provided, the last created integration will be used.
-If you are using the `Add to Slack` button you have to provide the `Shareable URL` as the `redirect_uri` parameter like in this example. Make sure that the `Shareable URL` is URL encoded:
+- `ENVIRONMENT_ID` is a context of an environment you can locate your environment id in the setting in the [dashboard settings](https://dashboard.novu.co/settings?utm_campaign=docs-integrations-slack).
+- `PROVIDER_ID` (optional) is a unique identifier of the integration and is required when you have multiple slack integrations in Novu. You can locate your integration identifier in the [Integration Store](https://dashboard.novu.co/integrations?utm_campaign=docs-integratons-slack). When not provided, the last created integration will be used.
+ If you are using the `Add to Slack` button you have to provide the `Shareable URL` as the `redirect_uri` parameter like in this example. Make sure that the `Shareable URL` is URL encoded:
```html
```
+
7. Either you use the 'add to Slack' button or use the `Shareable URL`, you should land here:
-
-8. Then you'll be redirected to the address you chose in the [Integration Store](https://web.novu.co/integrations?utm_campaign=docs-integrations-slack):
-
-You can use the URL of whichever page you want your users to land on, after successful execution
+
+ {" "}
+
+8. Then you'll be redirected to the address you chose in the [Integration Store](https://dashboard.novu.co/integrations?utm_campaign=docs-integrations-slack):
+
+ {" "}
+
+
+ You can use the URL of whichever page you want your users to land on, after
+ successful execution
+
9. That's it! Now you can trigger your workflow and send notifications:
-
-Don't forget to check out our [dedicated guide](/guides/slack-guide) on integrating Novu in a Slack app for more.
+
+ {" "}
+
+
+ Don't forget to check out our [dedicated guide](/guides/slack-guide) on
+ integrating Novu in a Slack app for more.
+
+
### 2. Manually managed
-To use the manually managed option, you need to generate a `webhookUrl` and plug it into your backend.
+
+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:
## Update credential webhookUrl
@@ -91,12 +124,13 @@ import {
const novu = new Novu("");
await novu.subscribers.setCredentials('subscriberId', ChatProviderIdEnum.Slack, {
- webhookUrl: "",
+webhookUrl: "",
});
-```
+
+````
-```bash
+```bash
curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
@@ -108,7 +142,8 @@ curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials'
},
"integrationIdentifier": "slack-MnGLxp8uy"
}'
-```
+````
+
@@ -123,8 +158,8 @@ Checkout the [API reference](/api-reference/subscribers/update-subscriber-creden
## 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.
- - If you use the Novu Managed solution add `https://api.novu.co/v1/subscribers`.
+ - If you use a manual Management solution, add the API endpoint you created in Step 1.
+ - If you use the Novu Managed solution add `https://api.novu.co/v1/subscribers`.
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.
@@ -134,16 +169,15 @@ To enable Hash-Based Message Authentication Codes, you need to do the following
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_API_KEY)
- .update(subscriberId)
- .digest('hex');
-
- ```
-
+
+ ```jsx
+ import { createHmac } from "crypto";
+
+ const hmacHash = createHmac("sha256", process.env.NOVU_API_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/channels-and-providers/chat/whats-app.mdx b/integrations/providers/chat/whats-app.mdx
similarity index 77%
rename from channels-and-providers/chat/whats-app.mdx
rename to integrations/providers/chat/whats-app.mdx
index 99322061..3c24681a 100644
--- a/channels-and-providers/chat/whats-app.mdx
+++ b/integrations/providers/chat/whats-app.mdx
@@ -1,7 +1,7 @@
---
-title: 'How to send WhatsApp Business notifications with Novu'
-sidebarTitle: 'WhatsApp Business'
-description: 'Learn about how to use WhatsApp for chat notifications'
+title: "How to send WhatsApp Business notifications with Novu"
+sidebarTitle: "WhatsApp Business"
+description: "Learn about how to use WhatsApp for chat notifications"
---
## Getting Started
@@ -21,12 +21,14 @@ On the App Setup page, click on "Set Up" under the "WhatsApp" product. You will
### 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.
+ 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
@@ -63,12 +65,13 @@ and in the `overrides` field, add the following:
```
- For test credentials you can only used the built in Whats App Template.
+ 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.
@@ -77,7 +80,6 @@ Follow the [Facebook Instructions](https://developers.facebook.com/docs/whatsapp
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.
@@ -86,21 +88,21 @@ After your template is approved, you can use the `template_name` to send notific
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"
+novu.trigger("workflow-id", {
+ to: {
+ subscriberId: "SUBSCRIBER_ID",
+ phone: "+11111111111",
+ },
+ payload: {},
+ overrides: {
+ chat: {
+ template: {
+ name: "template_name",
+ language: {
+ code: "en_US",
+ },
+ },
},
- payload: {},
- overrides: {
- chat: {
- template: {
- name: "template_name",
- language: {
- code: "en_US"
- }
- }
- }
- }
-})
+ },
+});
```
diff --git a/channels-and-providers/chat/zulip.mdx b/integrations/providers/chat/zulip.mdx
similarity index 82%
rename from channels-and-providers/chat/zulip.mdx
rename to integrations/providers/chat/zulip.mdx
index 228c5281..533a9bb2 100644
--- a/channels-and-providers/chat/zulip.mdx
+++ b/integrations/providers/chat/zulip.mdx
@@ -1,6 +1,6 @@
---
-title: 'Zulip'
-description: 'Learn about how to use Zulip provider for chat notifications'
+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.
@@ -13,19 +13,27 @@ Similar to Discord, the credential for this provider needs to be stored in the s
- 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
@@ -48,12 +56,13 @@ import {
const novu = new Novu("");
await novu.subscribers.setCredentials('subscriberId', ChatProviderIdEnum.Zulip, {
- webhookUrl: "",
+webhookUrl: "",
});
-```
+
+````
-```bash
+```bash
curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
@@ -65,7 +74,8 @@ curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials'
},
"integrationIdentifier": "zulip-MnGLxp8uy"
}'
-```
+````
+
diff --git a/integrations/providers/default-providers.mdx b/integrations/providers/default-providers.mdx
new file mode 100644
index 00000000..0c312651
--- /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.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/channels-and-providers/email/amazon-ses.mdx b/integrations/providers/email/amazon-ses.mdx
similarity index 74%
rename from channels-and-providers/email/amazon-ses.mdx
rename to integrations/providers/email/amazon-ses.mdx
index dc8980ad..dcf31ecf 100644
--- a/channels-and-providers/email/amazon-ses.mdx
+++ b/integrations/providers/email/amazon-ses.mdx
@@ -1,6 +1,6 @@
---
-title: 'Amazon SES'
-description: 'Learn how to use the Amazon SES provider to send email notifications using Novu'
+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.
@@ -23,14 +23,16 @@ To use the Amazon SES provider in the email channel, you will need to create an
## Creating an SES integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-integrations-ses) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
+
+ 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.
@@ -40,11 +42,9 @@ To use the Amazon SES provider in the email channel, you will need to create an
- 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.
+ 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/channels-and-providers/email/braze.mdx b/integrations/providers/email/braze.mdx
similarity index 82%
rename from channels-and-providers/email/braze.mdx
rename to integrations/providers/email/braze.mdx
index f7e89ffc..9a9d75c3 100644
--- a/channels-and-providers/email/braze.mdx
+++ b/integrations/providers/email/braze.mdx
@@ -1,6 +1,6 @@
---
-title: 'Braze'
-description: 'Learn how to use the Braze provider to send email notifications using Novu'
+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.
@@ -19,10 +19,9 @@ To generate a new API key in Braze, you can follow these steps:
- 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://web.novu.co/integrations?utm_campaign=docs-braze) page on Novu.
+- Visit the [Integrations](https://dashboard.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).
@@ -32,4 +31,4 @@ To generate a new API key in Braze, you can follow these steps:
- Enter the `Base URL`.
- Enter the `From email address`.
- Enter the `Sender name`.
-- Click on the **Update** button.
\ No newline at end of file
+- Click on the **Update** button.
diff --git a/channels-and-providers/email/custom-smtp.mdx b/integrations/providers/email/custom-smtp.mdx
similarity index 75%
rename from channels-and-providers/email/custom-smtp.mdx
rename to integrations/providers/email/custom-smtp.mdx
index 1adf0bfe..bad0435a 100644
--- a/channels-and-providers/email/custom-smtp.mdx
+++ b/integrations/providers/email/custom-smtp.mdx
@@ -1,6 +1,6 @@
---
-title: 'Custom SMTP'
-description: 'Learn how to use the Custom SMTP provider to send email notifications using Novu'
+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.
@@ -23,17 +23,17 @@ Those options are:
# Creating a Custom SMTP integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-customsmtp) page on Novu.
+- Visit the [Integrations](https://dashboard.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*
+ - `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.
\ No newline at end of file
+- You should now be able to send notifications using Custom SMTP in Novu.
diff --git a/channels-and-providers/email/infobip.mdx b/integrations/providers/email/infobip.mdx
similarity index 76%
rename from channels-and-providers/email/infobip.mdx
rename to integrations/providers/email/infobip.mdx
index 82cf7a2b..8df2304d 100644
--- a/channels-and-providers/email/infobip.mdx
+++ b/integrations/providers/email/infobip.mdx
@@ -1,6 +1,6 @@
---
-title: 'Infobip - email'
-description: 'Learn how to use the Infobip provider to send email notifications using Novu'
+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.
@@ -18,14 +18,14 @@ To generate a new API key in Infobip, you can follow these steps:
# Creating an Infobip integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-infobip) page on Novu.
+- Visit the [Integrations](https://dashboard.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`.
+ - 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.
\ No newline at end of file
+- You should now be able to send notifications using Infobip in Novu.
diff --git a/channels-and-providers/email/mailersend.mdx b/integrations/providers/email/mailersend.mdx
similarity index 69%
rename from channels-and-providers/email/mailersend.mdx
rename to integrations/providers/email/mailersend.mdx
index c048ad81..7734e49d 100644
--- a/channels-and-providers/email/mailersend.mdx
+++ b/integrations/providers/email/mailersend.mdx
@@ -1,6 +1,6 @@
---
-title: 'Mailersend'
-description: 'Learn how to use the MailerSend provider to send email notifications using Novu'
+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.
@@ -11,7 +11,7 @@ To use the MailerSend provider in the email channel, you will need to create a M
## Creating the MailerSend integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-mailersend) page on Novu.
+- Visit the [Integrations](https://dashboard.novu.co/integrations?utm_campaign=docs-mailersend) page on Novu.
- Click on Add a Provider.
- Select MailerSend service.
- Enter the API key.
@@ -33,51 +33,52 @@ import {
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"
+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
@@ -126,7 +127,7 @@ curl --location 'https://api.novu.co/v1/events/trigger' \
}
}
}'
-```
+````
+
-
diff --git a/channels-and-providers/email/mailgun.mdx b/integrations/providers/email/mailgun.mdx
similarity index 77%
rename from channels-and-providers/email/mailgun.mdx
rename to integrations/providers/email/mailgun.mdx
index c6fecce1..2039a07c 100644
--- a/channels-and-providers/email/mailgun.mdx
+++ b/integrations/providers/email/mailgun.mdx
@@ -1,6 +1,6 @@
---
-title: 'Mailgun'
-description: 'Learn how to use the Mailgun provider to send email notifications using Novu'
+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.
@@ -22,22 +22,22 @@ To generate a new API key in Mailgun, you can follow these steps:
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`.
+ - 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://web.novu.co/integrations?utm_campaign=docs-mailgun) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
+ - 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.
\ No newline at end of file
+- You should now be able to send notifications using Mailgun in Novu.
diff --git a/channels-and-providers/email/mailjet.mdx b/integrations/providers/email/mailjet.mdx
similarity index 90%
rename from channels-and-providers/email/mailjet.mdx
rename to integrations/providers/email/mailjet.mdx
index 58c88d6e..2c15a310 100644
--- a/channels-and-providers/email/mailjet.mdx
+++ b/integrations/providers/email/mailjet.mdx
@@ -1,6 +1,6 @@
---
-title: 'Mailjet'
-description: 'Learn how to use the Mailjet provider to send email notifications using Novu'
+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.
@@ -30,11 +30,11 @@ Mailjet allows you to authenticate your sender identity using one of the followi
# Creating a Mailjet integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-mailjet) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
\ No newline at end of file
+- You should now be able to send notifications using Mailjet in Novu.
diff --git a/channels-and-providers/email/mailtrap.mdx b/integrations/providers/email/mailtrap.mdx
similarity index 86%
rename from channels-and-providers/email/mailtrap.mdx
rename to integrations/providers/email/mailtrap.mdx
index 307353db..b20f677e 100644
--- a/channels-and-providers/email/mailtrap.mdx
+++ b/integrations/providers/email/mailtrap.mdx
@@ -1,6 +1,6 @@
---
-title: 'Mailtrap'
-description: 'Learn how to use the Mailtrap provider to send email notifications using Novu'
+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.
@@ -15,7 +15,7 @@ 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.
+- 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
@@ -24,7 +24,7 @@ Before you can send emails, you will need to [verify your sending domain ownersh
# Creating a Mailtrap integration with Novu
-- Visit the [Integrations store](https://web.novu.co/integrations?utm_campaign=docs-mailtrap) on the Novu web dashboard.
+- Visit the [Integrations store](https://dashboard.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.
diff --git a/channels-and-providers/email/mandrill.mdx b/integrations/providers/email/mandrill.mdx
similarity index 89%
rename from channels-and-providers/email/mandrill.mdx
rename to integrations/providers/email/mandrill.mdx
index bb7c2b8f..d449413d 100644
--- a/channels-and-providers/email/mandrill.mdx
+++ b/integrations/providers/email/mandrill.mdx
@@ -1,6 +1,6 @@
---
-title: 'Mandrill'
-description: 'Learn how to use the Mandrill provider to send email notifications using Novu'
+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.
@@ -27,7 +27,7 @@ To get started, you’ll need to add the domain that you want to send messages f
# Creating the Mandrill integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-mandrill) page on Novu.
+- Visit the [Integrations](https://dashboard.novu.co/integrations?utm_campaign=docs-mandrill) page on Novu.
- Click on Add a Provider.
- Select Mandrill service.
- Enter your Mandrill API key.
@@ -35,4 +35,4 @@ To get started, you’ll need to add the domain that you want to send messages f
- 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.
\ No newline at end of file
+- You should now be able to send notifications using Mandrill in Novu.
diff --git a/channels-and-providers/email/maqsam.mdx b/integrations/providers/email/maqsam.mdx
similarity index 81%
rename from channels-and-providers/email/maqsam.mdx
rename to integrations/providers/email/maqsam.mdx
index f5344935..b62dc639 100644
--- a/channels-and-providers/email/maqsam.mdx
+++ b/integrations/providers/email/maqsam.mdx
@@ -1,11 +1,10 @@
---
-title: 'Maqsam'
-description: 'Learn how to use the Maqsam provider to send sms notifications using Novu'
+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.
@@ -13,11 +12,11 @@ Contact `support@maqsam.com` to enable the API feature for your account, then yo
# Creating the Maqsam integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-maqsam) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
\ No newline at end of file
+- You should now be able to send notifications using Maqsam in Novu.
diff --git a/channels-and-providers/email/netcore.mdx b/integrations/providers/email/netcore.mdx
similarity index 88%
rename from channels-and-providers/email/netcore.mdx
rename to integrations/providers/email/netcore.mdx
index 4dab1c45..352953c4 100644
--- a/channels-and-providers/email/netcore.mdx
+++ b/integrations/providers/email/netcore.mdx
@@ -1,6 +1,6 @@
---
-title: 'Netcore'
-description: 'Learn how to use the Netcore provider to send email notifications using Novu'
+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.
@@ -25,7 +25,7 @@ Follow the instructions on this [page](https://emaildocs.netcorecloud.com/docs/
# Creating a Netcore integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-netcore) page on Novu.
+- Visit the [Integrations](https://dashboard.novu.co/integrations?utm_campaign=docs-netcore) page on Novu.
- Click on Add a Provider.
- Select Netcore service.
- Enter your Netcore API Key.
@@ -33,4 +33,4 @@ Follow the instructions on this [page](https://emaildocs.netcorecloud.com/docs/
- 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.
\ No newline at end of file
+- You should now be able to send notifications using Netcore in Novu.
diff --git a/channels-and-providers/email/outlook365.mdx b/integrations/providers/email/outlook365.mdx
similarity index 53%
rename from channels-and-providers/email/outlook365.mdx
rename to integrations/providers/email/outlook365.mdx
index 38962d41..52e5e7a1 100644
--- a/channels-and-providers/email/outlook365.mdx
+++ b/integrations/providers/email/outlook365.mdx
@@ -1,6 +1,6 @@
---
-title: 'Outlook 365'
-description: 'Learn how to use the Outlook 365 provider to send email notifications using Novu'
+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.
@@ -11,15 +11,19 @@ To use the Outlook 365 provider in the email channel, you will need to have the
## Creating the Outlook 365 integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-office365) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
+ - `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.
\ No newline at end of file
+
+ {" "}
+ In order to create outlook integration, turn off multi factor authentication from
+ account security settings.
+
diff --git a/channels-and-providers/email/overview.mdx b/integrations/providers/email/overview.mdx
similarity index 73%
rename from channels-and-providers/email/overview.mdx
rename to integrations/providers/email/overview.mdx
index 90dbd4da..70130abd 100644
--- a/channels-and-providers/email/overview.mdx
+++ b/integrations/providers/email/overview.mdx
@@ -1,13 +1,20 @@
---
-title: 'Email providers'
-description: 'Learn the process of configuring email providers with Novu'
+title: "E-mail Provider Integrations"
+sidebarTitle: "Overview"
+description: "Learn the process of configuring email providers with Novu"
---
import { MissingProvider } from "/snippets/missing-provider.mdx";
Novu can be used to deliver email messages to your customers using a unified delivery API. You can easily integrate your favorite email provider using the built-in integration store.
-
+
## Configuring email providers
@@ -30,22 +37,23 @@ 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'],
- },
- },
+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'],
+},
+},
});
-```
+
+````
@@ -77,15 +85,17 @@ novu.trigger('', {
],
},
});
-```
+````
+
## 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.
+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:-
-If there are 4 active email integrations with these identifiers:-
1. sendgrid-abcdef
2. sendgrid-ghijkl
3. brevo-abcdef
@@ -101,15 +111,16 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
novu.trigger('', {
- to: {
- subscriberId: '',
- },
- overrides: {
- email: {
- integrationIdentifier: "brevo-abcdef"
- },
- },
+to: {
+subscriberId: '',
+},
+overrides: {
+email: {
+integrationIdentifier: "brevo-abcdef"
+},
+},
});
+
```
@@ -118,4 +129,5 @@ novu.trigger('', {
-
\ No newline at end of file
+
+```
diff --git a/channels-and-providers/email/plunk.mdx b/integrations/providers/email/plunk.mdx
similarity index 85%
rename from channels-and-providers/email/plunk.mdx
rename to integrations/providers/email/plunk.mdx
index 92639710..4217e25f 100644
--- a/channels-and-providers/email/plunk.mdx
+++ b/integrations/providers/email/plunk.mdx
@@ -1,6 +1,6 @@
---
-title: 'Plunk'
-description: 'Learn how to use the Plunk provider to send email notifications using Novu'
+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.
@@ -23,11 +23,11 @@ Before you can send emails on a large scale, you will need to authenticate your
## Create a Plunk integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-plunk) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
\ No newline at end of file
+- You should now be able to send notifications using Plunk in Novu.
diff --git a/channels-and-providers/email/postmark.mdx b/integrations/providers/email/postmark.mdx
similarity index 89%
rename from channels-and-providers/email/postmark.mdx
rename to integrations/providers/email/postmark.mdx
index afbb7a65..bbf458c4 100644
--- a/channels-and-providers/email/postmark.mdx
+++ b/integrations/providers/email/postmark.mdx
@@ -1,6 +1,6 @@
---
-title: 'Postmark'
-description: 'Learn how to use the Postmark provider to send email notifications using Novu'
+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.
@@ -25,7 +25,7 @@ Postmark allows the authentication of the sender's identity using one of the fol
# Create a Postmark integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-postmark) page on Novu.
+- Visit the [Integrations](https://dashboard.novu.co/integrations?utm_campaign=docs-postmark) page on Novu.
- Click on Add a Provider.
- Select Postmark service.
- Enter the Postmark API key.
diff --git a/channels-and-providers/email/resend.mdx b/integrations/providers/email/resend.mdx
similarity index 82%
rename from channels-and-providers/email/resend.mdx
rename to integrations/providers/email/resend.mdx
index 3595b2d0..5f5c3c97 100644
--- a/channels-and-providers/email/resend.mdx
+++ b/integrations/providers/email/resend.mdx
@@ -1,6 +1,6 @@
---
-title: 'Resend'
-description: 'Learn how to use the Resend provider to send email notifications using Novu'
+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.
@@ -27,13 +27,13 @@ Resend allows you to authenticate your sender identity using [Domain Authentica
# Creating a Resend integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-resend) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
+ - 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.
\ No newline at end of file
+- You should now be able to send notifications using Resend in Novu.
diff --git a/channels-and-providers/email/sendgrid.mdx b/integrations/providers/email/sendgrid.mdx
similarity index 77%
rename from channels-and-providers/email/sendgrid.mdx
rename to integrations/providers/email/sendgrid.mdx
index 80f919f5..f7eab2fb 100644
--- a/channels-and-providers/email/sendgrid.mdx
+++ b/integrations/providers/email/sendgrid.mdx
@@ -39,7 +39,7 @@ SendGrid allows you to authenticate your sender identity using one of the follow
## SendGrid integration with Novu
-- Visit the [Integrations store](https://web.novu.co/integrations?utm_campaign=docs-sendgrid) on the Novu web dashboard.
+- Visit the [Integrations store](https://dashboard.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.
@@ -62,43 +62,44 @@ 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"
+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
@@ -140,6 +141,7 @@ curl --location 'https://api.novu.co/v1/events/trigger' \
}
}
}'
-```
+````
+
-
\ No newline at end of file
+
diff --git a/channels-and-providers/email/sendinblue.mdx b/integrations/providers/email/sendinblue.mdx
similarity index 72%
rename from channels-and-providers/email/sendinblue.mdx
rename to integrations/providers/email/sendinblue.mdx
index ce0c446a..4ed10ec4 100644
--- a/channels-and-providers/email/sendinblue.mdx
+++ b/integrations/providers/email/sendinblue.mdx
@@ -1,6 +1,6 @@
---
-title: 'Sendinblue'
-description: 'Learn how to use the Sendinblue provider to send email notifications using Novu'
+title: "Sendinblue"
+description: "Learn how to use the Sendinblue provider to send email notifications using Novu"
---
You can use the [Sendinblue](https://www.sendinblue.com/) provider to send transactional emails to your customers using the Novu Platform with a single API.
@@ -24,7 +24,7 @@ Sendinblue allows you to authenticate your sender identity using one of the foll
# Creating a Sendinblue integration with Novu
-- Visit the [Integrations store](https://web.novu.co/integrations?utm_campaign=docs-sendinblue) on the Novu web dashboard.
+- Visit the [Integrations store](https://dashboard.novu.co/integrations?utm_campaign=docs-sendinblue) on the Novu web dashboard.
- Click on Add a Provider.
- Select Sendinblue service.
- Enter your Sendinblue API key.
@@ -47,43 +47,44 @@ 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"
+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
@@ -125,6 +126,7 @@ curl --location 'https://api.novu.co/v1/events/trigger' \
}
}
}'
-```
+````
+
-
\ No newline at end of file
+
diff --git a/channels-and-providers/email/sparkpost.mdx b/integrations/providers/email/sparkpost.mdx
similarity index 70%
rename from channels-and-providers/email/sparkpost.mdx
rename to integrations/providers/email/sparkpost.mdx
index 034429db..28975494 100644
--- a/channels-and-providers/email/sparkpost.mdx
+++ b/integrations/providers/email/sparkpost.mdx
@@ -1,6 +1,6 @@
---
-title: 'Sparkpost'
-description: 'Learn how to use the Sparkpost provider to send email notifications using Novu'
+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.
@@ -14,12 +14,9 @@ To use the SparkPost provider in the email channel, you will need to create a Sp
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/)*
- >
+ > 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.
@@ -33,7 +30,7 @@ SparkPost allows you to authenticate your sender identity using [Sending Domain
# Creating a SparkPost integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sparkpost) page on Novu.
+- Visit the [Integrations](https://dashboard.novu.co/integrations?utm_campaign=docs-sparkpost) page on Novu.
- Click on Add a Provider.
- Select SparkPost service.
- Enter your SparkPost API Key.
@@ -42,4 +39,4 @@ SparkPost allows you to authenticate your sender identity using [Sending Domain
- 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.
\ No newline at end of file
+- You should now be able to send notifications using SparkPost in Novu.
diff --git a/channels-and-providers/email/webhook.mdx b/integrations/providers/email/webhook.mdx
similarity index 68%
rename from channels-and-providers/email/webhook.mdx
rename to integrations/providers/email/webhook.mdx
index 466889eb..bb626f04 100644
--- a/channels-and-providers/email/webhook.mdx
+++ b/integrations/providers/email/webhook.mdx
@@ -1,17 +1,17 @@
---
-title: 'Email Webhook'
-description: 'Learn how to use the Email Webhook provider to send email notifications using Novu'
+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://web.novu.co/settings/email?utm_campaign=docs-webhook) in Settings menu to configure Email Webhook.
+First go to [Email Settings](https://dashboard.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://web.novu.co/integrations?utm_campaign=docs-webhook) page on Novu.
+- Visit the [Integrations](https://dashboard.novu.co/integrations?utm_campaign=docs-webhook) page on Novu.
- Click the "Add a provider" button.
- Select Email Webhook service
- Click `Next`
@@ -20,4 +20,4 @@ First go to [Email Settings](https://web.novu.co/settings/email?utm_campaign=doc
- 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.
\ No newline at end of file
+- You should now be able to send notifications using Email Webhook in Novu.
diff --git a/channels-and-providers/in-app/introduction.mdx b/integrations/providers/in-app/introduction.mdx
similarity index 90%
rename from channels-and-providers/in-app/introduction.mdx
rename to integrations/providers/in-app/introduction.mdx
index 54ad8ed1..e11bd23d 100644
--- a/channels-and-providers/in-app/introduction.mdx
+++ b/integrations/providers/in-app/introduction.mdx
@@ -1,7 +1,9 @@
---
-title: 'Introduction'
-description: 'Learn how to integrate In-App notification center and send In-App notification using Novu'
+title: "Inbox"
+description: "Learn how to integrate In-App notification center and send In-App notification using Novu"
+icon: "bell"
---
+
In-app notifications are messages or alerts that appear within a mobile app or website while a user is actively using it. Unlike push notifications, which can reach users even when they're not actively engaged with an app, in-app notifications are designed to enhance the user experience within the app itself. Here's why they are important:
1. User Engagement: In-app notifications can keep users engaged and informed while they are using your app, providing valuable updates, reminders, or information relevant to their current activity. This can improve user satisfaction and encourage them to spend more time within the app.
@@ -20,14 +22,14 @@ In-app notifications are messages or alerts that appear within a mobile app or w
8. A/B Testing and Optimization: In-app notifications can be A/B tested to determine which messages and designs are most effective in achieving specific goals, such as increasing conversions or user engagement.
-
## In-app notifications using Novu
-
+
Novu provides a pre built component to display in-app notifications for almost all web frameworks. You can use this component to display in-app notifications in your web app. If you don't want to use the pre built component, you can use the headless component to build your own in-app notification center. Read more about notification center [here](/notification-center/introduction).
-
-
-
-
-
diff --git a/integrations/providers/introduction.mdx b/integrations/providers/introduction.mdx
new file mode 100644
index 00000000..048c6b4c
--- /dev/null
+++ b/integrations/providers/introduction.mdx
@@ -0,0 +1,18 @@
+---
+title: "Overview"
+description: "Learn about what channels, providers and oganizations are"
+---
+
+## Channels
+
+Novu lets you send notifications across different communication mediums, including emails, in-app messages, push notifications, SMS, and chat. Each of these five communication mediums is referred to as a notification ‘channel’.
+
+
+ {" "}
+
+
+## Providers
+
+Providers are what allow us to handle message delivery over multiple channels. Of the five notification channels that Novu currently supports, each channel except the ‘in-app’ channel has multiple providers.
+
+The Inbox channel only has one provider (the default Novu provider). All the remaining channels have multiple providers.
diff --git a/channels-and-providers/push/apns.mdx b/integrations/providers/push/apns.mdx
similarity index 76%
rename from channels-and-providers/push/apns.mdx
rename to integrations/providers/push/apns.mdx
index d5d25edd..501bdcfe 100644
--- a/channels-and-providers/push/apns.mdx
+++ b/integrations/providers/push/apns.mdx
@@ -1,7 +1,7 @@
---
-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'
+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.
@@ -27,27 +27,27 @@ You also need the following to connect to APNs:
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:
```jsx
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
-novu.trigger('', {
+novu.trigger("", {
to: {
- subscriberId: '',
+ subscriberId: "",
},
payload: {
- abc: 'def', // If the notification is a data notification, the payload will be sent as the data
+ 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',
+ title: "Test",
+ body: "Test push",
},
data: {
- key: 'value',
+ key: "value",
},
},
},
@@ -57,31 +57,31 @@ novu.trigger('', {
```
```jsx
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
-novu.trigger('', {
+novu.trigger("", {
to: {
- subscriberId: '',
+ subscriberId: "",
},
payload: {
- key1: 'val1',
- key2: 'val2', // If the notification is a data notification, the payload will be sent as the data
+ key1: "val1",
+ key2: "val2", // If the notification is a data notification, the payload will be sent as the data
},
overrides: {
- type: 'data',
+ type: "data",
apns: {
headers: {
- 'apns-priority': '5',
+ "apns-priority": "5",
},
payload: {
aps: {
alert: {
- 'loc-key': 'GAME_PLAY_REQUEST_FORMAT',
- 'loc-args': ['Shelly', 'Rick'],
+ "loc-key": "GAME_PLAY_REQUEST_FORMAT",
+ "loc-args": ["Shelly", "Rick"],
},
- sound: 'demo.wav',
+ sound: "demo.wav",
},
},
},
@@ -102,12 +102,13 @@ import {
const novu = new Novu("");
await novu.subscribers.setCredentials('subscriberId', PushProviderIdEnum.APNS, {
- deviceTokens: ['token1', 'token2'],
+deviceTokens: ['token1', 'token2'],
});
-```
+
+````
-```bash
+```bash
curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
@@ -117,8 +118,9 @@ curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials'
"deviceTokens": ["token1", "token2"],
"integrationIdentifier": "apns-MnGLxp8uy"
}'
-```
+````
+
-Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
\ No newline at end of file
+Checkout the [API reference](/api-reference/subscribers/update-subscriber-credentials) for more details.
diff --git a/channels-and-providers/push/expo-push.mdx b/integrations/providers/push/expo-push.mdx
similarity index 82%
rename from channels-and-providers/push/expo-push.mdx
rename to integrations/providers/push/expo-push.mdx
index a5536d80..e7aebd33 100644
--- a/channels-and-providers/push/expo-push.mdx
+++ b/integrations/providers/push/expo-push.mdx
@@ -1,6 +1,6 @@
---
-title: 'Expo Push'
-description: 'Learn how to use the Expo push provider to send push notifications using Novu'
+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.
@@ -10,16 +10,16 @@ To enable Expo Push integration, you need to create an [Expo Application Servic
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:
```jsx
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
-novu.trigger('', {
+novu.trigger("", {
to: {
- subscriberId: '',
+ subscriberId: "",
},
payload: {
- abc: 'def',
+ abc: "def",
},
});
```
@@ -36,12 +36,13 @@ import {
const novu = new Novu("");
await novu.subscribers.setCredentials('subscriberId', PushProviderIdEnum.EXPO, {
- deviceTokens: ['token1', 'token2'],
+deviceTokens: ['token1', 'token2'],
});
-```
+
+````
-```bash
+```bash
curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
@@ -51,7 +52,8 @@ curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials'
"deviceTokens": ["token1", "token2"],
"integrationIdentifier": "expo-MnGLxp8uy"
}'
-```
+````
+
diff --git a/channels-and-providers/push/fcm.mdx b/integrations/providers/push/fcm.mdx
similarity index 98%
rename from channels-and-providers/push/fcm.mdx
rename to integrations/providers/push/fcm.mdx
index a81b1fc7..2b2c6c10 100644
--- a/channels-and-providers/push/fcm.mdx
+++ b/integrations/providers/push/fcm.mdx
@@ -63,12 +63,13 @@ import {
const novu = new Novu("");
await novu.subscribers.setCredentials(
- 'subscriberId',
- PushProviderIdEnum.FCM,
- { deviceTokens: ['token1', 'token2'] },
- 'fcm-MnGLxp8uy'
+'subscriberId',
+PushProviderIdEnum.FCM,
+{ deviceTokens: ['token1', 'token2'] },
+'fcm-MnGLxp8uy'
);
-```
+
+````
@@ -81,13 +82,14 @@ curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials'
"providerId": "fcm",
"credentials": {
"deviceTokens" : [
- "token1",
+ "token1",
"token2"
]
},
"integrationIdentifier": "fcm-MnGLxp8uy"
}'
-```
+````
+
@@ -192,7 +194,8 @@ novu.trigger("", {
-## FCM Cost
+## 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
diff --git a/channels-and-providers/push/onesignal.mdx b/integrations/providers/push/onesignal.mdx
similarity index 84%
rename from channels-and-providers/push/onesignal.mdx
rename to integrations/providers/push/onesignal.mdx
index bab6199a..ab9da6ec 100644
--- a/channels-and-providers/push/onesignal.mdx
+++ b/integrations/providers/push/onesignal.mdx
@@ -1,6 +1,6 @@
---
-title: 'Onesignal'
-description: 'Learn how to use the Onesignal provider to send push notifications using Novu'
+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).
@@ -28,13 +28,14 @@ import {
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'],
+// Your user's unique 'player_id' from OneSignal
+deviceTokens: ['ad0452ca-3ca7-43b5-bf9b-fa93fd322035'],
});
-```
+
+````
-```bash
+```bash
curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
@@ -44,7 +45,8 @@ curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials'
"deviceTokens": ["ad0452ca-3ca7-43b5-bf9b-fa93fd322035"],
"integrationIdentifier": "one-signal-MnGLxp8uy"
}'
-```
+````
+
@@ -53,18 +55,18 @@ Checkout the [API reference](/api-reference/subscribers/update-subscriber-creden
# SDK Trigger Example
```jsx
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
-novu.trigger('', {
+novu.trigger("", {
to: {
- subscriberId: '',
+ subscriberId: "",
},
payload: {
- abc: 'def', // If the notification is a data notification, the payload will be sent as the data
+ abc: "def", // If the notification is a data notification, the payload will be sent as the data
},
});
```
-Device/notification identifiers can be set by using [setCredentials](https://docs.novu.co/channels/email/resend/#set-device-token) or by using the `deviceIdentifiers` field in overrides.
\ No newline at end of file
+Device/notification identifiers can be set by using [setCredentials](https://docs.novu.co/channels/email/resend/#set-device-token) or by using the `deviceIdentifiers` field in overrides.
diff --git a/channels-and-providers/push/overview.mdx b/integrations/providers/push/overview.mdx
similarity index 89%
rename from channels-and-providers/push/overview.mdx
rename to integrations/providers/push/overview.mdx
index 1ace71a3..00066cd4 100644
--- a/channels-and-providers/push/overview.mdx
+++ b/integrations/providers/push/overview.mdx
@@ -35,7 +35,7 @@ To send a push notification to subscribers (users) using Novu:
Novu supports multiple active providers for push channel.
-
+
## Managing push device tokens
@@ -43,6 +43,7 @@ To send a push notification to subscribers (users) using Novu:
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.
@@ -51,14 +52,14 @@ Novu offers to ways of keeping your device tokens in sync with subscriber profil
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', {
+novu.trigger("workflow-id", {
to: {
- subscriberId: 'subscriber-id',
+ subscriberId: "subscriber-id",
channels: [
{
- providerId: 'fcm',
+ providerId: "fcm",
credentials: {
- deviceTokens: ['token-1', 'token-2'],
+ deviceTokens: ["token-1", "token-2"],
},
},
],
@@ -89,29 +90,31 @@ 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,
+// \_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: [] },
+'subscriberId',
+PushProviderIdEnum.FCM,
+{ deviceTokens: [] },
);
// remove the token you want to remove
const newDeviceTokens = currentDeviceTokens.filter(
- (token) => token !== 'token-to-be-removed',
+(token) => token !== 'token-to-be-removed',
);
// update subscriber credentials with new device tokens
await this.novu.subscribers.setCredentials(
- 'subscriberId',
- PushProviderIdEnum.FCM,
- { deviceTokens: newDeviceTokens },
+'subscriberId',
+PushProviderIdEnum.FCM,
+{ deviceTokens: newDeviceTokens },
);
+
```
+```
diff --git a/channels-and-providers/push/push-webhook.mdx b/integrations/providers/push/push-webhook.mdx
similarity index 89%
rename from channels-and-providers/push/push-webhook.mdx
rename to integrations/providers/push/push-webhook.mdx
index 2851235b..0805615b 100644
--- a/channels-and-providers/push/push-webhook.mdx
+++ b/integrations/providers/push/push-webhook.mdx
@@ -8,7 +8,7 @@ Users can use their own api url as webhook url and novu will make a post request
## Steps To Configure
-1. Go to [integration store](https://web.novu.co/integrations?utm_campaign=docs-push-webhook) and click on `Add a provider` button. Choose `Push` channel and then `Push Webhook` provider.
+1. Go to [integration store](https://dashboard.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.
@@ -32,12 +32,13 @@ const novu = new Novu("");
// PushProviderIdEnum.PushWebhook = push-webhook
await novu.subscribers.setCredentials('subscriberId', PushProviderIdEnum.PushWebhook, {
- deviceTokens: ['ANY_RANDOM_STRING'],
+deviceTokens: ['ANY_RANDOM_STRING'],
});
-```
+
+````
-```bash
+```bash
curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
@@ -47,24 +48,23 @@ curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials'
"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
+## Example paylod sent by novu to webhook url
```json
{
- "target": [
- "subscriber-token-for-push-webhook-provider"
- ],
+ "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",
+ "custom_message": "this is custom message from payload push webhook demo"
}
},
"payload": {
@@ -83,9 +83,7 @@ Checkout the [API reference](/api-reference/subscribers/update-subscriber-creden
"channels": [
{
"credentials": {
- "deviceTokens": [
- "subscriber-token-for-push-webhook-provider"
- ]
+ "deviceTokens": ["subscriber-token-for-push-webhook-provider"]
},
"_integrationId": "integrationId",
"providerId": "push-webhook"
diff --git a/channels-and-providers/push/pusher-beams.mdx b/integrations/providers/push/pusher-beams.mdx
similarity index 84%
rename from channels-and-providers/push/pusher-beams.mdx
rename to integrations/providers/push/pusher-beams.mdx
index 257ff653..a8e08541 100644
--- a/channels-and-providers/push/pusher-beams.mdx
+++ b/integrations/providers/push/pusher-beams.mdx
@@ -1,6 +1,6 @@
---
-title: 'Pusher Beams'
-description: 'Learn how to use the Pusher Beams provider to send push notifications using Novu'
+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.
@@ -28,13 +28,14 @@ import {
const novu = new Novu("");
await novu.subscribers.setCredentials('subscriberId', PushProviderIdEnum.PusherBeams, {
- // Your user's unique 'userId' from Pusher Beams
- deviceTokens: ['userId-from-pusher-beams'],
+// Your user's unique 'userId' from Pusher Beams
+deviceTokens: ['userId-from-pusher-beams'],
});
-```
+
+````
-```bash
+```bash
curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
@@ -44,7 +45,8 @@ curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials'
"deviceTokens": ['userId-from-pusher-beams'],
"integrationIdentifier": "pusher-beams-MnGLxp8uy"
}'
-```
+````
+
@@ -53,16 +55,16 @@ Checkout the [API reference](/api-reference/subscribers/update-subscriber-creden
# SDK Trigger Example
```jsx
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
-novu.trigger('', {
+novu.trigger("", {
to: {
- subscriberId: '',
+ subscriberId: "",
},
payload: {
- custom_data: 'custom_data', // the payload will be sent as notification data object. Cannot contain the key “pusher”
+ custom_data: "custom_data", // the payload will be sent as notification data object. Cannot contain the key “pusher”
},
});
-```
\ No newline at end of file
+```
diff --git a/channels-and-providers/push/pushpad.mdx b/integrations/providers/push/pushpad.mdx
similarity index 87%
rename from channels-and-providers/push/pushpad.mdx
rename to integrations/providers/push/pushpad.mdx
index c0771cd7..96ed2932 100644
--- a/channels-and-providers/push/pushpad.mdx
+++ b/integrations/providers/push/pushpad.mdx
@@ -1,6 +1,6 @@
---
-title: 'Pushpad'
-description: 'Learn how to use the Pushpad provider to send web push notifications using Novu'
+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.
@@ -28,13 +28,14 @@ import {
const novu = new Novu("");
await novu.subscribers.setCredentials('subscriberId', PushProviderIdEnum.Pushpad, {
- // the user ID (uid) that you used for Pushpad
- deviceTokens: ['user123'],
+// the user ID (uid) that you used for Pushpad
+deviceTokens: ['user123'],
});
-```
+
+````
-```bash
+```bash
curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
@@ -44,7 +45,8 @@ curl -L -X PUT 'https://api.novu.co/v1/subscribers//credentials'
"deviceTokens": ['user123'],
"integrationIdentifier": "pushpad-MnGLxp8uy"
}'
-```
+````
+
@@ -53,15 +55,15 @@ Checkout the [API reference](/api-reference/subscribers/update-subscriber-creden
# SDK Trigger Example
```jsx
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
const novu = new Novu("");
-novu.trigger('', {
+novu.trigger("", {
to: {
- subscriberId: '',
+ subscriberId: "",
},
- payload: {}
+ payload: {},
});
```
diff --git a/channels-and-providers/sms/46elks.mdx b/integrations/providers/sms/46elks.mdx
similarity index 71%
rename from channels-and-providers/sms/46elks.mdx
rename to integrations/providers/sms/46elks.mdx
index 0dc0655a..a0b458a5 100644
--- a/channels-and-providers/sms/46elks.mdx
+++ b/integrations/providers/sms/46elks.mdx
@@ -1,6 +1,6 @@
---
-title: '46elks'
-description: 'Learn how to use the 46elks provider to send sms notifications using Novu'
+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.
@@ -11,11 +11,11 @@ To use the 46elks provider in the sms channel, you will need to create a 46elks
# Creating the 46elks integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-46elks) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
\ No newline at end of file
+- You should now be able to send SMS, MMS, using 46elks in Novu.
diff --git a/channels-and-providers/sms/africas-talking.mdx b/integrations/providers/sms/africas-talking.mdx
similarity index 57%
rename from channels-and-providers/sms/africas-talking.mdx
rename to integrations/providers/sms/africas-talking.mdx
index 6dfe7365..d51683f2 100644
--- a/channels-and-providers/sms/africas-talking.mdx
+++ b/integrations/providers/sms/africas-talking.mdx
@@ -5,7 +5,6 @@ description: "Learn how to use the Africa's Talking provider to send sms notific
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.
@@ -16,30 +15,41 @@ You’ll need to create an application to create a username in Africa’s Talkin
- [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.
-
+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.
+
+ {" "}
+
+- 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.
+ Once you've generated your API Key, wait about 3 minutes before testing it.
## Getting your Sender's ID
@@ -49,25 +59,33 @@ Sender IDs allow you to brand your messages as you send them to your customers.
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.
-
-
+ 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
-
+ 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://web.novu.co/integrations?utm_campaign=docs-africastalking) page on Novu.
+- Visit the [Integrations](https://dashboard.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`.
@@ -76,4 +94,4 @@ On the page that appears, fill in the form and submit
- 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.
\ No newline at end of file
+Now it is possible to send SMS notifications using Africa's Talking in Novu.
diff --git a/channels-and-providers/sms/aws-sns.mdx b/integrations/providers/sms/aws-sns.mdx
similarity index 82%
rename from channels-and-providers/sms/aws-sns.mdx
rename to integrations/providers/sms/aws-sns.mdx
index 68f57d1e..fa4e6aaf 100644
--- a/channels-and-providers/sms/aws-sns.mdx
+++ b/integrations/providers/sms/aws-sns.mdx
@@ -1,6 +1,6 @@
---
-title: 'AWS SNS'
-description: 'Learn how to use the AWS SNS provider to send sms notifications using Novu'
+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.
@@ -21,10 +21,10 @@ For security reasons, it is suggested that you create a new User to use with Nov
# Create an AWS SNS integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-sns) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
\ No newline at end of file
+- You should now be able to send SMS notifications using **Amazon SNS** in Novu.
diff --git a/channels-and-providers/sms/azure.mdx b/integrations/providers/sms/azure.mdx
similarity index 80%
rename from channels-and-providers/sms/azure.mdx
rename to integrations/providers/sms/azure.mdx
index 0611850e..360dbf42 100644
--- a/channels-and-providers/sms/azure.mdx
+++ b/integrations/providers/sms/azure.mdx
@@ -1,6 +1,6 @@
---
-title: 'Azure SMS'
-description: 'Learn how to use the Azure SMS provider to send sms notifications using Novu'
+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.
@@ -11,7 +11,7 @@ To use Azure SMS provider in the SMS channel, the first step is to create an Azu
# Creating a Azure SMS integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-azure) page on Novu.
+- Visit the [Integrations](https://dashboard.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).
@@ -21,4 +21,4 @@ To use Azure SMS provider in the SMS channel, the first step is to create an Azu
- Enter the `From` value.
- Click on the **Update** button.
-Now it is possible to send SMS notifications using **Azure Sms** in Novu.
\ No newline at end of file
+Now it is possible to send SMS notifications using **Azure Sms** in Novu.
diff --git a/channels-and-providers/sms/bulk-sms.mdx b/integrations/providers/sms/bulk-sms.mdx
similarity index 78%
rename from channels-and-providers/sms/bulk-sms.mdx
rename to integrations/providers/sms/bulk-sms.mdx
index 191160c1..61d8722f 100644
--- a/channels-and-providers/sms/bulk-sms.mdx
+++ b/integrations/providers/sms/bulk-sms.mdx
@@ -1,6 +1,6 @@
---
-title: 'BulkSMS'
-description: 'Learn how to use the BulkSMS provider to send sms notifications using Novu'
+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.
@@ -11,7 +11,7 @@ To use BulkSMS provider in the SMS channel, the first step is to create a BulkSM
# Creating a BulkSMS integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-bulksms) page on Novu.
+- Visit the [Integrations](https://dashboard.novu.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).
@@ -20,4 +20,4 @@ To use BulkSMS provider in the SMS channel, the first step is to create a BulkSM
- Enter the `API Token`.
- Click on the **Update** button.
-Now it is possible to send SMS notifications using **BulkSMS** in Novu.
\ No newline at end of file
+Now it is possible to send SMS notifications using **BulkSMS** in Novu.
diff --git a/channels-and-providers/sms/burst-sms.mdx b/integrations/providers/sms/burst-sms.mdx
similarity index 82%
rename from channels-and-providers/sms/burst-sms.mdx
rename to integrations/providers/sms/burst-sms.mdx
index 7a20793d..00472210 100644
--- a/channels-and-providers/sms/burst-sms.mdx
+++ b/integrations/providers/sms/burst-sms.mdx
@@ -1,6 +1,6 @@
---
-title: 'BurstSMS'
-description: 'Learn how to use the BurstSMS provider to send sms notifications using Novu'
+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.
@@ -15,11 +15,11 @@ To find the BurstSMS API and Secret key, log into the personal BurstSMS account
# Creating a BurstSMS integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-burstsms) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
\ No newline at end of file
+- Now it is possible to send SMS notifications using **BurstSMS** in Novu.
diff --git a/channels-and-providers/sms/clickatell.mdx b/integrations/providers/sms/clickatell.mdx
similarity index 51%
rename from channels-and-providers/sms/clickatell.mdx
rename to integrations/providers/sms/clickatell.mdx
index df9ceeca..74d8b62b 100644
--- a/channels-and-providers/sms/clickatell.mdx
+++ b/integrations/providers/sms/clickatell.mdx
@@ -1,6 +1,6 @@
---
-title: 'Clickatell'
-description: 'Learn how to use the Clickatell provider to send sms notifications using Novu'
+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.
@@ -8,7 +8,7 @@ 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://web.novu.co/integrations?utm_campaign=docs-sms-clickatell).
+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.novu.co/integrations?utm_campaign=docs-sms-clickatell).
## Retrieving your API Key
@@ -16,26 +16,43 @@ 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://web.novu.co/integrations?utm_campaign=docs-sms-clickatell) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
diff --git a/channels-and-providers/sms/clicksend.mdx b/integrations/providers/sms/clicksend.mdx
similarity index 83%
rename from channels-and-providers/sms/clicksend.mdx
rename to integrations/providers/sms/clicksend.mdx
index 2a93bcff..75553157 100644
--- a/channels-and-providers/sms/clicksend.mdx
+++ b/integrations/providers/sms/clicksend.mdx
@@ -1,6 +1,6 @@
---
-title: 'Clicksend'
-description: 'Learn how to use the Clicsend provider to send sms notifications using Novu'
+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.
@@ -8,7 +8,7 @@ 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://web.novu.co/integrations?utm_campaign=docs-sms-clicksend).
+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.novu.co/integrations?utm_campaign=docs-sms-clicksend).
# Retrieving your API Key
@@ -18,7 +18,7 @@ To use the [Clicksend](https://www.clicksend.com/in/) provider in the SMS channe
# Create a Clicksend integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-clicksend) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
diff --git a/channels-and-providers/sms/firetext.mdx b/integrations/providers/sms/firetext.mdx
similarity index 63%
rename from channels-and-providers/sms/firetext.mdx
rename to integrations/providers/sms/firetext.mdx
index bfaa5eb1..9b151ec3 100644
--- a/channels-and-providers/sms/firetext.mdx
+++ b/integrations/providers/sms/firetext.mdx
@@ -1,6 +1,6 @@
---
-title: 'Firetext'
-description: 'Learn how to use the firetext provider to send sms notifications using Novu'
+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.
@@ -8,8 +8,8 @@ You can use the [firetext](https://www.firetext.co.uk) provider to send SMS me
## 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.
+- Note : Firetext is only available in uk region. Others may require additional verification.
## Retrieving your API Key
@@ -17,18 +17,25 @@ 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`.
-
+
+ {" "}
+
+- On the API Keys page, copy the `API key`.
+
+ {" "}
+
## Create a firetext integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-firetxt) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
diff --git a/channels-and-providers/sms/gupshup.mdx b/integrations/providers/sms/gupshup.mdx
similarity index 82%
rename from channels-and-providers/sms/gupshup.mdx
rename to integrations/providers/sms/gupshup.mdx
index 77909c2f..5a6612ff 100644
--- a/channels-and-providers/sms/gupshup.mdx
+++ b/integrations/providers/sms/gupshup.mdx
@@ -1,6 +1,6 @@
---
-title: 'gupshup'
-description: 'Learn how to use the gupshup provider to send sms notifications using Novu'
+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.
@@ -16,7 +16,7 @@ To use the gupshup provider in the SMS channel, the first step is to create a gu
# Creating a gupshup integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-gupshup) page on Novu.
+- Visit the [Integrations](https://dashboard.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`.
diff --git a/channels-and-providers/sms/infobip.mdx b/integrations/providers/sms/infobip.mdx
similarity index 67%
rename from channels-and-providers/sms/infobip.mdx
rename to integrations/providers/sms/infobip.mdx
index 78fd8960..8ae2e03a 100644
--- a/channels-and-providers/sms/infobip.mdx
+++ b/integrations/providers/sms/infobip.mdx
@@ -1,6 +1,6 @@
---
-title: 'Infobip - SMS'
-description: 'Learn how to use the Infobip provider to send sms notifications using Novu'
+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.
@@ -16,30 +16,38 @@ 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://web.novu.co/integrations?utm_campaign=docs-sms-infobip) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
@@ -48,4 +56,4 @@ To see your base URL, log in to the account. Once logged in, on the Homepage, yo
- 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.
\ No newline at end of file
+You should now be able to send SMS notifications using Infobip in Novu.
diff --git a/channels-and-providers/sms/kannel.mdx b/integrations/providers/sms/kannel.mdx
similarity index 75%
rename from channels-and-providers/sms/kannel.mdx
rename to integrations/providers/sms/kannel.mdx
index 1b91c624..1f907863 100644
--- a/channels-and-providers/sms/kannel.mdx
+++ b/integrations/providers/sms/kannel.mdx
@@ -1,16 +1,16 @@
---
-title: 'Kannel'
-description: 'Learn how to use the Kannel sms provider to send sms notifications using Novu'
+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-
+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
@@ -23,31 +23,34 @@ Before integrating Kannel with Novu, you should have Kannel set up and configure
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
+
+ ```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.
+
+ ```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:
+After setting up your Kannel, follow these steps to integrate with novu:
-- Visit the [Integrations Store](https://web.novu.co/integrations?utm_campaign=docs-sms-kannel) on Novu.
+- Visit the [Integrations Store](https://dashboard.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.
@@ -57,24 +60,20 @@ Before integrating Kannel with Novu, you should have Kannel set up and configure
- **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.
+ ```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/channels-and-providers/sms/messagebird.mdx b/integrations/providers/sms/messagebird.mdx
similarity index 80%
rename from channels-and-providers/sms/messagebird.mdx
rename to integrations/providers/sms/messagebird.mdx
index 4008d21d..72b506b8 100644
--- a/channels-and-providers/sms/messagebird.mdx
+++ b/integrations/providers/sms/messagebird.mdx
@@ -1,6 +1,6 @@
---
-title: 'MessageBird'
-description: 'Learn how to use the messagebird provider to send sms notifications using Novu'
+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.
@@ -11,7 +11,7 @@ To use the MessageBird provider in the SMS channel, the first step is to create
# Creating a MessageBird integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-messagebird) page on Novu.
+- Visit the [Integrations](https://dashboard.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).
@@ -20,4 +20,4 @@ To use the MessageBird provider in the SMS channel, the first step is to create
- Enter the `From` value.
- Click on the **Update** button.
-Now it is possible to send SMS notifications using **MessageBird** in Novu.
\ No newline at end of file
+Now it is possible to send SMS notifications using **MessageBird** in Novu.
diff --git a/channels-and-providers/sms/nexmo.mdx b/integrations/providers/sms/nexmo.mdx
similarity index 82%
rename from channels-and-providers/sms/nexmo.mdx
rename to integrations/providers/sms/nexmo.mdx
index 9d0a55ef..850e1519 100644
--- a/channels-and-providers/sms/nexmo.mdx
+++ b/integrations/providers/sms/nexmo.mdx
@@ -1,6 +1,6 @@
---
-title: 'Nexmo'
-description: 'Learn how to use the Nexmo provider to send sms notifications using Novu'
+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.
@@ -15,11 +15,11 @@ First, [sign up for a Vonage account](https://ui.idp.vonage.com/ui/auth/login)
# Create a Nexmo integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-nexmo) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
\ No newline at end of file
+- Now it is possible to send SMS notifications using **Nexmo** in Novu.
diff --git a/channels-and-providers/sms/overview.mdx b/integrations/providers/sms/overview.mdx
similarity index 90%
rename from channels-and-providers/sms/overview.mdx
rename to integrations/providers/sms/overview.mdx
index 9c3e535f..ff9cedd2 100644
--- a/channels-and-providers/sms/overview.mdx
+++ b/integrations/providers/sms/overview.mdx
@@ -3,11 +3,18 @@ title: "SMS Channel Overview"
sidebarTitle: "Overview"
description: "Learn the process of configuring and using sms providers with Novu"
---
+
import { MissingProvider } from "/snippets/missing-provider.mdx";
Novu can be used to deliver sms messages to your customers using a unified delivery API. You can easily integrate your favorite sms provider using the built-in integration store.
-
+
## Configuring SMS providers
@@ -66,15 +73,16 @@ import { Novu } from '@novu/node';
const novu = new Novu('');
novu.trigger('', {
- to: {
- subscriberId: '',
- },
- overrides: {
- sms: {
- integrationIdentifier: "infobip-abcdef"
- },
- },
+to: {
+subscriberId: '',
+},
+overrides: {
+sms: {
+integrationIdentifier: "infobip-abcdef"
+},
+},
});
+
```
@@ -90,4 +98,5 @@ Common errors and reason for these errors while sending sms messages using Novu.
-
\ No newline at end of file
+
+```
diff --git a/channels-and-providers/sms/plivo.mdx b/integrations/providers/sms/plivo.mdx
similarity index 83%
rename from channels-and-providers/sms/plivo.mdx
rename to integrations/providers/sms/plivo.mdx
index 71ad083a..f7b5783d 100644
--- a/channels-and-providers/sms/plivo.mdx
+++ b/integrations/providers/sms/plivo.mdx
@@ -1,6 +1,6 @@
---
-title: 'Plivo'
-description: 'Learn how to use the Plivo provider to send sms notifications using Novu'
+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.
@@ -15,7 +15,7 @@ To use the Plivo provider in the SMS channel, the first step is to create a Pliv
# Creating a Plivo integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-plivo) page on Novu.
+- Visit the [Integrations](https://dashboard.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`.
@@ -24,4 +24,4 @@ To use the Plivo provider in the SMS channel, the first step is to create a Pliv
- 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.
\ No newline at end of file
+Now it is possible to send SMS notifications using **Plivo** in Novu.
diff --git a/channels-and-providers/sms/sendchamp.mdx b/integrations/providers/sms/sendchamp.mdx
similarity index 62%
rename from channels-and-providers/sms/sendchamp.mdx
rename to integrations/providers/sms/sendchamp.mdx
index c1edd0c7..2fbab74c 100644
--- a/channels-and-providers/sms/sendchamp.mdx
+++ b/integrations/providers/sms/sendchamp.mdx
@@ -1,6 +1,6 @@
---
-title: 'Sendchamp'
-description: 'Learn how to use the Sendchamp provider to send sms notifications using Novu'
+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.
@@ -15,14 +15,21 @@ 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.
+
+
+ {" "}
+
+ 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
@@ -32,19 +39,24 @@ 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:
+
+
+ {" "}
+
+ 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://web.novu.co/integrations?utm_campaign=docs-sms-sendchamp) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
@@ -52,4 +64,4 @@ Once it is approved, you can use your Sender ID as the from field on the Novu
- 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.
\ No newline at end of file
+Now it is possible to send SMS notifications using **Sendchamp** in Novu.
diff --git a/channels-and-providers/sms/simpletexting.mdx b/integrations/providers/sms/simpletexting.mdx
similarity index 76%
rename from channels-and-providers/sms/simpletexting.mdx
rename to integrations/providers/sms/simpletexting.mdx
index 6875c9ba..49ba86f7 100644
--- a/channels-and-providers/sms/simpletexting.mdx
+++ b/integrations/providers/sms/simpletexting.mdx
@@ -1,6 +1,6 @@
---
-title: 'SimpleTexting'
-description: 'Learn how to use the SimpleTexting provider to send sms notifications using Novu'
+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.
@@ -11,7 +11,7 @@ To use SimpleTexting provider in the SMS channel, the first step is to create a
# Creating a SimpleTexting integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-simpletexting) page on Novu.
+- Visit the [Integrations](https://dashboard.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).
@@ -21,4 +21,4 @@ To use SimpleTexting provider in the SMS channel, the first step is to create a
- Enter the `From` value.
- Click on the **Update** button.
-Now it is possible to send SMS notifications using **SimpleTexting** in Novu.
\ No newline at end of file
+Now it is possible to send SMS notifications using **SimpleTexting** in Novu.
diff --git a/channels-and-providers/sms/sms-central.mdx b/integrations/providers/sms/sms-central.mdx
similarity index 78%
rename from channels-and-providers/sms/sms-central.mdx
rename to integrations/providers/sms/sms-central.mdx
index 1a324e95..719be3d8 100644
--- a/channels-and-providers/sms/sms-central.mdx
+++ b/integrations/providers/sms/sms-central.mdx
@@ -1,25 +1,23 @@
---
-title: 'SMS Central'
-description: 'Learn how to use the SMS Central provider to send sms notifications using Novu'
+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://web.novu.co/integrations?utm_campaign=docs-sms-smscentral) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
+- 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.
\ No newline at end of file
+- You should now be able to send notifications using SMS Central in Novu.
diff --git a/channels-and-providers/sms/sms77.mdx b/integrations/providers/sms/sms77.mdx
similarity index 81%
rename from channels-and-providers/sms/sms77.mdx
rename to integrations/providers/sms/sms77.mdx
index 8aaaa3fe..386dba88 100644
--- a/channels-and-providers/sms/sms77.mdx
+++ b/integrations/providers/sms/sms77.mdx
@@ -1,6 +1,6 @@
---
-title: 'SMS77'
-description: 'Learn how to use the SMS77 provider to send sms notifications using Novu'
+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.
@@ -15,10 +15,10 @@ To find the SMS77 API key, log into the personal SMS77 account and navigate to t
# Creating an SMS77 integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-sms77) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
\ No newline at end of file
+- Now it is possible to send SMS notifications using **SMS77** in Novu.
diff --git a/channels-and-providers/sms/sns.mdx b/integrations/providers/sms/sns.mdx
similarity index 88%
rename from channels-and-providers/sms/sns.mdx
rename to integrations/providers/sms/sns.mdx
index cf1646a5..12f3ffb7 100644
--- a/channels-and-providers/sms/sns.mdx
+++ b/integrations/providers/sms/sns.mdx
@@ -1,6 +1,6 @@
---
-title: 'SNS'
-description: 'Learn how to use the SNS provider to send sms notifications using Novu'
+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.
@@ -16,10 +16,10 @@ Before you can use SNS as your SMS provider in the Novu platform, you'll need to
# Create an SNS integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations?utm_campaign=docs-sms-sns) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
\ No newline at end of file
+- You should now be able to send SMS notifications using **SNS** in Novu.
diff --git a/channels-and-providers/sms/telnyx.mdx b/integrations/providers/sms/telnyx.mdx
similarity index 90%
rename from channels-and-providers/sms/telnyx.mdx
rename to integrations/providers/sms/telnyx.mdx
index a562052d..d74ce65e 100644
--- a/channels-and-providers/sms/telnyx.mdx
+++ b/integrations/providers/sms/telnyx.mdx
@@ -1,6 +1,6 @@
---
-title: 'Telnyx'
-description: 'Learn how to use the Telnyx provider to send sms notifications using Novu'
+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.
@@ -36,7 +36,7 @@ A valid from address must be a valid phone number in +E.164 format, a short code
# Creating a Telnyx integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations) page on the Novu.
+- Visit the [Integrations](https://dashboard.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.
@@ -44,4 +44,4 @@ A valid from address must be a valid phone number in +E.164 format, a short code
- 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.
\ No newline at end of file
+- You should now be able to send notifications using Telnyx in Novu.
diff --git a/channels-and-providers/sms/termii.mdx b/integrations/providers/sms/termii.mdx
similarity index 70%
rename from channels-and-providers/sms/termii.mdx
rename to integrations/providers/sms/termii.mdx
index 96eb4953..c6523dae 100644
--- a/channels-and-providers/sms/termii.mdx
+++ b/integrations/providers/sms/termii.mdx
@@ -1,6 +1,6 @@
---
-title: 'Termii'
-description: 'Learn how to use the Termii provider to send sms notifications using Novu'
+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.
@@ -16,12 +16,17 @@ 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.
+
+
+ {" "}
+
+ 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
@@ -32,7 +37,9 @@ 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:
@@ -40,11 +47,13 @@ If you have not created one yet:
- Fill in the form
- Click on `Save`
-
+
+ {" "}
+
## Creating a Termii integration with Novu
-- Visit the [Integrations](https://web.novu.co/integrations) page on Novu.
+- Visit the [Integrations](https://dashboard.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.
@@ -52,4 +61,4 @@ If you have not created one yet:
- 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.
\ No newline at end of file
+Now it is possible to send SMS notifications using **Termii** in Novu.
diff --git a/channels-and-providers/sms/twilio.mdx b/integrations/providers/sms/twilio.mdx
similarity index 84%
rename from channels-and-providers/sms/twilio.mdx
rename to integrations/providers/sms/twilio.mdx
index 4a9a4268..2978dfdb 100644
--- a/channels-and-providers/sms/twilio.mdx
+++ b/integrations/providers/sms/twilio.mdx
@@ -1,6 +1,6 @@
---
-title: 'Twilio'
-description: 'Learn how to use the Twilio provider to send sms notifications using Novu'
+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:
@@ -21,15 +21,15 @@ 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.
+ - 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://web.novu.co/integrations) on Novu.
+- Visit the [Integrations Store](https://dashboard.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.
@@ -43,14 +43,12 @@ Creating a Twilio integration with Novu is quite simple. Just follow these steps
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'
- },
- }
-);
+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/schema/zod.mdx b/integrations/schema/zod.mdx
new file mode 100644
index 00000000..d51685be
--- /dev/null
+++ b/integrations/schema/zod.mdx
@@ -0,0 +1,54 @@
+---
+title: "Integrate Zod with your notification workflows"
+sidebarTitle: "Zod"
+---
+
+Novu Framework allows you to use [Zod](https://zod.dev/) to define the [Control](/concepts/controls) and [Payload](/concepts/payload) schemas for your workflows.
+
+## Add Zod to your project
+
+
+
+ ```bash
+ npm install zod zod-to-json-schema
+ ```
+
+ Novu requires the `zod-to-json-schema` package to generate JSON schemas from your Zod definitions.
+
+
+ After installation, the Zod schemas can be used interchangeably with the `controlSchema` and `payloadSchema` options in your workflow definitions.
+
+ ```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: 'Hello, World!',
+ };
+ },
+ {
+ controlSchema: z.object({
+ subject: z.string().default('A test subject'),
+ }),
+ });
+ }, {
+ payloadSchema: z.object({
+ userName: z.string(),
+ }),
+ });
+ ```
+
+
+
+
+## Controls and Payload UI
+
+When you define a `controlSchema` for a step, Novu will automatically generate a UI for the controls in the workflow editor.
+
+- **Form Input Title** - Will be derived from the key of the Zod schema. Unfortunately Zod does not support custom titles at this point.
+- **Form Input Type** - Will be derived from the Zod schema type, with support for `string`, `number`, `boolean`, and `enum` and `array` types.
+- **Default Value** - Will be derived from the Zod schema default value.
+- **Validation** - Will be derived from the Zod schema validation rules, including `min`, `max`, `email`, `url`, `regex` and etc...
diff --git a/introduction.mdx b/introduction.mdx
index 27f9d09b..308879d5 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.
+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...`.
+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.
@@ -102,8 +158,9 @@ Let's import the "FirebaseCore" dependency by adding `import FirebaseCore` to th
Then, we will copy `firebaseapp.configure()` and place it in `didFinishLaunchingWithOptions` method.
-
-
+
+ {" "}
+
```Swift
@@ -150,67 +207,97 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
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).
+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
+## 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()`.
-
+ 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`.
@@ -237,9 +324,9 @@ 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]
@@ -250,7 +337,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
application.registerForRemoteNotifications()
-
+
return true
}
@@ -272,7 +359,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
extension AppDelegate: UNUserNotificationCenterDelegate {
-
+
}
```
@@ -281,12 +368,18 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
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
@@ -311,9 +404,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
FirebaseApp.configure()
FirebaseConfiguration.shared.setLoggerLevel(.min)
-
+
// Register for Remote Notitifcations
-
+
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
@@ -323,12 +416,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
)
application.registerForRemoteNotifications()
-
+
// Messaging Delegate
-
+
Messaging.messaging().delegate = self
-
+
return true
}
@@ -350,7 +443,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
extension AppDelegate: UNUserNotificationCenterDelegate {
-
+
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification) async
@@ -382,14 +475,14 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
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"),
@@ -399,8 +492,8 @@ extension AppDelegate: MessagingDelegate {
// TODO: If necessary send token to application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
-
-
+
+
}
```
@@ -411,7 +504,9 @@ extension AppDelegate: MessagingDelegate {
2. Add the `didReceiveRemoteNotification`.
3. We must declare a `gcmMessageIDKey` inside of `AppDelegate`. We can define this as a `string` variable.
-
+
+ {" "}
+
```Swift
@@ -428,7 +523,7 @@ import FirebaseMessaging
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
-
+
let gcmMessageIDKey = "gcm.Message_ID"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
@@ -436,9 +531,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
FirebaseApp.configure()
FirebaseConfiguration.shared.setLoggerLevel(.min)
-
+
// Register for Remote Notitifcations
-
+
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
@@ -448,12 +543,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
)
application.registerForRemoteNotifications()
-
+
// Messaging Delegate
-
+
Messaging.messaging().delegate = self
-
+
return true
}
@@ -475,7 +570,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
extension AppDelegate: UNUserNotificationCenterDelegate {
-
+
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification) async
@@ -506,7 +601,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
// Print full message.
print(userInfo)
}
-
+
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any]) async
-> UIBackgroundFetchResult {
@@ -528,16 +623,16 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
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"),
@@ -547,82 +642,121 @@ extension AppDelegate: MessagingDelegate {
// 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
+
+- 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.
+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:
@@ -652,17 +786,27 @@ Make sure your service account key JSON content contains these fields:
```
-
-
-
-
-
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
## 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.
+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.
@@ -670,14 +814,22 @@ Workflow creation is for streamlining automated notifications, enabling teams to
-
-
+
+ {" "}
+
+
+ {" "}
+
-
+
+ {" "}
+
-
+
+ {" "}
+
@@ -685,7 +837,9 @@ Workflow creation is for streamlining automated notifications, enabling teams to
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.
-
+
+ {" "}
+
@@ -694,24 +848,25 @@ Creating a subscriber in Novu refers to the process of establishing a subscriber
```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"
- }
- }'
-```
+--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"
+}
+}'
+
+````
@@ -742,7 +897,7 @@ Creating a subscriber in Novu refers to the process of establishing a subscriber
"providerId":"fcm"
}'
-```
+````
@@ -750,7 +905,7 @@ Creating a subscriber in Novu refers to the process of establishing a subscriber
## Sending a notification to iOS device with Novu
-To send a notification with Novu, you are actually triggering a notification workflow.
+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**
@@ -770,8 +925,9 @@ curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
```
-
-
+
+ {" "}
+
## Dynamic Content
@@ -780,9 +936,11 @@ When we were creating the first workflow, we "Hardcoded" the content of the noti
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.
+ That way, we could insert values through the payload of the API call.
-
+
+ {" "}
+
2. Add a 'payload' object to the API call.
@@ -804,11 +962,13 @@ curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
```
-
+
+ {" "}
+
## 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.
+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.
@@ -887,32 +1047,45 @@ curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
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.
+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.
+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.
@@ -925,11 +1098,11 @@ Next, replace the contents of `didReceive(_:withContentHandler:)` with the fol
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 {
@@ -939,10 +1112,10 @@ Messaging.serviceExtension().populateNotificationContent(bestAttemptContent, wit
```
-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.
+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()`.
+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.
@@ -965,21 +1138,21 @@ class NotificationService: UNNotificationServiceExtension {
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.
@@ -994,14 +1167,16 @@ class NotificationService: UNNotificationServiceExtension {
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,
+- "image" in "fcm_options" object,
- URL address of the image.
-
```JSON
curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
@@ -1035,15 +1210,19 @@ curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
```
-
-
+
+ {" "}
+
+
+ {" "}
+
## 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.
+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
@@ -1056,7 +1235,7 @@ extension UNNotificationAction {
title: "Accept",
options: [.foreground]
)
-
+
static let reject = UNNotificationAction(
identifier: "REJECT_ACTION",
title: "Reject",
@@ -1066,35 +1245,36 @@ extension UNNotificationAction {
```
-2. Register Notification Category:
-
- You need to register the notification category with the actions you defined in your `didFinishLaunchingWithOptions` method:
+2. Register Notification Category:
- ```
- 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])
+ You need to register the notification category with the actions you defined in your `didFinishLaunchingWithOptions` method:
- return true
-}
+ ```
+ 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`.
+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
@@ -1117,7 +1297,7 @@ func userNotificationCenter(_ center: UNUserNotificationCenter,
}
}
-```
+````
Your full `AppDelegate.swift` file should look like this:
@@ -1136,7 +1316,7 @@ import FirebaseMessaging
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
-
+
let gcmMessageIDKey = "gcm.Message_ID"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
@@ -1144,9 +1324,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
FirebaseApp.configure()
FirebaseConfiguration.shared.setLoggerLevel(.min)
-
+
// Register for Remote Notitifcations
-
+
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
@@ -1156,25 +1336,25 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
)
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
}
@@ -1196,7 +1376,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
extension AppDelegate: UNUserNotificationCenterDelegate {
-
+
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification) async
@@ -1218,7 +1398,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
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")
@@ -1239,10 +1419,10 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
// Print full message.
print(userInfo)
-
-
+
+
}
-
+
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any]) async
-> UIBackgroundFetchResult {
@@ -1260,22 +1440,22 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
// 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"),
@@ -1285,8 +1465,8 @@ extension AppDelegate: MessagingDelegate {
// 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 {
@@ -1295,7 +1475,7 @@ extension UNNotificationAction {
title: "Accept",
options: [.foreground]
)
-
+
static let reject = UNNotificationAction(
identifier: "REJECT_ACTION",
title: "Reject",
@@ -1336,8 +1516,9 @@ curl --location --request POST "https://api.novu.co/v1/events/trigger" \
```
-
-
+
+ {" "}
+
## Additional resources
diff --git a/guides/add-digest-to-email-notifications.mdx b/legacy-guides/add-digest-to-email-notifications.mdx
similarity index 73%
rename from guides/add-digest-to-email-notifications.mdx
rename to legacy-guides/add-digest-to-email-notifications.mdx
index 1f52a1e3..35f816a5 100644
--- a/guides/add-digest-to-email-notifications.mdx
+++ b/legacy-guides/add-digest-to-email-notifications.mdx
@@ -1,6 +1,6 @@
---
-title: 'How to Add Digest to Email Notifications'
-description: 'Leverage the digest functionality to send email notifications'
+title: "How to Add Digest to Email Notifications"
+description: "Leverage the digest functionality to send email notifications"
---
# Introduction
@@ -9,9 +9,10 @@ In this guide, you’ll learn how to add digest functionality to email notificat
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](/guides/add-digest-to-inapp-notifications).
+ If, instead, you want to add digest to in-app notifications, we have a guide
+ for that as well. Take a
+ look [here](/guides/add-digest-to-inapp-notifications).
### What is a Digest Notification?
@@ -23,7 +24,7 @@ A digest notification is a notification that consolidates information from sever
### 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://web.novu.co/workflows?utm_campaign=docs-digests). If you want to learn more about it, [this](/getting-started/concepts#digest) is a great place to start.
+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.novu.co/workflows?utm_campaign=docs-digests). If you want to learn more about it, [this](/getting-started/concepts#digest) is a great place to start.
Let’s see it in action now!
@@ -31,7 +32,7 @@ Let’s see it in action now!
To get started with this, you need the following:
-- A Novu account. [Sign up for free](http://web.novu.co/?utm_campaign=docs-gs-digests) if you don’t have one yet.
+- 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
@@ -41,24 +42,42 @@ 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.
-
+
+ {" "}
+
+ 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
+ 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:
-
+
+
+ {" "}
+
+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.
@@ -71,7 +90,10 @@ Here’s a brief explanation of all the options:
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
@@ -86,26 +108,27 @@ 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 express from "express";
-import { getEmailDigest } from '../controller/emaildigest.js';
+import { getEmailDigest } from "../controller/emaildigest.js";
const router = express.Router();
-router.post('/sending-email-digest', getEmailDigest);
+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';
+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 });
+ res.status(201).json({ message: "success", notif: notif });
} catch (error) {
res.status(409).json({ message: error.message });
}
@@ -116,13 +139,13 @@ To make it modular, we’ll keep the trigger code in a separate function in a se
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://web.novu.co/subscribers?utm_campaign=docs-digests) as well.
+Subscribers are users to which the notifications are sent. You can see a list of subscribers in the [Novu dashboard](https://dashboard.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',
+await novu.subscribers.identify("digestEmailSub", {
+ firstName: "digest email subscriber",
email: email,
});
```
@@ -132,18 +155,18 @@ Here, we’re creating a subscriber with the `subscriberID` of `digestEmailSu
Back in our app, we can now add the trigger function:
```jsx
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
export const sendEmailDigest = async (notif, email) => {
const novu = new Novu(process.env.YOUR_NOVU_API_KEY);
- await novu.subscribers.identify('digestEmailSub', {
- firstName: 'digest email subscriber',
+ await novu.subscribers.identify("digestEmailSub", {
+ firstName: "digest email subscriber",
email: email,
});
- novu.trigger('emaildigestworkflow', {
+ novu.trigger("emaildigestworkflow", {
to: {
- subscriberId: 'digestEmailSub',
+ subscriberId: "digestEmailSub",
email: email,
},
payload: {
@@ -161,23 +184,23 @@ From the front end, we just need to hit the route we had defined above. Below, I
```jsx
const Body = () => {
- const [formInput, setFormInput] = useState({ notif: '', email: '' });
+ 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',
+ "https://emaildigestbackend.onrender.com/api/v1/sending-email-digest",
{
- method: 'POST',
+ method: "POST",
headers: {
- 'Content-Type': 'application/json',
+ "Content-Type": "application/json",
},
body: JSON.stringify(formInput),
}
);
console.log(response.data);
- setFormInput({ notif: '' });
+ setFormInput({ notif: "" });
};
const handleClick = () => {
@@ -190,7 +213,8 @@ const Body = () => {
};
const onChangeHandler = (e) => {
- const value = e.target.name === 'email' ? e.target.value.trim() : e.target.value;
+ const value =
+ e.target.name === "email" ? e.target.value.trim() : e.target.value;
setFormInput((prev) => ({
...prev,
@@ -201,9 +225,9 @@ const Body = () => {
@@ -247,8 +271,11 @@ We're hitting the backend route we had created earlier. The backend has been dep
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!
\ No newline at end of file
+This is how we add digest to email notifications!
diff --git a/guides/add-digest-to-inapp-notifications.mdx b/legacy-guides/add-digest-to-inapp-notifications.mdx
similarity index 67%
rename from guides/add-digest-to-inapp-notifications.mdx
rename to legacy-guides/add-digest-to-inapp-notifications.mdx
index 56babcd9..08085f3f 100644
--- a/guides/add-digest-to-inapp-notifications.mdx
+++ b/legacy-guides/add-digest-to-inapp-notifications.mdx
@@ -1,6 +1,6 @@
---
-title: 'How to Add Digest to In-App Notifications'
-description: 'Leverage the digest functionality to send in-app notifications'
+title: "How to Add Digest to In-App Notifications"
+description: "Leverage the digest functionality to send in-app notifications"
---
## Introduction
@@ -19,7 +19,7 @@ A digest notification is a notification that consolidates information from sever
### 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://web.novu.co/workflows?utm_campaign=docs-digestsinapp).
+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.novu.co/workflows?utm_campaign=docs-digestsinapp).
Let’s see it in action now!
@@ -27,7 +27,7 @@ Let’s see it in action now!
To get started with this, you need the following:
-- A Novu account. [Sign up for free](http://web.novu.co/?utm_campaign=docs-gs-digestsinapp) if you don’t have one yet.
+- 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
@@ -37,22 +37,42 @@ 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.
+
+ {" "}
+
+ 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
+ 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:
-
+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.
@@ -63,10 +83,16 @@ Here’s a brief explanation of all the options:
- **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:
-
+
+
+ {" "}
+
+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
@@ -76,28 +102,30 @@ 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';
+import express from "express";
+import { getDigest } from "../controller/digest.js";
const router = express.Router();
-router.post('/sending-digest', getDigest);
+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';
+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 });
+ res.status(201).json({ message: "success", name: name });
} catch (error) {
res.status(409).json({ message: error.message });
}
@@ -108,13 +136,13 @@ To make it modular, we’ll keep the trigger code in a separate function in a se
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://web.novu.co/subscribers?utm_campaign=docs-digests-inapp) as well.
+Subscribers are entities to which the notifications are sent. You can see a list of subscribers in the [Novu dashboard](https://dashboard.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',
+await novu.subscribers.identify("aa234u787", {
+ firstName: "digest subscriber",
});
```
@@ -123,18 +151,18 @@ Here, we’re creating a subscriber with the `subscriberID` of `aa234u787.`
Back in our app, we can now add the trigger function:
```jsx
-import { Novu } from '@novu/node';
+import { Novu } from "@novu/node";
export const sendDigest = async (name) => {
const novu = new Novu(process.env.NOVU_API_KEY);
- await novu.subscribers.identify('aa234u787', {
- firstName: 'digest subscriber',
+ await novu.subscribers.identify("aa234u787", {
+ firstName: "digest subscriber",
});
- await novu.trigger('digest-showcase', {
+ await novu.trigger("digest-showcase", {
to: {
- subscriberId: 'aa234u787',
+ subscriberId: "aa234u787",
},
payload: {
name: name,
@@ -162,25 +190,27 @@ import {
PopoverNotificationCenter,
NotificationBell,
IMessage,
-} from '@novu/notification-center';
+} 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;
+ 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:
@@ -190,14 +220,14 @@ import {
NovuProvider,
PopoverNotificationCenter,
NotificationBell,
-} from '@novu/notification-center';
-import '../css/Header.css';
+} 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;
+ window.location.href = message.cta.data.url;
}
}
return (
@@ -205,16 +235,21 @@ window.location.href = message.cta.data.url;
Play with the digest engine!
- Don't know how to? Start here.
+ Don't know how to? Start{" "}
+ here.
@@ -230,17 +265,20 @@ You’ll also need to plug in your `applicationIdentifier`. You can get your `
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';
+import { useState } from "react";
+import axios from "axios";
+import "../css/Body.css";
const Body = () => {
- const [name, setName] = useState('');
+ 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 res = await axios.post(
+ "http://localhost:3000/api/v1/sending-digest",
+ { name }
+ );
+ setName("");
};
const onChangeHandler = (e) => {
setName(e.target.value);
@@ -259,8 +297,8 @@ const Body = () => {
className="text"
/>
);
@@ -274,7 +312,12 @@ 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!
\ No newline at end of file
+
+ {" "}
+
+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/guides/cookbook/introduction.mdx b/legacy-guides/cookbook/introduction.mdx
similarity index 80%
rename from guides/cookbook/introduction.mdx
rename to legacy-guides/cookbook/introduction.mdx
index 1ef78e8e..76eeab5d 100644
--- a/guides/cookbook/introduction.mdx
+++ b/legacy-guides/cookbook/introduction.mdx
@@ -5,17 +5,20 @@ 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.
+
+ **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:
@@ -25,14 +28,15 @@ const { data: inAppMessages } = await novu.subscribers.getNotificationsFeed('sub
page: 0,
limit: 10,
- // it is of type string. By default all feeds messages are fetched
- feedIdentifier: 'Marketing',
+// 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
+// seen and read filter of type boolean
+seen: true,
+read: true
});
-```
+
+````
## Fetch All Feeds
@@ -42,9 +46,10 @@ 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
+```javascript Node.js
const { data: feedsData } = await novu.feeds.get();
-```
+````
+
## Delete a Message From a Feed
@@ -54,9 +59,7 @@ A message is a content sent to a single subscriber over a single channel. Some m
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');
-```
+ ```javascript Node.js await novu.messages.deleteById('messageId'); ```
## Fetch all Messages Sent To All Subscribers
@@ -73,21 +76,23 @@ import { ChannelTypeEnum } from '@novu/node';
// All fields are optional
const listMessagesOptions = {
- // pagination options
- page: 0,
- limit: 20,
+// pagination options
+page: 0,
+limit: 20,
- /**
- * Filter options
- */
+/\*\*
+
+- 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
@@ -95,7 +100,7 @@ const { data: messagesData } = await novu.messages.list(listMessagesOptions);
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
+```javascript Node.js
const { data: markMessageAsRead } = await novu.subscribers.markMessageRead(
'subscriberId',
'messageId'
@@ -105,7 +110,8 @@ const { data: markMessageAsSeen } = await novu.subscribers.markMessageSeen(
'subscriberId',
'messageId'
);
-```
+````
+
## Mark an In-App Message as Read/Unread/Seen/Unseen
@@ -133,18 +139,19 @@ Messages from other channels: **Email**, **Push**, **Chat**, **Sms** can't be ma
import { MarkMessagesAsEnum } from "@novu/node"
const { data: markAllInAppMessages } = await novu.subscribers.markAllMessagesAs(
- 'subscriberId',
+'subscriberId',
- // can be filtered with feed identifiers
- feedIdentifier: ['Marketing', 'Product']
+// 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
+// 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
@@ -178,8 +185,8 @@ await novu.trigger('slack', {
chatMsg: ''
}
});
-```
+````
where `chatMsg` is a payload variable in the workflow editor.
-Follow the [full guide](/guides/slack-guide) on how to send Slack notifications using Novu.
\ No newline at end of file
+Follow the [full guide](/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 00000000..bb324d70
--- /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/guides/discord-guide.mdx b/legacy-guides/discord-guide.mdx
similarity index 50%
rename from guides/discord-guide.mdx
rename to legacy-guides/discord-guide.mdx
index ef9c8df9..c85364f1 100644
--- a/guides/discord-guide.mdx
+++ b/legacy-guides/discord-guide.mdx
@@ -1,80 +1,116 @@
---
-title: 'How to use Novu to send notifications to a channel in a Discord server'
-description: 'Learn to send Discord notifications swiftly with Novu'
+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).
+
+
+ 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://web.novu.co/integrations?utm_campaign=docs-discordnotifications).
-
-2. Goto the [Novu Web Dashboard](https://web.novu.co/workflows?utm_campaign=docs-discordnotifications).
+
+1. Make sure that you've set the Discord Integration as active from the [Novu Integrations Store](https://dashboard.novu.co/integrations?utm_campaign=docs-discordnotifications).
+
+ {" "}
+
+2. Goto the [Novu Web Dashboard](https://dashboard.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.
+
+ {" "}
+
+ 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!
+
+ {" "}
+
+ 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);
+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"
+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 })
- }
-}
+ 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';
+
+
+ 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 {
@@ -91,11 +127,13 @@ export const chat = async (chatMsg) => {
} catch (error) {
console.log(error);
}
+
}
-```
+
+````
Add the trigger code you'd copied earlier:
```jsx
-import { Novu } from '@novu/node';
+import { Novu } from '@novu/node';
const novu = new Novu('');
@@ -107,47 +145,64 @@ novu.trigger('chat-with-discord', {
chatMsg: ''
}
});
-```
+````
Our final trigger code should look something like this:
+
```jsx
-import { Novu, ChatProviderIdEnum } from '@novu/node';
+import { Novu, ChatProviderIdEnum } from "@novu/node";
export const chat = async (chatMsg) => {
- try {
- const novu = new Novu(process.env.YOUR_NOVU_API_KEY_HERE);
+ try {
+ const novu = new Novu(process.env.YOUR_NOVU_API_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);
+ }
+};
+```
- await novu.subscribers.identify(process.env.SUB_ID, {
- firstName: 'newSubForDiscordChat',
- });
+
+ We're keeping all the sensitive data in a `.env` file to avoid hardcoding as a
+ good practice
+
- await novu.subscribers.setCredentials(process.env.SUB_ID, ChatProviderIdEnum.Discord, {
- webhookUrl: process.env.WEBHOOK_URL
- });
+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).
- 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.
+
+ 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).
+
+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!
\ No newline at end of file
+This is how we send Discord notifications using Novu!
diff --git a/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
similarity index 86%
rename from guides/fcm-flutter-novu/how-to-send-push-notifications-to-flutter-apps-with-fcm-using-Novu.mdx
rename to legacy-guides/fcm-flutter-novu/how-to-send-push-notifications-to-flutter-apps-with-fcm-using-Novu.mdx
index e28b3552..bae862f2 100644
--- a/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
@@ -1,6 +1,6 @@
---
-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'
+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
@@ -10,7 +10,7 @@ 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://web.novu.co/?utm_campaign=docs-gs-guides-fcm-flutter) account.
+- [Novu](https://dashboard.novu.co/?utm_campaign=docs-gs-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.
@@ -176,6 +176,7 @@ class _MyHomePageState extends State {
}
}
```
+
_lib/main.dart_
There are 4 sections to pay attention to:
@@ -211,6 +212,7 @@ There are 4 sections to pay attention to:
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.
@@ -227,6 +229,7 @@ There are 4 sections to pay attention to:
_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.
@@ -250,72 +253,94 @@ There are 4 sections to pay attention to:
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://web.novu.co)?utm_campaign=docs-gs-guides-fc-flutter.
+Let's use Novu to fire push notifications via FCM. First, sign up on [Novu Cloud](https://dashboard.novu.co)?utm_campaign=docs-gs-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
+## Connect FCM as a Push Channel provider
-
-
+
+ {" "}
+
+
+ {" "}
+
-You only need to configure FCM with Novu with the Firebase Service Accounts private key.
+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:
@@ -345,30 +370,48 @@ Make sure your service account key JSON content contains these fields:
```
-
-
-
-
-
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+
## 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.
+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.
-
-
+
+ {" "}
+
+
+ {" "}
+
-
+
+ {" "}
+
-
+
+ {" "}
+
@@ -380,7 +423,9 @@ A subscriber is essentially the recipient of the notifications sent through Novu
You can see the list of subscribers in the `Subscribers` section of the Novu dashboard.
-
+
+ {" "}
+
@@ -389,17 +434,18 @@ You can see the list of subscribers in the `Subscribers` section of the Novu das
```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",
- }'
-```
+--header 'Content-Type: application/json' \
+ --header 'Accept: application/json' \
+ --header 'Authorization: ApiKey ' \
+ --data-raw '{
+"subscriberId": "584349343",
+"firstName": "Flutter",
+"lastName": "Boy",
+"email": "flutterboy@gmail.com",
+}'
+
+````
@@ -430,8 +476,9 @@ You can see the list of subscribers in the `Subscribers` section of the Novu das
"providerId":"fcm"
}'
- ```
- _Update the Subscriber Credentials by adding the device tokens to the subscriber_
+````
+
+_Update the Subscriber Credentials by adding the device tokens to the subscriber_
@@ -439,7 +486,7 @@ You can see the list of subscribers in the `Subscribers` section of the Novu das
## Sending a Push Notification to a Device(Android/iOS) with Novu
-To send a notification with Novu, you are actually triggering a notification workflow.
+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**
@@ -463,17 +510,22 @@ curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
**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.
@@ -481,9 +533,11 @@ When we were creating the first workflow, we "Hardcoded" the content of the noti
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.
+ That way, we could insert values through the payload of the API call.
-
+
+ {" "}
+
2. Add a `payload` object to the API call.
@@ -507,7 +561,9 @@ curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
```
-
+
+ {" "}
+
## Handling Data Type Messages
@@ -544,17 +600,15 @@ curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
```
-
+
-
## 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.
+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
@@ -681,23 +735,20 @@ curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
```
-
## 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.
+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,
+- "image" in "fcm_options" object,
- URL address of the image.
-
```JSON
curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
@@ -731,4 +782,4 @@ curl --location --request POST 'https://api.novu.co/v1/events/trigger' \
## Additional resources
-- [Notifications Usage - Flutter Fire](https://firebase.flutter.dev/docs/messaging/notifications)
\ No newline at end of file
+- [Notifications Usage - Flutter Fire](https://firebase.flutter.dev/docs/messaging/notifications)
diff --git a/guides/framework-guides/digest.mdx b/legacy-guides/framework-guides/digest.mdx
similarity index 69%
rename from guides/framework-guides/digest.mdx
rename to legacy-guides/framework-guides/digest.mdx
index 6644afdb..9961cb8d 100644
--- a/guides/framework-guides/digest.mdx
+++ b/legacy-guides/framework-guides/digest.mdx
@@ -1,5 +1,5 @@
---
-title: 'How to batch product notifications via code'
+title: "How to batch product notifications via code"
description: "Leverage Novu's Digest Engine to batch product notifications"
---
@@ -37,43 +37,42 @@ Novu’s Digest Engine is designed to consolidate multiple trigger events into a
import { Client } from "@novu/framework";
export const client = new Client({
- apiKey: '',
+ apiKey: "",
/**
* Enable this flag only during local development
*/
strictAuthentication: process.env.NODE_ENV !== "development",
});
-export const digestWorkflow = workflow('novu-digest',
-
+export const digestWorkflow = workflow(
+ "novu-digest",
+
async ({ step, payload }) => {
-
// Add Digest Node
- const digestResult = await step.digest('email-digest', async () => ({
- unit: 'seconds',
+ const digestResult = await step.digest("email-digest", async () => ({
+ unit: "seconds",
amount: 30,
}));
// Send a welcome email
- await step.email('send-email', () => {
+ await step.email("send-email", () => {
const resObj = {
subject: `Welcome to Novu`,
- body: (digestResult.events.map((event) => event.payload.text).join('\n')),
- }
- return resObj
+ body: digestResult.events.map((event) => event.payload.text).join("\n"),
+ };
+ return resObj;
});
},
{
payloadSchema: {
properties: {
- email: { type: 'string' },
- text: { type: 'string', default: 'Sumit' },
+ email: { type: "string" },
+ text: { type: "string", default: "Sumit" },
},
- required: ['text'],
+ required: ["text"],
},
}
);
-
```
@@ -84,13 +83,12 @@ export const digestWorkflow = workflow('novu-digest',
2. Here’s a simple client-side app with a handler function attached to the `submit` event:
```tsx
-"use client"
+"use client";
import React, { useState } from "react";
export default function Home() {
-
- const [email, setEmail] = useState('')
- const [text, setText] = useState('')
+ const [email, setEmail] = useState("");
+ const [text, setText] = useState("");
const onClickHandler = async (e: React.FormEvent) => {
try {
@@ -108,23 +106,30 @@ export default function Home() {
// console.log('working fine');
} catch (error) {
- console.error('Error:', error);
+ console.error("Error:", error);
}
};
return (
-
+