Headless using Novu/JS

I am using the following snippet on our react js app const novu = useMemo(() => { return new Novu({ applicationIdentifier: applicationId, subscriberId: memberId, }); }, [applicationId, memberId]); novu.on('notifications.notification_received', data => { console.log('new notification =>', data); getNotifications(1); }); I see websockets being called in the inspector but the event does NOT get fired. Am I missing anything?
20 Replies
Mark Garcia
Mark GarciaOP5mo ago
When I call list, it's always empty const getNovuNotifications = useCallback(async () => { const {data} = await novu.notifications.list({limit: 30}); setList(data?.notifications); console.log('NOVU-list', data?.notifications); }, [novu]); I know the subsciber has existing notifications when I call the novu api. https://api.novu.co/v1/messages?subscriberId=759291&page=0&limit=15 This is the default websocket url: wss://ws.novu.co/socket.io
Pawan Jain
Pawan Jain5mo ago
@Mark Garcia Could you please share complete code?
Mark Garcia
Mark GarciaOP5mo ago
parts redacted but this is how it's implemented in a Provider component export const GlobalNoticeProvider = ({ children, }: GlobalNoticeProviderProps): JSX.Element => { const applicationId = process.env.NEXT_PUBLIC_NOVU_APPLICATION_ID as string; const memberId = getUserIdFromStoredToken() as string; const novu = useMemo(() => { return new Novu({ applicationIdentifier: applicationId, subscriberId: memberId, }); }, [applicationId, memberId]); novu.on('notifications.notification_received', data => { console.log('new notification =>', data); getNotifications(1); }); const getNovuNotifications = useCallback(async () => { const {data} = await novu.notifications.list({limit: 30}); setList(data?.notifications); console.log('NOVU-list', data?.notifications); }, [novu]);

return ( <GlobalNoticeContext.Provider value={value}> <> {openNotice && ( <NoticeDialog notice={openNotice} onClose={handleOnClose} /> )} {children} </> </GlobalNoticeContext.Provider> ); }
Pawan Jain
Pawan Jain5mo ago
Thanks. I will take a look
Mark Garcia
Mark GarciaOP5mo ago
Hi @Pawan Jain just following up on this.
Pawan Jain
Pawan Jain5mo ago
@Mark Garcia Checkout this code 👇🏻
"use client";

import { Novu } from "@novu/js";
import { useMemo, useState, useEffect } from "react";
import { env } from "@/env.mjs";

export const HeadlessNotification = () => {
const [list, setList] = useState<any[]>([]);
const applicationId = env.NEXT_PUBLIC_NOVU_APPLICATION_IDENTIFIER;
const memberId = env.NEXT_PUBLIC_SUBSCRIBER_ID;

const novu = useMemo(() => {
console.log("applicationId", applicationId);
return new Novu({
applicationIdentifier: applicationId,
subscriberId: memberId,
});
}, [applicationId, memberId]);

const getNovuNotifications = async () => {
try {
const { data } = await novu.notifications.list({
limit: 30,
useCache: false,
});

setList(data?.notifications || []);
console.log("NOVU-list", data?.notifications);
} catch (error) {
console.error("Error fetching notifications:", error);
}
};

useEffect(() => {
const handleNewNotification = (data: any) => {
console.log("new notification =>", data);
getNovuNotifications();
};

// Set up event listener
novu.on("notifications.notification_received", handleNewNotification);

// Initial fetch
getNovuNotifications();
}, [novu]);

return (
<div>
{list.length > 0 ? (
list.map((item) => (
<div key={item.id} dangerouslySetInnerHTML={{ __html: item.body }} />
))
) : (
<div>No notifications</div>
)}
</div>
);
};
"use client";

import { Novu } from "@novu/js";
import { useMemo, useState, useEffect } from "react";
import { env } from "@/env.mjs";

export const HeadlessNotification = () => {
const [list, setList] = useState<any[]>([]);
const applicationId = env.NEXT_PUBLIC_NOVU_APPLICATION_IDENTIFIER;
const memberId = env.NEXT_PUBLIC_SUBSCRIBER_ID;

const novu = useMemo(() => {
console.log("applicationId", applicationId);
return new Novu({
applicationIdentifier: applicationId,
subscriberId: memberId,
});
}, [applicationId, memberId]);

const getNovuNotifications = async () => {
try {
const { data } = await novu.notifications.list({
limit: 30,
useCache: false,
});

setList(data?.notifications || []);
console.log("NOVU-list", data?.notifications);
} catch (error) {
console.error("Error fetching notifications:", error);
}
};

useEffect(() => {
const handleNewNotification = (data: any) => {
console.log("new notification =>", data);
getNovuNotifications();
};

// Set up event listener
novu.on("notifications.notification_received", handleNewNotification);

// Initial fetch
getNovuNotifications();
}, [novu]);

return (
<div>
{list.length > 0 ? (
list.map((item) => (
<div key={item.id} dangerouslySetInnerHTML={{ __html: item.body }} />
))
) : (
<div>No notifications</div>
)}
</div>
);
};
Mark Garcia
Mark GarciaOP5mo ago
Thanks @Pawan Jain but it still does NOT trigger the new_notification event. I've created custom hook for this implementation import {useEffect, useMemo} from 'react'; import {useNotification} from '@hooks/useNotification'; import {Novu} from '@novu/js'; import {useAuthentication} from './useAuthentication'; export const useNovuEvents = () => { const {getUserIdFromStoredToken} = useAuthentication(); const {getNotifications} = useNotification(); const applicationId = process.env.NEXT_PUBLIC_NOVU_APPLICATION_ID as string; const memberId = getUserIdFromStoredToken() as string; const novu = useMemo(() => { return new Novu({ applicationIdentifier: applicationId, subscriberId: memberId, }); }, [applicationId, memberId]); useEffect(() => { // Set up event listener novu.on('notifications.notification_received', data => { console.log('new notification =>', data); getNotifications(1); }); }, [novu, getNotifications]); }; Then calling this in our GlobalNotice provider useNovuEvents();
Mark Garcia
Mark GarciaOP5mo ago
I can confirm websocket is established and the useEffect hook gets called.
No description
Mark Garcia
Mark GarciaOP5mo ago
This is the generated websocket domain: wss://ws.novu.co/socket.io/?token=
Novu_Bot
Novu_Bot5mo ago
@Mark Garcia, you just advanced to level 2!
Mark Garcia
Mark GarciaOP5mo ago
curl --location 'https://api.novu.co/v1/events/trigger' \
--header 'Authorization: ApiKey {ApiKey}' \
--header 'Content-Type: application/json' \
--data '{"name":"CampaignRegistration","to": [{"subscriberId":"759291" }],"payload":{"Id":"123456","MemberId":759291,"Description":"Testing my new notification here.","Title":"New campaign title 7!","CampaignId":"1","CampaignUrl":"https://test.com","Market":"AUS","Type": "CampaignRegistration"}}'
curl --location 'https://api.novu.co/v1/events/trigger' \
--header 'Authorization: ApiKey {ApiKey}' \
--header 'Content-Type: application/json' \
--data '{"name":"CampaignRegistration","to": [{"subscriberId":"759291" }],"payload":{"Id":"123456","MemberId":759291,"Description":"Testing my new notification here.","Title":"New campaign title 7!","CampaignId":"1","CampaignUrl":"https://test.com","Market":"AUS","Type": "CampaignRegistration"}}'
Above is the sample curl I send out to trigger new notification but 'notifications.notification_received' event is not picking it up and it does NOT fire.
Mark Garcia
Mark GarciaOP5mo ago
I confirm that I receive the notification.
No description
Pawan Jain
Pawan Jain5mo ago
@Mark Garcia Did not get chance to check with wrapping this in hooks What is your usecase with wrapping it over a hook?
Mark Garcia
Mark GarciaOP5mo ago
We want to eventually create a component that allows for multiple notification provider so we would like to place each provider in its own custom hook. But I also did the SUGGESTED implementation and I got the same result. Do you have any reports of anything blocking your websocket requests or interferring with it? I'll try to create a new project and try this there. I've created a blank nextjs project and even that didn't work 'use client' import Image from "next/image"; import { Novu } from "@novu/js"; import { useEffect, useMemo } from "react"; export default function Home() { const novu = useMemo(() => { return new Novu({ applicationIdentifier: '6nupmbyERXRf', subscriberId: '759291', }) }, []); useEffect(() => { novu.on("notifications.notification_received", (data) => { console.log("new notification =>", data); });
novu.on("notifications.unread_count_changed", (data) => { console.log("new unread notifications count =>", data); }); }, [novu]) return ( <div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]"> EMPTY HTML </div> ); }
Pawan Jain
Pawan Jain5mo ago
@Mark Garcia Are you self hosting Novu because I can not reproduce this on novu cloud
Mark Garcia
Mark GarciaOP5mo ago
No, we're using novu cloud services again. This is the only thing missing so that we can launch the notification feature This is when I try to get notification list [GET] https://api.novu.co/v1/inbox/notifications?limit=10 Generated Bearer: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2NmY5ZmY3ZGVjMmM5MTBiMmVmYjBjMDQiLCJlbWFpbCI6ImRldmVsb3BlckBob21ldGVzdGVyY2x1Yi5jb20iLCJvcmdhbml6YXRpb25JZCI6IjY2YTJkM2E4MzIzYmEzOWZhY2VjZTBjNCIsImVudmlyb25tZW50SWQiOiI2NmEyZDNhODMyM2JhMzlmYWNlY2UwZDIiLCJzdWJzY3JpYmVySWQiOiI3NTkyOTEiLCJpYXQiOjE3NDc2MTQ1MjcsImV4cCI6MTc0ODkxMDUyNywiYXVkIjoid2lkZ2V0X3VzZXIiLCJpc3MiOiJub3Z1X2FwaSJ9.tYVfiLl72UEPUi6ZfEtNIor6AIsFhl5Pwt35JdXm09A I am getting empty data here. const [notification, setNotification] = useState<Notification[] | null>([]); const getNotices = useCallback(async () => { const { data: notifications, error } = await novu.notifications.list(); if (!error) { setNotification(notifications?.notifications ?? []); } }, [novu]); Do I need to whitelabel domains? Currently testing this in my local machine. Maybe any CORS issue if I test in local machine? Where can I white list origin domains? Hi @Pawan Jain we need to resolve this with urgency
Novu_Bot
Novu_Bot5mo ago
@Mark Garcia, you just advanced to level 3!
Mark Garcia
Mark GarciaOP5mo ago
@Pawan Jain please let me know what are the next steps
Pawan Jain
Pawan Jain5mo ago
@Mark Garcia Could you please send us an email to support@novu.co from the same account you signed up on Novu Please share your application identifier. I will check in logs if there is some issue
Mark Garcia
Mark GarciaOP5mo ago
Ok, will also include the blank next js app with the basic implementation.

Did you find this page helpful?