Skip to Content
Living documentation — last reviewed 2026-05-28
FeaturesAnnouncementsAnnouncements

Announcements

Status: Shipped. Last reviewed: 2026-05-28

What

Org-wide one-to-many broadcasts authored by staff. Carry title, content, and a priority flag. Each member’s view tracks an individual announcement_reads row with read_at for unread badges and audit.

Distinct from messages (1:1) and notifications (system-emitted reminders).

Why

Coaches need a low-effort way to push “we’re closed this Friday” or “new program drops tomorrow” to every member in the org. WebSocket + push + email-deferred (today: push + WS only).

Personas

PersonaSurfaceCapabilities
Staff (coach/admin/owner)/dashboard announcement composerCreate, see read receipts, list, archive (soft-delete)
MemberMobile/web announcement bell + feedRead; mark as read; see priority badge

Capabilities

  • CreatePOST /announcements with { title, content, priority? }. Author is the calling staff user. Triggers WS broadcast + push fan-out to every active org member except the author. PostHog announcement_published event tracked.
  • ListGET /announcements cursor-paginated. Includes readAt (per caller) and readCount / totalMembers for staff visibility.
  • DetailGET /announcements/:id — staff-only path includes read-receipt list.
  • Unread countGET /announcements/unread-count — feeds the bell badge.
  • Mark readPUT /announcements/:id/read — upserts the announcement_reads row.
  • Priority — boolean flag; UI sorts priority above non-priority and renders a badge.

Capabilities (gaps)

  • No archive UI (soft-delete column exists; no API verb today — verify).
  • No targeting (segment-by-role or by tag). Always fans out to every active member.
  • No email channel for announcements (push + WS only).

Source code

  • API: apps/api/src/announcements/
  • DB: libs/db/src/lib/schema/announcements.ts
  • Web: apps/web/src/components/announcements/