Skip to main content
Hayon notifies you the moment something happens to one of your posts — whether it succeeded, failed, or was created. Notifications are delivered through two parallel channels: real-time WebSocket events for the browser and Firebase Cloud Messaging (FCM) for mobile push notifications.

Notification channels

Real-time (Socket.io)

Instant in-app notifications delivered over a persistent WebSocket connection while your dashboard is open. No polling required.

Push (Firebase)

Firebase Cloud Messaging push notifications sent to your registered device even when the dashboard is closed.

Notification types

Notifications are created at two points in the post lifecycle:
Fired immediately after POST /api/posts succeeds. The message reflects the initial status:
“Your post was created successfully and is now pending.”
Or for a scheduled post:
“Your post was created successfully and is now scheduled.”
Notification type: success
Fired by the PostWorker after each platform successfully accepts the post:
“Your post has been successfully posted on bluesky”
The notification includes a link to the live post URL (platformPostUrl) and the first media item’s image as a preview.Notification type: success
When a platform permanently rejects a post (after exhausting retries), the worker records a failed platform status. You can view the error reason from the post detail page and trigger a retry from /history.Notification type: error (implicit via platform status)

Notification data model

Each notification document stores:
FieldTypeDescription
userIdObjectIdThe user this notification belongs to.
messagestringHuman-readable notification text.
typestringsuccess, error, info, or warning.
reference.typestringThe referenced entity type (e.g. post).
reference.idstringThe referenced entity’s ID.
reference.modelstringThe Mongoose model name (e.g. Post).
options.imagestringOptional preview image URL.
options.linkstringOptional deep link (e.g. /history).
readbooleanWhether the user has seen this notification.
createdAtDateTimestamp managed by Mongoose timestamps.

Notification center

The bell icon in the dashboard header opens the Notification Center, which shows a reverse-chronological list of your recent notifications with unread indicators.
1

View notifications

Click the bell icon to open the notification drawer. Unread notifications are highlighted. The list is paginated — the default page size is 20.
2

Mark as read

Click a single notification to mark it as read. This calls PATCH /api/notifications/:id/read and updates the read field to true.
3

Mark all as read

Use the Mark all as read button to dismiss all unread notifications at once. This calls PATCH /api/notifications/read-all.

Notification API

Fetch notifications

GET /api/notifications Returns a paginated list of notifications for the authenticated user, ordered most-recent first.
curl -X GET "https://api.yourhayon.com/api/notifications?page=1&limit=20" \
  -H "Authorization: Bearer <token>"
200 response
{
  "data": {
    "notifications": [
      {
        "_id": "664f1a2b3c4d5e6f7a8b9c0e",
        "message": "Your post has been successfully posted on bluesky",
        "type": "success",
        "reference": {
          "type": "post",
          "id": "664f1a2b3c4d5e6f7a8b9c0d",
          "model": "Post"
        },
        "options": {
          "link": "https://bsky.app/profile/yourhandle/post/xyz"
        },
        "read": false,
        "createdAt": "2026-03-22T10:15:00.000Z"
      }
    ],
    "total": 42,
    "page": 1,
    "limit": 20
  }
}

Mark a notification as read

PATCH /api/notifications/:id/read
curl -X PATCH "https://api.yourhayon.com/api/notifications/664f1a2b3c4d5e6f7a8b9c0e/read" \
  -H "Authorization: Bearer <token>"

Mark all notifications as read

PATCH /api/notifications/read-all
curl -X PATCH "https://api.yourhayon.com/api/notifications/read-all" \
  -H "Authorization: Bearer <token>"

WebSocket connection (Socket.io)

Hayon uses Socket.io for real-time delivery. The frontend connects to the Socket.io server on page load and joins a room scoped to the authenticated user’s ID.
Connecting to the notification socket
import { io } from "socket.io-client";

const socket = io(process.env.NEXT_PUBLIC_API_URL, {
  auth: { token: "<your-jwt-token>" },
});

// Listen for incoming notifications
socket.on("notification", (notification) => {
  console.log("New notification:", notification.message);
});

// Clean up on unmount
return () => socket.disconnect();
The socket connection is authenticated using the same JWT used for REST API calls. Unauthenticated connections are rejected by the server.

Firebase push notifications

Firebase Cloud Messaging delivers notifications to your device when the dashboard is not open. To receive push notifications:
1

Grant browser permission

The dashboard requests notification permission from your browser on first load. Accept the prompt to enable push delivery.
2

FCM token is registered

After permission is granted, Firebase generates a device-specific FCM token. The dashboard sends this token to the backend to associate it with your account.
3

Notifications are delivered

When the NotificationService creates a notification, it also sends an FCM message to all registered tokens for the user. The notification appears as a native browser or mobile push alert.
FCM push notifications require HTTPS in production. During local development, push delivery is typically disabled. Use the in-app notification center to verify notifications during development.

Managing notification preferences

Notification preferences are managed from the Settings page at /settings. From there you can:
  • Enable or disable push notifications for your device.
  • Revoke FCM token registration to stop receiving push notifications on a specific device.
  • Review recent notification history in the notification center.
If you stop receiving push notifications, check that your browser notification permission is still granted. You may need to re-grant permission if it was blocked or reset by the browser.

Build docs developers (and LLMs) love