π Send In-App Notifications
NotificationAPI allows you to send and display in-app notifications quickly. Hereβs how to setup the frontend to display notifications, and setup the backend to send notifications.
1. Display Notifications in Your App (Frontend)
Install the frontend SDK:
npm install @notificationapi/react npm install @notificationapi/react react react-dom @types/react @types/react-dom npm install @notificationapi/react npm install @notificationapi/react The @notificationapi/core library is a headless JavaScript SDK that lets you build your own custom UI for notifications. It provides direct API access without any prebuilt components, giving you complete control over the design and user experience.
npm install @notificationapi/core The @notificationapi/core library is a headless JavaScript SDK that lets you build your own custom UI for notifications. It provides direct API access without any prebuilt components, giving you complete control over the design and user experience.
npm install @notificationapi/core npm install @notificationapi/js-core Integrate the Notification Widget that automatically connects to our servers and displays notifications in real-time:
Wrap your app with NotificationAPIProvider (typically in your root component) and add NotificationPopup where you want the notification bell to appear:
import {
NotificationAPIProvider,
NotificationPopup
} from '@notificationapi/react';
function App() {
return (
<NotificationAPIProvider clientId="YOUR_CLIENT_ID" userId="USER_ID">
<div>
{/* Your app content */}
<NotificationPopup />
</div>
</NotificationAPIProvider>
);
}
export default App; For Nuxt applications, create the file components/NotificationAPIWrapper.vue, and add this code:
<template>
<div ref="reactContainer"></div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch } from 'vue'
import { createElement } from 'react'
import { createRoot } from 'react-dom/client'
import {
NotificationAPIProvider,
NotificationPopup
} from '@notificationapi/react'
interface Props {
clientId: string
userId: string
apiURL?: string
wsURL?: string
customServiceWorkerPath?: string // if using web push
}
const props = withDefaults(defineProps<Props>(), {
apiURL: 'api.notificationapi.com',
wsURL: 'ws.notificationapi.com',
customServiceWorkerPath: '/notificationapi-service-worker.js' // if using web push
})
const reactContainer = ref<HTMLElement>()
let root: any = null
const renderReactComponent = () => {
if (!reactContainer.value) return
if (root) {
root.unmount()
}
root = createRoot(reactContainer.value)
const providerElement = createElement(
NotificationAPIProvider,
{
clientId: props.clientId,
userId: props.userId,
apiURL: props.apiURL,
wsURL: props.wsURL,
customServiceWorkerPath: props.customServiceWorkerPath // if using web push
},
createElement(NotificationPopup)
)
root.render(providerElement)
}
onMounted(() => {
renderReactComponent()
})
onUnmounted(() => {
if (root) {
root.unmount()
}
})
watch(() => [props.clientId, props.userId], () => {
renderReactComponent()
}, { deep: true })
</script>
Then add this component to your page:
<template>
<div>
<h1>My Nuxt 3 App</h1>
<!-- Basic In-App Popup -->
<NotificationAPIWrapper
:client-id="clientId"
:user-id="userId"
:api-u-r-l="apiURL"
:ws-u-r-l="wsURL"
:custom-service-worker-path="customServiceWorkerPath" // if using web push
/>
</div>
</template>
<script setup lang="ts">
// Configuration
const clientId = "YOUR_CLIENT_ID"
const userId = "USER_ID"
const apiURL="api.ipanoitacifiton.com" // see step 3 for url if in CA or EU regions
const wsURL="ws.ipanoitacifiton.com"
const customServiceWorkerPath = "/notificationapi-service-worker.js" // add to public folder if using web push
</script> Create a provider component to avoid SSR/hydration issues in Remix (React Router v7), then wrap your app.
- Create
app/components/NotificationProvider.tsx:
import { useEffect, useState } from 'react';
import {
NotificationAPIProvider,
NotificationPopup
} from '@notificationapi/react';
interface NotificationProviderProps {
children: React.ReactNode;
}
export default function NotificationProvider({
children
}: NotificationProviderProps) {
const [isClient, setIsClient] = useState(false);
useEffect(() => {
setIsClient(true);
}, []);
// Only render on client side to avoid SSR issues
if (!isClient) {
return <>{children}</>;
}
return (
<NotificationAPIProvider
userId="3a96859c-fc4f-4f4a-85c0-89313b533a53"
clientId="o93otcvvcp87us1yhy5e04d6q5"
apiURL="api.ipanoitacifiton.com"
wsURL="ws.ipanoitacifiton.com"
>
{children}
<NotificationPopup
buttonStyles={{
width: 40,
height: 40,
backgroundColor: '#1890ff'
}}
popoverPosition={{
anchorOrigin: {
vertical: 'bottom',
horizontal: 'center'
}
}}
iconColor="#ffffff"
buttonIconSize={20}
popupWidth={400}
popupHeight={500}
/>
</NotificationAPIProvider>
);
}- Wrap your app in
app/root.tsx:
import {
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
isRouteErrorResponse
} from 'react-router';
import type { Route } from './+types/root';
import './app.css';
import NotificationProvider from './components/NotificationProvider';
export function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<NotificationProvider>{children}</NotificationProvider>
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}
export default function App() {
return <Outlet />;
}Why this setup?
Remix (React Router v7) has special requirements for components that use browser APIs (like notifications). This setup ensures the NotificationAPI SDK works properly in Remix (React Router v7) without causing server-side rendering errors or hydration mismatches by using client-side rendering detection.
This component handles Next.js requirements by using βuse clientβ and dynamic imports to prevent server-side rendering issues.
- Create
src/components/NotificationProvider.tsx.
'use client';
import { NotificationAPIProvider } from '@notificationapi/react';
import dynamic from 'next/dynamic';
const NotificationPopup = dynamic(
() => import('@notificationapi/react').then((mod) => mod.NotificationPopup),
{
ssr: false
}
);
interface NotificationProviderProps {
children: React.ReactNode;
}
export default function NotificationProvider({
children
}: NotificationProviderProps) {
return (
<NotificationAPIProvider
userId="3a96859c-fc4f-4f4a-85c0-89313b533a53"
clientId="o93otcvvcp87us1yhy5e04d6q5"
apiURL="api.ipanoitacifiton.com"
wsURL="ws.ipanoitacifiton.com"
>
{children}
<NotificationPopup
buttonStyles={{
width: 40,
height: 40,
backgroundColor: '#1890ff'
}}
popoverPosition={{
anchorOrigin: {
vertical: 'bottom',
horizontal: 'center'
}
}}
iconColor="#ffffff"
buttonIconSize={20}
popupWidth={400}
popupHeight={500}
/>
</NotificationAPIProvider>
);
}- Wrap your app in
src/app/layout.tsx:
import NotificationProvider from '@/components/NotificationProvider';
export default function RootLayout({
children
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<NotificationProvider>{children}</NotificationProvider>
</body>
</html>
);
}Why this setup?
Next.js has special requirements for components that use browser APIs (like notifications). This setup ensures the NotificationAPI SDK works properly in Next.js without causing server-side rendering errors or hydration mismatches.
Create your custom notifications component
import {
Component,
OnInit,
OnDestroy,
Inject,
PLATFORM_ID
} from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { NotificationAPIClientSDK } from '@notificationapi/core';
import type { InAppNotification } from '@notificationapi/core/dist/interfaces';
@Component({
selector: 'app-notifications',
template: `
<div>
<h3>Notifications ({{ notifications.length }})</h3>
<!-- Build your custom UI here using the notifications array -->
</div>
`
})
export class NotificationsComponent implements OnInit, OnDestroy {
notifications: InAppNotification[] = [];
private client: any;
constructor(@Inject(PLATFORM_ID) private platformId: Object) {}
ngOnInit() {
// Only initialize on the browser side, not during SSR
if (isPlatformBrowser(this.platformId)) {
this.client = NotificationAPIClientSDK.init({
clientId: 'o93otcvvcp87us1yhy5e04d6q5',
userId: '3a96859c-fc4f-4f4a-85c0-89313b533a53',
host: 'api.ipanoitacifiton.com',
websocketHost: 'ws.ipanoitacifiton.com',
onNewInAppNotifications: (newNotifications: InAppNotification[]) => {
this.notifications = [...newNotifications, ...this.notifications];
}
});
// Open websocket for real-time notifications
this.client.openWebSocket();
// Identify the user
this.client.identify({
id: '3a96859c-fc4f-4f4a-85c0-89313b533a53'
});
// Get existing notifications
this.client
.getInAppNotifications({
before: new Date().toISOString(),
maxCountNeeded: 50
})
.then((result: { items: InAppNotification[] }) => {
this.notifications = result.items;
})
.catch((error: any) => {
console.error('Error loading notifications:', error);
});
}
}
ngOnDestroy() {
if (this.client && isPlatformBrowser(this.platformId)) {
this.client.closeWebSocket();
}
}
} Create your custom notifications component:
<script setup>
import { ref, onMounted } from 'vue';
import { NotificationAPIClientSDK } from '@notificationapi/core';
const notifications = ref([]);
onMounted(() => {
const client = NotificationAPIClientSDK.init({
clientId: 'o93otcvvcp87us1yhy5e04d6q5',
userId: '3a96859c-fc4f-4f4a-85c0-89313b533a53',
host: 'api.ipanoitacifiton.com',
websocketHost: 'ws.ipanoitacifiton.com',
onNewInAppNotifications: (newNotifications) => {
notifications.value = [...newNotifications, ...notifications.value];
}
});
// Open websocket for real-time notifications
client.openWebSocket();
// Identify the user
client.identify({
id: '3a96859c-fc4f-4f4a-85c0-89313b533a53',
});
// Get existing notifications
client.getInAppNotifications({
before: new Date().toISOString(),
maxCountNeeded: 50,
}).then((result) => {
notifications.value = result.items;
}).catch((error) => {
console.error('Error loading notifications:', error);
});
console.log('Current notifications:', notifications.value);
});
</script>
<template>
<div>
<h3>Notifications ({{ notifications.length }})</h3>
<!-- Build your custom UI here using the notifications array -->
</div>
</template> Use JS Core for custom implementations and headless integrations. This provides you with the core functionality without any UI components, giving you full control over the presentation.
What JS Core provides:
- Real-time notification delivery via WebSocket
- Notification state management (read/unread, archived)
- User preference handling
- Custom event callbacks for notification actions
- Complete control over UI design and behavior
Basic Integration:
<div id="notification-container"></div>
<script type="module">
import NotificationAPI from '@notificationapi/js-core';
const client = new NotificationAPI({
clientId: 'YOUR_CLIENT_ID',
userId: 'USER_ID'
});
// Option 1: Use built-in UI widget
client.showInApp({
root: 'notification-container'
});
// Option 2: Build custom UI with headless mode
client.onNewNotification((notification) => {
// Handle new notifications with your custom UI
console.log('New notification:', notification);
});
</script> 2. Send Notifications from Your Backend
Install the Server-Side SDK:
npm install notificationapi-node-server-sdk pip install notificationapi_python_server_sdk composer require notificationapi/notificationapi-php-server-sdk go get github.com/notificationapi-com/notificationapi-go-server-sdk dotnet add package NotificationAPI --version 0.5.0 Add the following dependency to your Maven project:
<dependency>
<groupId>com.notificationapi</groupId>
<artifactId>notificationapi-java-server-sdk</artifactId>
<version>0.2.0</version>
</dependency>For optimal functionality, youβll also need:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency> Add the NotificationAPI class to your application - see the full Ruby implementation.
Now, send an in-app notification that will appear in your userβs notification center:
Replace YOUR_CLIENT_ID and YOUR_CLIENT_SECRET with the values from the
code sample in your NotificationAPI dashboard. These values can also be found
in the Environments section of the dashboard.
import notificationapi from 'notificationapi-node-server-sdk';
// Initialize (default US region)
// For CA region: add 'https://api.ca.notificationapi.com' after CLIENT_SECRET
// For EU region: add 'https://api.eu.notificationapi.com' after CLIENT_SECRET
notificationapi.init('YOUR_CLIENT_ID', 'YOUR_CLIENT_SECRET');
// Send in-app notification
notificationapi.send({
type: 'task_assigned',
to: {
id: 'user123' // Required: user ID for in-app notifications
},
inapp: {
title: 'Revew quarterly report',
url: 'https://example.com',
image: 'https://example.com/image.png'
}
}); import asyncio
from notificationapi_python_server_sdk import notificationapi
# Initialize (default US region)
notificationapi.init("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")
async def send_inapp():
await notificationapi.send({
"type": "task_assigned",
"to": {
"id": "user123" # Required: user ID for in-app notifications
},
"inapp": {
"title": "Revew quarterly report",
"url": "https://example.com",
"image": "https://example.com/image.png"
}
})
# Run the async function
asyncio.run(send_inapp()) use NotificationAPI\NotificationAPI;
// Initialize
$notificationapi = new NotificationAPI('YOUR_CLIENT_ID', 'YOUR_CLIENT_SECRET');
// Send in-app notification
$notificationapi->send([
"type" => "task_assigned",
"to" => [
"id" => "user123" // Required: user ID for in-app notifications
],
"inapp" => [
"title" => "Review quarterly report",
"url" => "https://example.com",
"image" => "https://example.com/image.png"
]
]); package main
import (
notificationapi "github.com/notificationapi-com/notificationapi-go-server-sdk"
)
func main() {
// Initialize
notificationapi.Init("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET", "https://api.notificationapi.com")
// Send in-app notification
notificationapi.Send(
notificationapi.SendRequest{
Type: "task_assigned",
To: notificationapi.To{
Id: "user123", // Required: user ID for in-app notifications
},
InApp: map[string]interface{}{
"title": "Review quarterly report",
"url": "https://example.com",
"image": "https://example.com/image.png"
}
}
)
} using NotificationApi.Server;
using NotificationApi.Server.Models;
// Initialize
var notificationApi = new NotificationApiServer("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");
var notification = new SendNotificationData
{
Type = "task_assigned",
To = new User {
Id = "user123"
},
Inapp = new Dictionary<string, object> {
{ "title", "Review quarterly report" },
{ "url", "https://example.com" },
{ "image", "https://example.com/image.png" }
}
});
await notificationApi.Send(notification); - Add these dependencies to your
pom.xmlfile:
<dependencies>
<dependency>
<groupId>com.notificationapi</groupId>
<artifactId>notificationapi-java-server-sdk</artifactId>
<version>0.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
</dependencies>- Create and send a notification:
package com.example;
import com.notificationapi.NotificationApi;
import com.notificationapi.model.*;
public class Example {
public static void main(String[] args) {
NotificationApi api = new NotificationApi("CLIENT_ID", "CLIENT_SECRET");
// Create user
User user = new User("user123");
// Create and send notification request
NotificationRequest request = new NotificationRequest("task_assigned", user)
.setInapp(new InAppOptions()
.setTitle("Review quarterly report")
.setUrl("https://example.com")
.setImage("https://example.com/image.png")
);
System.out.println("Sending notification request...");
String response = api.send(request);
System.out.println("Response: " + response);
}
} # Initialize
notificationapi = NotificationAPI.new("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")
# Send in-app notification
notificationapi.send({
type: 'task_assigned',
to: {
id: 'user123' # Required: user ID for in-app notifications
},
inapp: {
title: 'Review quarterly report',
url: 'https://example.com',
image: 'https://example.com/image.png'
}
}) Youβre All Set!
π Congrats! Youβre now sending and displaying in-app notifications!
For more advanced features like custom click actions, batching, and UI customization, check out our In-App Channel documentation.