Notifications
CoderFlow can reach users through email (SMTP) and browser desktop notifications (foreground + Web Push). Both are off by default until configured: the server doesn't send email until SMTP is set up, and a browser doesn't receive desktop notifications until the user grants permission.
This page covers the server configuration, the per-user preferences each channel honors, and the @-mentions that drive most comment notifications.
Channels at a glance
| Channel | Triggers | Configured by | Per-user opt-out |
|---|---|---|---|
| Email — @mentions | Someone mentions you in a comment | Admin: SMTP | Profile → Notifications → @Mentions |
| Email — comments on your tasks | Someone comments on a task or objective you created | Admin: SMTP | Profile → Notifications → Comments on my tasks/objectives |
| Email — failed scheduled builds | A scheduled image build fails in an environment where you are a contact | Admin: SMTP; environment contacts | Profile → Notifications → Failed scheduled builds |
| Desktop notifications (foreground) | A task you launched in this browser tab finishes | Per-user, per-browser permission | Toggle off Browser Notifications → Enable on this browser |
| Web Push (background) | A task you launched finishes while the tab is closed/backgrounded | Auto-enabled when desktop notifications are granted | Same as above (revoking the toggle unsubscribes) |
| Web Push — @mentions | Someone mentions you in a comment | Auto-enabled when desktop notifications are granted | Same as above |
Every comment notification goes only to people who can view the task or objective. A mentioned user, or an owner, who cannot open it is skipped.
The server stores per-user preferences (email_mentions, email_comments_on_my_tasks, email_build_failures, email_it_requests, email_scheduled_questions, notify_on_snooze_return, task_completion_notification_mode) on the user record; the browser-permission toggle is per-device and lives in localStorage.
In Full edition, Ask CoderFlow can read and, after you confirm, change your own preferences, check this browser's notification setup, and offer a button that turns notifications on or off in this browser.
Email (SMTP) Configuration
Navigate to Settings → Email (SMTP) to configure outbound mail:
- SMTP Host — Your mail server hostname (e.g.,
smtp.office365.com) - SMTP Port — Typically
587for STARTTLS or465for SSL/TLS - Use TLS/SSL — Enable for port 465; leave disabled for port 587 with STARTTLS
- Username — SMTP authentication username
- Password — SMTP authentication password (leave blank when re-saving to keep the existing one)
- From Address — Email address shown as the sender
- From Name — Display name shown alongside the sender address (optional)
Use Test Connection to verify the SMTP server is reachable, then Send Test Email to confirm full delivery to a recipient you specify.
SMTP settings can also be supplied via environment variables (SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, SMTP_SECURE, SMTP_FROM, SMTP_FROM_NAME). The Settings UI takes precedence: when both are set, the saved configuration is used.
Provider-specific notes
Office 365. Use smtp.office365.com on port 587 with TLS/SSL disabled (STARTTLS is negotiated automatically). Ensure the sending account has SMTP authentication enabled — you may need to turn on "Authenticated SMTP" in the Microsoft 365 admin center.
Gmail. Use smtp.gmail.com on port 587 with TLS/SSL disabled. Gmail requires an App Password rather than the regular account password. Generate one at Google Account → Security → App Passwords; 2-Step Verification must be enabled on the account.
SendGrid. Use smtp.sendgrid.net on port 587. The username is literally apikey; the password is the SendGrid API key.
AWS SES. Use email-smtp.<region>.amazonaws.com on port 587 (replace <region> with your AWS region). SES SMTP credentials are different from your AWS access keys — generate them in the AWS SES console under SMTP Settings, and verify the From address before sending.
Troubleshooting
Connection timeout. Verify the SMTP host and port. Check that your firewall allows outbound connections on the SMTP port; some cloud providers block port 25, in which case use 587 or 465.
Authentication failed. Confirm the username and password. For Gmail, use an App Password. For Office 365, confirm SMTP authentication is enabled for the account.
Emails not received. Check the spam/junk folder. Verify the From address is authorized to send from your mail server. For SES, confirm the From address is verified.
Certificate errors. If your mail server uses a self-signed certificate, the container needs to trust it. Confirm the server's system clock is accurate — certificate validation depends on it.
Browser & Push Notifications
CoderFlow can show desktop notifications when a task finishes — both while a CoderFlow tab is open (foreground) and after it's closed (Web Push). Both paths use the same service worker so the click handler routes to the right task page either way.
How it works
- The service worker (
/sw.js) is registered the first time a user enables notifications, and it stays registered across visits. - The browser displays the notification with
ServiceWorkerRegistration.showNotification(), including on Android Chrome where thenew Notification()constructor throws. - For background delivery, the browser subscribes to the server's Web Push endpoint (
POST /api/push/subscribe) using a VAPID public key fromGET /api/push/vapid-key. The server then dispatches push payloads to that subscription whenever the user's tasks reach a terminal status, and whenever someone @-mentions the user in a comment. - Notification clicks open
/task.html?id=<taskId>(or?groupId=...for groups, or/index.html?objective=<id>for a mention on an objective). If a tab on that URL is already open, it gets focused instead of opening a new one.
VAPID configuration (admin)
Web Push requires a VAPID key pair. CoderFlow loads keys with this priority:
VAPID_PUBLIC_KEYandVAPID_PRIVATE_KEYenvironment variables.- Persisted keys at
${DATA_DIR}/.vapid-keys.json. - Auto-generated on first start, persisted to that file with
0600permissions.
In other words, Web Push works out of the box without manual setup — you only need to set the env vars to pin a specific keypair (e.g. across replicas or for disaster recovery).
The VAPID subject defaults to mailto:[email protected] and can be overridden with VAPID_SUBJECT (it appears in push requests so the push service has a contact for abuse reports). If the web-push npm package isn't installed in the running build, Web Push is disabled silently and GET /api/push/vapid-key returns 503 push_disabled; foreground notifications still work in that case.
Per-user push subscriptions are stored at ${DATA_DIR}/push-subscriptions.json. When a push delivery returns 404 or 410, the stale endpoint is pruned automatically.
User experience
The first time a logged-in user lands on the home page, a banner appears:
Enable Desktop Notifications — Stay informed when your tasks complete
Clicking Enable Notifications asks the browser for permission, registers the service worker, and (if VAPID is configured) registers a push subscription. The same toggle lives at Profile → Notifications → Browser Notifications → Enable on this browser. The Dismiss button hides the banner permanently for the current browser via localStorage.
The browser-notification preference is per-device, not per-account: it follows the browser's permission and a localStorage flag, so enabling it in Chrome on a laptop does not automatically enable it in Firefox on a phone. The profile checkbox reflects the local state, not a server-stored preference.
A push endpoint identifies a specific browser+VAPID pair, not a user. If a different account logs in to the same browser and re-subscribes, the server transfers ownership to the new account — so notifications follow whoever is currently logged in on that device.
Checking or changing this browser from Ask CoderFlow
When notifications do not arrive, ask Ask CoderFlow to check this browser. Its card reports, as separate lines, whether Web Push is configured on the server, whether the browser supports push, the permission, this browser's own switch, whether it has a push subscription, and whether CoderFlow has that subscription registered for you. Ask can also offer Turn on / Turn off notifications in this browser; clicking runs the same steps as the profile toggle. A permission blocked in the browser has to be allowed in the browser's site settings. The card cannot tell whether a notification was shown.
Foreground vs. background, group vs. per-task
When the user has notifications enabled, the client subscribes to the server-sent task event stream. Each terminal task event triggers either a foreground notification (if a CoderFlow tab is open and tracking it) or a Web Push delivery (otherwise).
The Grouped task runs preference at Profile → Notifications controls how groups and task trees behave:
- Notify each task as it finishes (default) — Each task fires its own notification, including every task in a group and every child task.
- Notify once when a group or task tree finishes — Multi-task groups suppress per-task notifications and emit a single summary notification once every task in the group reaches a terminal state. A task that created child tasks over the CoderFlow MCP server is treated as one unit with its task tree: everything created from it (child tasks and their children, their judges and reviews, deployments they started) and the tasks that share its group. None of them notifies on its own, including their groups, even if the task that started the tree has been deleted; the task that started the tree sends one notification when all of that work is quiet. Other standalone tasks still notify when they finish.
A task tree is quiet when the root task's own turn has ended, no task in the tree is running, queued or starting, no task in the tree has a follow-up scheduled for later (such as a wake-up the orchestrating task set for itself), no review loop is running for a group in the tree, and no child-task update is about to start another turn. Updates whose automatic delivery is held (for example by the limit on consecutive automatic turns, or because the parent failed, was stopped or lost its container) count as quiet, because they wait for you. So the notification arrives when the work is done and also when the orchestrating task stops to wait for you: an approval, a question, a hold or a failure. It shows the root task's name and the end of its latest reply, and opens the root task. It is sent once per quiet period: when work in the tree starts again, the next quiet moment notifies again. Children that finish close together resume the root task once, and the notification waits for that turn.
Standalone tasks without child tasks notify when they finish, regardless of this preference, except while queued follow-ups continue them (below). Test runs and deployment runs use a similar payload format (e.g. Test: <name>, Deploy: <profile>).
Queued follow-ups. In either mode, a turn that ends while the task still has queued follow-ups to deliver (and the queue is not paused) is not announced, because the next queued follow-up starts right away. The task notifies once its queue drains (a turn ends with nothing queued), or when the queue pauses because you have to act: the turn failed or was interrupted, or a queued follow-up could not be delivered (for example when pulling the latest changes conflicts). Removing everything that was queued also notifies. In Notify once mode a group waits the same way, and a task tree with queued follow-ups on any of its tasks is not quiet. Consecutive follow-ups queued by the same person are still sent together as one turn.
Completion notifications are only for your own tasks and groups: those you created, or an automation's tasks that name you to be notified. This holds whatever the board's scope. Under My teams or Everyone the board also follows teammates' running tasks, but their completions are not announced to you. Server Admins get the same rule. Web Push already worked this way.
Service worker & offline page
The service worker also caches a small offline fallback page (/offline.html). When a top-level navigation fails because the server can't be reached, the browser shows that page with a Reload button. Other requests (XHR, fetch, assets) are not cached and will fail normally. There is no general background-sync queue: CoderFlow does not retry failed API calls when connectivity returns.
Per-user notification preferences
Each user controls their own notification settings at Profile → Notifications. Defaults apply when a user has never edited them.
To see them without opening the profile, ask Ask CoderFlow ("What are my notification settings?"). With Allow Actions on, Ask can also change them after you click Confirm ("Stop emailing me about failed scheduled builds"), and offers Undo for 24 hours; see Changing your notification preferences. A profile dialog already open in another tab keeps the values it loaded until you reopen it, so reopen it before saving there. An MCP client connected with your API key can call get_my_notification_preferences, which returns the same seven server preferences (email_mentions, email_comments_on_my_tasks, email_build_failures, email_it_requests, email_scheduled_questions, notify_on_snooze_return, task_completion_notification_mode) as the profile shows them. It always reads the signed-in user and is not available to task tokens. Browser notifications are a device setting and are not part of it. Changing preferences is not available to MCP clients, because they have no confirmation step; use this dialog or Ask instead.
- Email Notifications
- @Mentions (default: on) — Email when mentioned in a task or objective comment.
- Comments on my tasks/objectives (default: on) — Email when someone else comments on a task or objective you created.
- Failed scheduled builds (default: on) — Email when a scheduled image build fails in an environment where you are a contact. Stored as
email_build_failures. - IT requests (default: on) — Email about new requests, replies, status updates, assignments and internal notes you are eligible to receive.
- Portal scheduled questions (default: on) — Email after runs of your Portal scheduled questions that are set to email you. Turning it off stops all of them.
- Browser Notifications
- Enable on this browser (default: off; per-device) — Toggle desktop notifications and Web Push for this browser, including @-mention notifications. Disabling unsubscribes from Web Push immediately.
- Grouped task runs (default: Notify each task) — Per-task desktop notifications, or one per group and one per task tree, as described above.
- Notify when snoozed tasks return (default: off; per-device) — A desktop notification when a snoozed pin returns to the Pinned view. This is a sub-preference of Enable on this browser and does nothing unless that is on. Unlike task-completion alerts, it is delivered by the open dashboard tab rather than Web Push, so it only fires while the dashboard is open in a browser tab. It is stored as the
notify_on_snooze_returnserver preference and mirrored per browser.
A user must have an email address on their profile to receive any email notification. SMTP must also be configured globally; otherwise email is skipped silently and only logged at debug level.
The server preferences are stored on the user record under preferences (email_mentions, email_comments_on_my_tasks, email_build_failures, email_it_requests, email_scheduled_questions, notify_on_snooze_return, task_completion_notification_mode).
Other saved user preferences have separate controls:
- Default Environment — Set it under Profile Settings → Profile. Used when a user creates a task without picking one explicitly.
- Auto-pin new tasks (default: on) — Set it in Task options, the sliders/settings icon at the bottom-left of the dashboard prompt. When enabled, new tasks you create there are pinned automatically. See Auto-pin New Tasks to start them unpinned. The setting is mirrored to a server preference (
auto_pin_new_tasks) so server-side flows like Slack-triggered tasks honor it. - Auto-update generated names (default: on) — Set it in the dashboard prompt's Task options menu. When CoderFlow named a task from its first prompt, it re-checks the name after each of the first three follow-ups and renames the task (and its group) only when the follow-ups show a clearly better name. Names the user typed, or changed later in the Web UI or through MCP, are never updated. The toggle is stored as the
auto_update_task_namesserver preference of the task owner.
@-Mentions in comments
Typing @ in any comment box opens a dropdown of the people who can view that task or objective. Anyone who can view the item gets it, admins included; it does not need access to the user directory. Type part of a name or username to filter, then press Enter or click to insert. The dropdown closes if you type a space or move the cursor outside the active mention.
The dropdown is filled by GET /tasks/<id>/mentionable-users?q=<text>, which any viewer of the item can call. It returns only each user's ID, display name, username and avatar URL, never email addresses or other account details, and lists only users who can view the item. For a private task, that is its owner and users with tasks:view_any on its environment. For a task shared view only, it also includes everyone with tasks:view on its environment. System accounts are not listed.
In the stored markdown, mentions are encoded as @[Display Name](mention:<userId>), which renders to a styled chip in the UI and to plain @Name in plain-text email bodies.
When a comment is posted:
- The server parses each
@[Name](mention:userId)token in the content. - For every mentioned user other than the commenter who can view the item:
- If the user enabled browser notifications, a Web Push notification ("
mentioned you" , with the start of the comment) goes to each of their subscribed browsers. Clicking it opens the task or objective. - If email is configured and the user has an email address and the
email_mentionspreference on, the server sends the Mention email template with a preview of the comment and a link to the task or objective.
- If the user enabled browser notifications, a Web Push notification ("
- Independently, if the task or objective has an owner other than the commenter who can still view it, the server sends the Comment email template to the owner, gated on their
email_comments_on_my_taskspreference.
A mentioned user who can read a task only because it is shared view only gets a reduced notification: the push notification and the email carry the task's redacted name and a link, without the commenter's name or the comment's text.
A mentioned user who cannot view the item receives nothing, even when the mention was typed by hand. Access is checked right before each notification is sent, with the same rule as opening the item: tasks:view on its environment for a shared item or a task shared view only, or tasks:view_any (or ownership plus tasks:view) for a private one.
A commenter is never notified about their own comment, even if they @-mention themselves. To opt out of mention emails, turn off Profile → Notifications → @Mentions. Mention push notifications follow Enable on this browser. To opt out of being notified about replies on your own tasks and objectives, turn off Comments on my tasks/objectives.
Mention notifications and owner notifications are independent: the same comment can trigger both (a mention notification and an owner email) or neither. Emails depend on SMTP being configured globally; push notifications depend on Web Push being available.
