Digest emails
The notification digest is an optional email that summarises your in-app notifications on a fixed cadence. Turn it on if you don't want to keep a dashboard tab open to watch the bell.
Off by default. Each user configures it themselves at
/dashboard/settings/notifications.
One setting per user per company — if you're on two companies, each
has its own cadence.
Configuring
From Settings → Notifications, three fields control the digest:
| Field | Values | Notes |
|---|---|---|
| Cadence | OFF, DAILY, WEEKLY | OFF stops all digest emails. DAILY sends one email per day. WEEKLY sends one email per week. |
| Hour (UTC) | 0–23 | The hour at which the digest fires. Stored as UTC — the form shows your offset hint so you can pick the right number for your timezone. |
| Day of week | 1 (Mon) – 7 (Sun) | Only used when cadence is WEEKLY. Hidden otherwise. |
On save, Distribu recomputes the next digest time. Changing any of the
three fields — including switching from WEEKLY to DAILY — always
recomputes forward; you won't accidentally trigger a retroactive send.
Scheduling
Distribu picks "the next matching time, strictly in the future":
DAILY— if the configuredhourUTCis still ahead today, the next digest fires today. If the hour has already passed, it fires tomorrow at the same hour.WEEKLY— the next occurrence of the configured(dayOfWeek, hourUTC). If today is the right day and the hour hasn't passed yet, it's today; otherwise it's the next matching weekday — up to seven days out.
The scheduler is driven by the fields lastDigestAt and nextDigestAt
on each NotificationPreference row. Both are set automatically by the
server; you never see them in the UI.
The delivery window
Each digest covers notifications in a half-open time window:
[ lastDigestAt ?? createdAt , now )
In words:
- Lower bound — your previous digest time (or the moment you first turned it on, if this is your first digest). Inclusive.
- Upper bound — the moment the cron fires. Exclusive.
This half-open shape matters for two edge cases:
- Cron drift. If the cron job fires slightly late, the next window picks up exactly where this one left off — no duplicates, no gaps.
- Notifications created at the cron boundary. A notification
created at exactly
nowis deferred to the next window, so you can't double-send the same row across two digests.
Zero-notification digests don't send
If the window contains no notifications, Distribu skips the email
entirely but still advances lastDigestAt and nextDigestAt. No
empty digests ever hit your inbox, and the scheduler stays aligned.
Cron job
The digest runs out of
GET /api/cron/notification-digest on a fixed schedule in
vercel.json:
0 13 * * * # daily at 13:00 UTC
The cron itself runs once a day — any user who picks hourUTC = 13
with cadence DAILY receives their digest in that run. Other
hourUTC values are honoured on the next run where nextDigestAt
has passed, so in practice the minimum granularity is whatever the
cron runs at. On Vercel's Hobby plan this is daily; on Pro it can
run hourly for finer-grained timing.
Email content
The digest email groups your notifications by type, with a count
header per group and up to 5 line items per group. Groups with more
than 5 items show an "and N more" link back to the full list at
/dashboard/notifications.
Subject lines:
- Daily:
Your daily digest — {Company} ({N} updates) - Weekly:
Your weekly digest — {Company} ({N} updates)
The email itself uses the same visual shell as other Distribu emails — logo in the header, quiet palette, unsubscribe-via-settings hint in the footer.
Turning it off
Setting cadence to OFF stops all future digests. The existing
lastDigestAt / nextDigestAt pointers are cleared, so when you turn
it back on later, the scheduler starts fresh from the re-enable
moment — you won't get a giant catch-up digest for the months you had
it off.
What's not here (yet)
- Per-type mute. You can turn the whole digest off, but you can't
say "digest everything except
MEMBER_INVITED." Workaround: turn the digest off and rely on the bell for in-app awareness. - Per-user timezone setting beyond
hourUTC. We don't store a timezone string; you do the UTC math yourself when picking an hour. - Separate digest for different notification priorities. Every notification in the window is included; there's no urgency tier today.
- Multiple recipients per digest. The digest is strictly per-user. If three staff want the digest, each configures their own.
Related:
- Notifications — the bell-icon UX and event-type catalog.
- Scheduled reports — different feature, similar shape (cron + email) — for actual data exports.
