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
| Persona | Surface | Capabilities |
|---|---|---|
| Staff (coach/admin/owner) | /dashboard announcement composer | Create, see read receipts, list, archive (soft-delete) |
| Member | Mobile/web announcement bell + feed | Read; mark as read; see priority badge |
Capabilities
- Create —
POST /announcementswith{ title, content, priority? }. Author is the calling staff user. Triggers WS broadcast + push fan-out to every active org member except the author. PostHogannouncement_publishedevent tracked. - List —
GET /announcementscursor-paginated. IncludesreadAt(per caller) andreadCount/totalMembersfor staff visibility. - Detail —
GET /announcements/:id— staff-only path includes read-receipt list. - Unread count —
GET /announcements/unread-count— feeds the bell badge. - Mark read —
PUT /announcements/:id/read— upserts theannouncement_readsrow. - 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).
Related
../messages-comments/— shares theMessagesGatewayfor WS broadcast (announcement:newevent).../push-notifications/— fan-out target with categoryannouncement.../event-tracking/— PostHog capture point.
Source code
- API:
apps/api/src/announcements/ - DB:
libs/db/src/lib/schema/announcements.ts - Web:
apps/web/src/components/announcements/