Notifications
Notifications are aggregated per app. Each app registers one or more notification sources, and the topbar refresh joins the results from every registered source into a single feed.
The polling interval comes from config/command-center.yaml at app.notifications_refresh_interval_ms.
If that key is omitted, the runtime falls back to 300000 milliseconds (5 minutes).
Contract
Backend payloads must match the visible notification serializer contract used by the UI:
class VisibleNotificationSerializer(serializers.ModelSerializer):
is_read = serializers.BooleanField(read_only=True)
class Meta:
model = Notification
fields = [
"id",
"type",
"created_at",
"title",
"description",
"meta_data",
"is_global",
"target_user",
"target_distribution_list",
"include_email",
"is_read",
]
Frontend payload type: src/notifications/types.ts
App Registration
Apps opt into notifications by adding notificationSources to their AppDefinition in
src/apps/types.ts.
Each source registers its own endpoints:
listPathdetailPathoptionalmarkReadPathoptionaldismissPathoptionalmarkAllReadPathoptionaldismissAllPathoptionalbaseUrloptionallistQueryoptional
Example:
notificationSources: [
{
id: "main-sequence-notifications",
title: "Main Sequence",
listPath: "/user/api/notifications/",
detailPath: "/user/api/notifications/{id}/",
markReadPath: "/user/api/notifications/{id}/mark-read/",
dismissPath: "/user/api/notifications/{id}/dismiss/",
markAllReadPath: "/user/api/notifications/mark-all-read/",
dismissAllPath: "/user/api/notifications/dismiss-all/",
listQuery: { limit: 50 },
},
],
Current Main Sequence Workbench registration: extensions/main_sequence/extensions/workbench/index.ts
Aggregation
On refresh, the client:
- collects notification sources from accessible apps
- fetches each source in parallel
- normalizes every item with its app/source metadata
- merges and sorts the final list by
created_at
Aggregation code: src/notifications/api.ts
Normalization helpers: src/notifications/registry.ts
Rendering
The bell menu renders the merged feed and routes per-item actions back to the source that produced that notification.
Menu UI: src/app/layout/NotificationsMenu.tsx
The menu query uses commandCenterConfig.app.notificationsRefreshIntervalMs as its
refetchInterval, so changing the YAML value changes how often notifications refresh.