Skip to content

notifications: announcement channel selector + proper re-engagement emails#55

Merged
dylanjeffers merged 2 commits into
mainfrom
notifications/send-notification-channels
Jun 6, 2026
Merged

notifications: announcement channel selector + proper re-engagement emails#55
dylanjeffers merged 2 commits into
mainfrom
notifications/send-notification-channels

Conversation

@dylanjeffers

Copy link
Copy Markdown
Contributor

Summary

Two related changes that make /internal/send-notification announcements (including the re-engagement / inactivity campaigns the notifications-dashboard cron sends) deliver good emails, not just push:

  1. Channel selector (c274d84): /internal/send-notification accepts an optional notificationTypes of email | push | both, stored as notification_channels on the announcement row and honored by the mapper. Defaults to both for back-compat.
  2. Email rendering fixes (91cbb9f): announcement emails previously reused the generic unread-notification shell and discarded the campaign's heading, CTA link, and artwork — the subject was always "N unread notifications on Audius".

Context

Re-engagement notifications are the same announcement notification type as one-off announcements (the cron inserts type: 'announcement' via the endpoint; the mapper dispatches on type == 'announcement'). The dashboard's send-reengagement cron passes the same fields a regular announcement does — title (heading), body, route (CTA), image_url — but the email side dropped all but the body.

Email fixes (all 5)

  • HeadinggetTitle() now renders data.title for announcements (was hardcoded null).
  • CTA routeWrapLink builds an absolute audius.co deep-link from the notification's route instead of the hardcoded /feed?openNotifications=true.
  • Artwork — the announcement body now renders image_url.
  • Subject — single-announcement emails use the heading instead of the generic unread-count subject.
  • Back-compat — every field is optional; rows without them fall back to the prior behavior (no heading/image, feed link, generic subject).

Testing

  • tsc --noEmit clean for apps/notifications/src (pre-existing @types/babel__traverse node_modules errors are unrelated).

🤖 Generated with Claude Code

dylanjeffers and others added 2 commits June 5, 2026 20:14
…nd-notification

Lets callers choose whether an announcement fires email only, push only,
or both. Adds a `notificationTypes` request field ("email" | "push" |
"both") validated at the endpoint and persisted on the notification row's
`data.notification_channels`. The Announcement mapper reads it and gates
the push/email broadcasts accordingly.

Defaults to "both" when omitted (and for pre-existing rows), so existing
callers are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Announcement emails (incl. re-engagement campaigns sent by the
notifications-dashboard cron via /internal/send-notification) reused the
generic unread-notification email shell and discarded almost all campaign
data: the heading, CTA deep-link, and artwork were dropped, and the subject
was always "N unread notifications on Audius".

These rows are the same `announcement` notification type as one-off
announcements, and the cron passes the same fields (title/body/route/
image_url), so the fix is on the email-rendering side:

- getTitle() now renders data.title as the heading for announcements
- WrapLink uses the notification's `route` to build an absolute audius.co
  deep-link instead of the hardcoded /feed link
- the announcement body now renders image_url as campaign artwork
- single-announcement emails use the heading as the subject line

All fields are optional; rows without them fall back to the previous
behavior (no heading/image, feed link, generic subject).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dylanjeffers dylanjeffers merged commit aee3433 into main Jun 6, 2026
36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant