一键导入
iblai-vibe-notification
Add notification bell and center page to your Next.js app
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Add notification bell and center page to your Next.js app
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Build and run your ibl.ai app on desktop and mobile (iOS, Android, macOS, Surface)
Add the agent Sandbox tab (OpenClaw instance management, agent prompt configuration, and agent skills) to your Next.js app
Add the agent Access tab (role-based access control for editor and chat roles) to your Next.js app
Add the agent Audit tab (audit log of who changed what and when, with user/date/action filters) to your Next.js app
Wrap the Chat surface with the SDK's AppSidebar — projects dropdown, pinned/recent messages, and host-supplied content/footer menu items
Add the in-process Chat SDK component (full agent surface — message stream, canvas, file attach, voice, prompts) to a Next.js app
| name | iblai-vibe-notification |
| description | Add notification bell and center page to your Next.js app |
| globs | null |
| alwaysApply | false |
Add notification features -- a compact bell icon with unread badge for your navbar and a full notification center page with Inbox and Alerts tabs.

Template: the bell this skill creates is bundled as
assets/notification-bell.tsx.j2. See/iblai-vibe-scaffoldfor the{{ }}contract.
Do NOT add custom styles to ibl.ai SDK components — they ship with their own styling. Do NOT implement dark mode unless asked.
Follow the component hierarchy: use ibl.ai SDK components
(@iblai/iblai-js) first, then shadcn/ui (npx shadcn@latest add <name>).
Navbar: If the user wants a navbar with the bell, send them to
/iblai-vibe-navbarfirst.
Before running this skill, ask the user:
Are you starting a new project from scratch? vibe-starter (https://github.com/iblai/vibe-starter/tree/spa) already ships the notification bell and /notifications page wired up, alongside auth, navbar, and profile/account. Want to use that instead?
If yes, clone into a temp directory and copy into the current directory before installing (running pnpm install inside the cloned subdirectory causes hardlink issues), then skip this skill:
git clone -b spa https://github.com/iblai/vibe-starter.git vibe-starter-init
cp -a vibe-starter-init/. . && rm -rf vibe-starter-init
pnpm install --ignore-scripts
Run with
--ignore-scriptsto skip package lifecycle (postinstall) scripts.
If they prefer to add notifications to an existing app, continue below.
/iblai-vibe-auth)@iblai/mcp in .mcp.json)iblai.env populated with PLATFORM, DOMAIN, TOKEN. If missing,
tell the user to download the template:
curl -o iblai.env https://raw.githubusercontent.com/iblai/vibe/refs/heads/main/iblai.envRender assets/notification-bell.tsx.j2
into components/iblai/notification-bell.tsx (substitute {{ }}
placeholders) — a bell with unread badge. Reads userData and tenant from
localStorage; returns null when unauthenticated.
Use MCP for full props/examples:
get_component_info("NotificationDropdown")
get_component_info("NotificationDisplay")
<NotificationDropdown> — bell icon for the navbar| Prop | Type | Description |
|---|---|---|
org | string | Platform key |
userId | string | Username |
onViewNotifications | (id?) => void? | "View all" callback |
className | string? | Additional CSS class |
<NotificationDisplay> — full notification center page| Prop | Type | Description |
|---|---|---|
org | string | Platform key |
userId | string | Username |
isAdmin | boolean? | Shows Alerts tab + Send button |
selectedNotificationId | string? | Pre-select a notification |
enableRbac | boolean? | Enable RBAC permission checks |
Derive isAdmin from the tenants array in localStorage.
| Feature | Everyone | Admin |
|---|---|---|
| Inbox, mark as read | ✓ | ✓ |
| Send notification, Alerts tab | ✓ |
Run /iblai-vibe-ops-test before reporting done:
pnpm build && pnpm test
pnpm dev &
npx playwright screenshot http://localhost:3000/notifications /tmp/notifications.png
@iblai/iblai-js/web-containers (framework-agnostic).mentorReducer and mentorMiddleware.initializeDataLayer() takes 5 args (data-layer v1.2+).@reduxjs/toolkit deduped via webpack aliases in next.config.ts.Base URL:
${dmUrl}/api/notification/v1/—dmUrlis the first arg passed toinitializeDataLayer()(sourced fromNEXT_PUBLIC_API_BASE_URL). Auth:Authorization: Token <token>Live OpenAPI: https://api.iblai.app/dm/api/docs/schema/swagger-ui/
The SDK's RTK Query hooks (useGetUserNotificationsQuery,
useGetNotificationCountQuery, useUpdateNotificationStatusMutation,
useMarkAllNotificationsReadMutation, …) wrap most endpoints. Drop down
to raw HTTP only for admin endpoints not yet exposed as hooks (template
PATCH, builder send, SMTP test). Discover hooks via
get_api_query_info(...) in MCP. {org} and {platform_key} are the
same value (the platform slug).
| Method | Path | Purpose |
|---|---|---|
GET | /orgs/{org}/users/{user_id}/notifications/ | List user notifications. Query: status, channel, exclude_channel, start_date, end_date, page |
PUT | /orgs/{org}/users/{user_id}/notifications/ | Update status. Body: {notification_id: "uuid,uuid", status: "READ|UNREAD|CANCELLED"} |
PATCH | /orgs/{org}/users/{user_id}/notifications/bulk-update/ | Set status on all user notifications. Body: {status} |
DELETE | /orgs/{org}/users/{user_id}/notifications/{id}/ | Delete one notification |
GET | /orgs/{org}/users/{user_id}/notifications-count/ | Count. Query: status, channel. Returns {count} |
POST | /orgs/{platform_key}/mark-all-as-read | Mark all (or notification_ids[]) read |
GET | /orgs/{org}/notifications/ / PUT / PATCH .../bulk-update/ | Org-wide variants (admin) |
Status values: READ, UNREAD, CANCELLED. Notification record:
{id, username, title, body, status, channel, context, short_message, created_at, updated_at}.
Templates inherit defaults; the first PATCH clones the default into a
platform-specific copy. reset deletes the override (toggle state is
preserved).
| Method | Path | Purpose |
|---|---|---|
GET | /platforms/{platform_key}/templates/ | List templates (system + custom) |
GET | /platforms/{platform_key}/templates/{type}/ | Template detail |
PATCH | /platforms/{platform_key}/templates/{type}/ | Customize template |
PATCH | /platforms/{platform_key}/templates/{type}/toggle/ | Body: {allow_notification: bool} |
POST | /platforms/{platform_key}/templates/{type}/reset/ | Revert to default |
POST | /platforms/{platform_key}/templates/{type}/test/ | Send test email. Body: {context?} |
Writable on PATCH: name, description, message_title,
message_body, short_message_body, email_subject,
email_from_address, email_html_template, spa_ids[], channel_ids[].
For PROACTIVE_LEARNER_NOTIFICATION, POLICY_ASSIGNMENT, and
HUMAN_SUPPORT_NOTIFICATION only their config fields are writable
(content is read-only). See "Special types" below.
Templates use Django syntax ({{ var }}, {% if %}, {% for %}).
email_html_template is sanitized by bleach — <script>, <iframe>,
<form>, event-handler attributes, and javascript: URLs are stripped.
System types include: USER_NOTIF_USER_REGISTRATION,
APP_REGISTRATION, USER_NOTIF_COURSE_ENROLLMENT,
USER_NOTIF_COURSE_COMPLETION, USER_NOTIF_CREDENTIALS,
USER_NOTIF_LEARNER_PROGRESS, USER_NOTIF_USER_INACTIVITY,
PLATFORM_INVITATION, COURSE_INVITATION, PROGRAM_INVITATION,
COURSE_LICENSE_ASSIGNMENT, COURSE_LICENSE_GROUP_ASSIGNMENT,
PROGRAM_LICENSE_ASSIGNMENT, PROGRAM_LICENSE_GROUP_ASSIGNMENT,
USER_LICENSE_ASSIGNMENT, USER_LICENSE_GROUP_ASSIGNMENT,
ROLE_CHANGE, ADMIN_NOTIF_COURSE_ENROLLMENT, POLICY_ASSIGNMENT,
HUMAN_SUPPORT_NOTIFICATION, PROACTIVE_LEARNER_NOTIFICATION,
REPORT_COMPLETED, CUSTOM_NOTIFICATION,
ACTIVITY_COURSE_MILESTONE, ACTIVITY_NEW_CONTENT,
COURSES_PROGRESS_SUMMARY, PATHWAY_ENROLLMENT_CONFIRMATION,
PROGRAM_ENROLLMENT_CONFIRMATION, SKILL_MASTERY_CHANGE. Per-type
template variables are returned in available_context from the GET
detail endpoint.
Admin-only. Flow: context → validate → preview → send.
| Method | Path | Purpose |
|---|---|---|
GET | /orgs/{platform_key}/notification-builder/context/ | Returns {templates[], channels[], sources[]} |
POST | /orgs/{platform_key}/notification-builder/validate_source/ | Body: {type, data}. Returns valid/invalid counts + sample |
POST | /orgs/{platform_key}/notification-builder/preview/ | Returns {build_id, count, warning, recipients[]} |
GET | /orgs/{platform_key}/notification-builder/{build_id}/recipients/ | Paginated. Query: search, page, page_size |
POST | /orgs/{platform_key}/notification-builder/send/ | Body: {build_id} |
Preview body:
{
"template_id": "uuid", // OR template_data — not both
"template_data": { "message_title": "...", "message_body": "..." },
"channels": [1, 2],
"sources": [{ "type": "email", "data": "a@x.com,b@x.com" }],
"context": { "course_name": "Python 101" },
"process_on": "2026-05-01T09:00:00Z" // optional, for scheduled send
}
Source types: email, username, platform, csv (multipart with
file_0), department, pathway, program, usergroup. Recipients
are merged + deduped across sources. Duplicate suppression: SHA-256 hash
of recipients+template+channels — if matched within 24h, send returns
"Similar notifications found".
| Method | Path | Body |
|---|---|---|
POST | /orgs/{org}/users/{user_id}/register-fcm-token/ | {name, registration_id, active?, cloud_message_type?, application_id?} |
DELETE | /orgs/{org}/users/{user_id}/register-fcm-token/ | {registration_id} |
| Method | Path | Purpose |
|---|---|---|
POST | /platforms/{platform_key}/config/test-smtp/ | Verify SMTP. Body: {smtp_host, smtp_port, smtp_username, smtp_password, use_tls?, use_ssl?, test_email, from_email?} |
use_tls (port 587) and use_ssl (port 465) are mutually exclusive.
| Method | Path | Purpose |
|---|---|---|
GET | /campaigns/unsubscribe/{unsubscribe_hash}/ | Public — unsubscribe link target |
POST | /orgs/{platform_key}/campaigns/enable/ | Re-enable. Body: {campaign_id, campaign_title, email} |
POST | /orgs/{platform_key}/campaigns/exclude/ | Opt-out. Body: same |
PATCH)HUMAN_SUPPORT_NOTIFICATION{
"human_support_recipient_mode": "platform_admins_and_mentor_owner",
"human_support_custom_recipients": [
{ "type": "user", "id": 42 },
{ "type": "user_group", "id": 7 },
{ "type": "rbac_policy", "policy_name": "Support Staff" }
]
}
recipient_mode: platform_admins_and_mentor_owner (default),
platform_admins_only, mentor_owner_only, custom.
POLICY_ASSIGNMENT{
"policy_notify_on_assignment": true,
"policy_notify_on_removal": true,
"policy_enabled_policies": [
{ "role_name": "Analytics Viewer", "enabled": true, "subject": "..." }
]
}
Empty policy_enabled_policies = global flags apply to all roles.
Non-empty = only listed roles trigger notifications.
PROACTIVE_LEARNER_NOTIFICATION{
"periodic_frequency": "WEEKLY",
"periodic_report_period_days": 7,
"periodic_execution_time": "09:00",
"periodic_timezone": "UTC",
"periodic_learner_scope": "ACTIVE_LEARNERS",
"periodic_custom_interval_days": 7,
"periodic_mentors": [
{ "unique_id": "uuid", "prompt": "Summarize {{student_name}}'s progress.", "name": "Coach" }
]
}
frequency: DAILY, WEEKLY, MONTHLY, CUSTOM. learner_scope:
ACTIVE_LEARNERS or ALL_LEARNERS. Empty mentors = use all platform
agents.
Ibl.Notifications/Notification/{list,write,delete},
Ibl.Notifications/NotificationTemplate/{list,read,write},
Ibl.Notifications/SMTP/action, Ibl.Notifications/Campaigns/action.
curl "${dmUrl}/api/notification/v1/orgs/acme-learning/users/jane.doe/notifications/?status=UNREAD" \
-H "Authorization: Token ${TOKEN}"
curl -X PATCH "${dmUrl}/api/notification/v1/platforms/acme-learning/templates/USER_NOTIF_COURSE_ENROLLMENT/" \
-H "Authorization: Token ${TOKEN}" -H "Content-Type: application/json" \
-d '{"email_subject": "Welcome to {{ course_name }}"}'