Agent Wranglers

In-app notifications Recommended

Keep read state the same everywhere

Mark an item read once on the server, and clear it in every open tab, every device badge and any pending reminder.

How to do it

Set read_at with a conditional update, so a second click changes nothing. Opening the page an item links to marks it read, as does a tap on its push. Broadcast the change to the user's other sessions over the live channel. Cancel any queued push or email for the same event, as in send one message per event. Update the app badge with the Badging API or the platform's badge count.

Example

app.post('/api/notifications/:id/read', requireUser, async (req, res) => {
  const changed = await db.query(
    'UPDATE notifications SET read_at = now() WHERE id = $1 AND user_id = $2 AND read_at IS NULL',
    [req.params.id, req.user.id]);
  if (changed.rowCount) await live.publish(req.user.id, { kind: 'read', id: req.params.id });
  res.sendStatus(204);
});
@app.post("/api/notifications/<int:item_id>/read")
@login_required
def mark_read(item_id):
    changed = db.execute(
        "UPDATE notifications SET read_at = now() WHERE id = %s AND user_id = %s AND read_at IS NULL",
        (item_id, current_user.id)).rowcount
    if changed:
        live.publish(current_user.id, {"kind": "read", "id": item_id})
    return "", 204

How to check

Open the inbox in two tabs and read an item in one. The other tab's unread count changes within 2 seconds. A pending reminder email for that item is not sent.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers notifications playbook: https://agentwranglers.se/playbook/notifications/in-app-notifications/read-state-sync.