All features
Operations

Persistent Notification Inbox

A bell badge that actually remembers what you've seen — badge reflects genuine new activity, not the same items on every reload.

The notification bell now connects to a server-side inbox. Matches, compliance overdue items, urgent staffing requests, and proposal deadlines persist between page loads. Mark individual items or everything at once — the badge stays at zero until something genuinely new happens.

What you get

Built to solve the actual problems hiring teams hit every day.

Persistent across sessions

Notifications are stored in the database. A refresh doesn't reset the badge — only new events do.

Deduplication built-in

A UNIQUE constraint on (profile, event type, resource) prevents the same event from appearing twice, even across repeated cron runs.

Mark all read in one click

One button sets read_at on every unread notification. The badge drops to zero immediately.

Read state preserved

Once you mark a notification read, re-running the cron that generated it does not reset the read state.

Role-aware visibility

Each notification is scoped to the profile that generated it. Candidates see their matches; clients see urgent reqs and proposal deadlines.

How it works

Four steps from setup to value.

1

Events persist on the server

When proposals enter their 7-day window, the cron upserts a notification row for each org member — the badge increments next time they open the app.

2

Badge reflects real unread count

GET /api/notifications returns only your unread rows. The badge is the count of rows where read_at is null.

3

Click the bell

The panel lists your 20 most recent notifications. Unread items have a blue dot; read items are dimmed.

4

Mark all read

Click "Mark all read" in the panel header. All unread rows are updated server-side; the badge drops to zero.

FAQ

Quick answers to common questions.

Why did my badge reset on every reload before?

Notifications were built entirely in-memory from live queries. There was no persistence layer, so read_at was always null, and the badge always showed the full count.

Will the same notification appear twice?

No. The UNIQUE(profile_id, type, resource_id) index means a cron re-run for the same proposal (or match, or compliance item) silently ignores the duplicate insert and leaves your existing row's read_at intact.

What events generate inbox notifications?

Currently: proposals due within 7 days (generated by the daily proposal scan). The same pattern extends to matches, compliance overdue items, and urgent staffing requests as those crons are updated.

Explore other features