---
title: Notifications & Web Push
description: Configure Chatto notifications, Web Push, VAPID keys, device behavior, and operator expectations.
---
import { Aside, CardGrid, LinkCard, Tabs, TabItem } from "@astrojs/starlight/components";
Chatto has persistent in-app notifications and optional browser Web Push. Operators configure whether push is available; members decide which rooms, threads, and devices should alert them.
## How Notifications Work
Chatto creates persistent notifications for attention-worthy events:
| Event | Default behavior |
| ----- | ---------------- |
| Room invitations | Notify the invited user; open the room to respond. |
| DM messages | Notify the recipient. |
| Root messages in channel rooms | Add a neutral room dot by default. |
| Direct `@username` mentions | Notify the mentioned user. |
| Role, `@all`, and `@here` mentions | Notify matching recipients, with confirmation for broad sends. |
| Replies to your message | Notify you. |
| Followed thread replies | Notify followers. |
| Reactions to your messages | Add a non-interruptive notification by default. |
Notifications are stored for the user, survive browser restarts, sync across tabs and devices, and normally expire after 90 days. Invitation notifications disappear when the invitation is accepted, declined, or expires. Read and Delete changes synchronize everywhere for that user.
## Desktop Alerts
In Chatto Desktop, enable **Push notifications on this device** in notification
settings. The choice applies to every signed-in server on this device. Use
**Send test notification** to check delivery. If no alert appears, check your
operating system's notification settings for Chatto.
Desktop alerts identify the actor, activity, and room where applicable. Activity
labels use your selected language. Alerts include message text when it is
already loaded in the client; other alerts show the activity summary. Your OS can
show names and previews on the lock screen; use its notification settings to
control this. Desktop alerts respect Do Not
Disturb and apply to new Important notifications that need your attention.
Alerts from inactive servers can arrive at the next notification poll. Desktop
alerts do not require the Web Push server configuration below.
On macOS, closing the window keeps Chatto running. Select Chatto in the Dock to
open it again. **Command-Q** quits the app and stops new alerts. On Windows and
Linux, closing the main window quits the app. Chatto adds no menu bar or system
tray icon. Click an alert to open its conversation.
## Notification Centre
Press **Option/Alt+Shift+Down** to open the next unread notification source
across your signed-in servers. You can also select **Go to next unread source**
in the **Cmd/Ctrl+K** quick switcher. Important notifications come first, then
Ambient notifications, then rooms with plain unread dots. Repeat the shortcut to
visit the remaining sources. It works from the message composer and preserves
your draft; it is inactive while a dialog is open.
Press **Cmd/Ctrl+Shift+K** to see the available app and message-editor shortcuts.
The list follows your editor and send-mode preferences. **Escape** closes help
and returns focus to your previous field. **Cmd/Ctrl+/** still opens room search
or focuses filters. You can also open **Cmd/Ctrl+K** and select the
**Keyboard shortcuts** (?) button.
Open the notification centre as its own page from the bell in the app header.
It combines notifications from all your signed-in servers. The current server's
sidebar stays available, and the back arrow returns to its last room.
Use **All notifications** or **Unread** to select which activity to show. Combine this with
**Reactions**, **Replies**, or **Mentions** to narrow the list. Replies include
activity in followed threads. Mentions include direct, role, @here, and @all
mentions. **Dismiss read** removes read notifications across all servers,
including those outside the selected filters.
The list is chronological:
- Notification rows use neutral backgrounds for all activity types.
- Unread notifications show their summary in bold. Read notifications stay in the same chronological list with muted text in regular weight.
- Delete permanently removes a notification from the list.
Related activity is grouped by DM, room, thread, or reacted-to message. Opening a group goes to its newest unread event, or its newest event when everything in the group is read. Reading a room or thread marks covered notifications read. Chatto reads only up to the newest message that you can see. If you open an older message, newer notifications stay unread until you scroll to them. Message notifications expire 90 days after their source activity. Invitation notifications open the room welcome screen and become Read after navigation. Reading or deleting the notification does not accept or decline the invitation.
## Notification Policy
Members use a matrix to control each notification cause at server, room-group, and room scope. The rows contain the ten notification causes. The columns contain the server, visible room groups and their joined or invited channel rooms, and current-member direct-message rooms.
| Mode | Effect |
| ---- | ------ |
| Inherit | Use the next broader room-group or server setting. |
| Off | Do not create attention for this cause. |
| Unread dot | Add only a neutral unread dot. Do not create a notification, play a sound, or send push. |
| In-app notification | Add an in-app notification. Important notifications can play the configured in-app sound, but Chatto does not send push. |
| Push notification | Add the same in-app notification and make it eligible for Web Push or native delivery. |
Room invitations, direct messages, direct mentions, replies, role mentions, `@here`, and `@all` use Push notification by default. Root messages in channel rooms use Unread dot. Followed threads and reactions use In-app notification. A message that matches several causes creates one exact output per cause, so each keeps its own policy and triage identity. The client can still consolidate related activity for display.
Ambient notifications, such as reactions, use a neutral badge and do not play an in-app sound. In the room list, a room shows its Important and Ambient notifications as two separate counts. Each count opens its newest notification. Important notifications use orange indicators and can play your selected sound.
The installed app icon shows an unnumbered badge for Important unread notifications. The window title shows their total count across signed-in servers. Ambient notifications do not contribute to either indicator, even when you enable pushes for them. An Important background push can set the app icon badge when the browser runs the app's notification handler and the server includes the attention level; otherwise, the badge stays unchanged until the app can update it.
The server column always shows a concrete setting. If you have not configured a server preference, the matrix shows the product default at full intensity. Select a server cell to cycle through Off, Unread dot, In-app notification, and Push notification.
Room-group and room cells cycle through Inherit, Off, Unread dot, In-app notification, Push notification, and back to Inherit. A grey crossed bell means Off. A small filled dot means Unread dot. It uses the same size and colour as the room dot: white in dark mode and dark in light mode. An orange bell means In-app notification. An orange phone means Push notification. An inherited value uses the same icon at reduced intensity.
An Unread dot setting uses the neutral dot for its room. Thread Unread dot activity rolls up to its parent room. Reading the room or thread clears covered Unread dot attention. An invitation Unread dot stays until the invitation is accepted, declined, or expires. The dot uses your current settings. If you change a setting from Unread dot to a different setting, unread messages of that type do not show the dot. If you unfollow a thread, its replies do not show the dot. An orange notification dot takes priority over the neutral dot. Unread dot does not change an operating-system or application-icon badge.
Room dots are controlled only by notification policy. If you set Room messages to Off, ordinary root messages do not add a dot. Chatto still keeps the Message Read Cursor and uses it to place the New messages separator when you open the room.
Channel rooms inherit from their current room group, then from the server. Direct-message rooms inherit directly from the server. Chatto uses the current room group and policy when it creates notification output. A room move or policy change can affect source activity that is still waiting for this step. It does not change notification output that Chatto has already created.
The Direct messages row applies to the server and direct-message rooms. The Room messages row applies to the server, room groups, and channel rooms. Cells outside these scopes are not available.
Use the matrix filter to find a group or room. A room match keeps its parent group visible. A group match keeps all of its current-member room columns visible. The server column always remains in the matrix.
## Do Not Disturb
Do Not Disturb does not discard notifications. Chatto still records the pending notification and updates counts, but suppresses interruptive delivery while the user is in DND:
- no notification sound
- no Web Push delivery
- no active interruption
This preserves "review later" behavior without waking the user's devices.
## Enable Web Push
Web Push is disabled until you provide VAPID keys. Without push configuration, the browser app's notification settings show a notice that push notifications are unavailable on this server. The notice replaces the device checkbox and push actions.
Generate VAPID keys:
```bash
npx web-push generate-vapid-keys
```
Then configure Chatto:
```toml
[push]
enabled = true
vapid_public_key = ""
vapid_private_key = ""
vapid_subject = "mailto:admin@example.com"
```
```bash
CHATTO_PUSH_ENABLED=true
CHATTO_PUSH_VAPID_PUBLIC_KEY=
CHATTO_PUSH_VAPID_PRIVATE_KEY=
CHATTO_PUSH_VAPID_SUBJECT=mailto:admin@example.com
```
Use a `mailto:` or HTTPS contact URI for `vapid_subject`. Keep the private key secret and stable; changing it can invalidate existing browser subscriptions.
## Device Behavior
To enable push notifications, select **Push notifications on this device** in a server's notification settings. This opens the browser or operating-system permission prompt if permission is unset. If you block notifications, change the choice in browser or operating-system settings before you try again.
Push is on for every registered server or for none of them. Each server's notification settings have one checkbox, **Push notifications on this device**. Unchecking it stops push from every server on this device; checking it turns push on again for all servers and asks the browser for permission if necessary.
While push is on, use **Send test notification** in a server's notification settings to check delivery to your devices.
If the browser cannot create a push subscription, Chatto pauses new subscription setup for all servers in that app. The pause remains after a reload and applies to other tabs on the same app origin. Existing subscriptions continue to work. Open notification settings and select **Try Again** to retry setup. If the browser fails again, setup pauses again. Turning push off and on also retries setup, but first removes existing subscriptions. A checked checkbox means push is enabled; wait for **Send test notification** before you test delivery.
When the user grants permission, Chatto creates a separate subscription for each registered server that supports push, including remote servers. While permission is granted, Chatto also registers servers that the user adds or signs in to later, without asking again. A user can have up to 16 active subscriptions on a server, and Chatto attempts every current endpoint for each push. Once any endpoint accepts a notification, Chatto does not retry the complete device set merely because another endpoint failed; this avoids repeatedly alerting healthy devices.
A server keeps a device's subscription for 180 days after the device last saved it. While the device uses Chatto, the app saves its subscriptions again when it starts, about once a day after that, and when the browser replaces a subscription. A device that does not open Chatto for 180 days stops receiving pushes until it opens Chatto again. Chatto also removes subscriptions when push providers report them as gone.
Chatto sends regular notifications in a declarative-compatible Web Push format, with browser-managed display and app-badge updates where supported. User-visible pushes request high-urgency delivery so mobile push services can wake sleeping devices promptly. Its service worker preserves notification display and click compatibility for browsers that do not handle the declarative payload directly.
While the app is running, confirmed read and delete actions also ask the browser to close matching OS notifications. The app checks again when it resumes or receives updated notification state. Cleanup is limited to the matching server and account. It preserves unread notifications and leaves uncertain results unchanged if a request fails or the server returns only part of the list. Older pushes without account metadata are not eligible for automatic cleanup. A closed or suspended app cannot guarantee immediate cleanup on another device; browser support also determines whether a close request removes the notification.
Operators do not need to change VAPID keys or push configuration for this behavior.
For security, Chatto connects directly only to absolute HTTPS push endpoints with public network addresses. It does not follow endpoint redirects or route push delivery through `HTTP_PROXY` or `HTTPS_PROXY`. Standard browser-created subscriptions already meet these requirements; private-network, redirecting, and proxy-only custom push endpoints are unsupported.
On iOS and iPadOS, Web Push works only for supported Home Screen web apps. Follow [Install Chatto on Your Phone](/getting-started/install-pwa/) to install the app, then open it from its Home Screen icon before you enable push notifications.
## Operator Checklist
1. Set `webserver.url` to the public HTTPS origin.
2. Enable Web Push with stable VAPID keys.
3. Keep the service worker path reachable through your proxy.
4. Test from a normal member account, not only an owner account.
5. Test one desktop browser and one mobile installed PWA if mobile push matters.
6. Explain to members that push is per device and that they enable it once per device.
## Related Guides