Skip to content

Add calendar links to meeting invite and update emails - #109

Merged
ralyodio merged 1 commit into
masterfrom
invite-calendar-links
Sep 22, 2026
Merged

ralyodio merged 1 commit into
masterfrom
invite-calendar-links

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

What

Follow-up to #108. The invite email (sent when a meeting is created) now has the same "Add to calendar" row with Google and Outlook links and attaches the .ics. The update email ("Updated: …") gets the links too, without the attachment.

Why no attachment on updates

sendBulk goes through Resend's batch endpoint, which does not carry attachments (the emailer's bulk options have no attachments field either). The update email links out instead, and the row's copy drops the "open the attached .ics" note for that case.

How

  • lib/calendar.ts: new calendarLinksHtml({ googleCalendarUrl, outlookUrl, attached }) so the reminder, invite and update emails share one markup. The reminder runner now uses it (no visible change).
  • app/actions/meetings.ts: calendarEventFor builds one CalendarEvent per meeting (UID = <session id>@pairux.com on invites, recurrence as RRULE). Invite sends attach the base64 .ics; update sends pass the event for links only.

Tests

  • calendar.test.ts gains 2 tests for the row helper (attached vs bulk).
  • tsc --noEmit, eslint, prettier clean on touched files; 70/70 pass across calendar, reminders, join, invite and scheduled-sessions suites.

🤖 Generated with Claude Code

The invite email now carries Google and Outlook links plus the .ics
attachment, like the reminder. The update email gets the links only:
it goes out through Resend's batch endpoint, which cannot attach.

The "Add to calendar" row moves into lib/calendar.ts so the three emails
share one markup, with an `attached` flag that drops the attachment note
for bulk sends.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

34 finding(s)

HIGH/CRITICAL: 4 | MEDIUM: 26 | LOW: 4

Severity Rule Location
HIGH sh-eval-expansion .githooks/pre-commit:33
HIGH js-electron-node-integration apps/desktop/src/main/window.ts:49
HIGH sh-unquoted-expansion-destructive apps/installer/scripts/install.sh:715
HIGH sh-unquoted-expansion-destructive apps/installer/scripts/install.sh:910
MEDIUM sh-remote-script-execution apps/installer/scripts/install.sh:691
MEDIUM sh-remote-script-execution apps/installer/scripts/install.sh:813
MEDIUM sh-remote-script-execution apps/installer/scripts/install.sh:815
MEDIUM sh-remote-script-execution apps/installer/scripts/install.sh:1064
MEDIUM sh-remote-script-execution apps/installer/scripts/install.sh:1066
MEDIUM sh-remote-script-execution apps/livekit/setup-livekit-server.sh:93
MEDIUM sh-remote-script-execution apps/turn/deploy-droplet.sh:62
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:48
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:73
MEDIUM js-unescaped-html-sink apps/web/src/app/c/[handle]/page.tsx:192
MEDIUM js-unescaped-html-sink apps/web/src/app/l/[joinCode]/page.tsx:129
MEDIUM js-unescaped-html-sink apps/web/src/app/l/[joinCode]/page.tsx:213
MEDIUM js-unescaped-html-sink apps/web/src/app/layout.tsx:142
MEDIUM js-unescaped-html-sink apps/web/src/app/live/page.tsx:145
MEDIUM js-unescaped-html-sink apps/web/src/app/page.tsx:122
MEDIUM js-unescaped-html-sink apps/web/src/app/pricing/page.tsx:284
MEDIUM js-open-redirect apps/web/src/app/pricing/UpgradeButton.tsx:50
MEDIUM js-unescaped-html-sink apps/web/src/app/u/[username]/page.tsx:282
MEDIUM js-open-redirect apps/web/src/hooks/useDesktopHandoff.ts:24
MEDIUM redos-nested-quantifier apps/web/src/lib/deliverable.ts:11
MEDIUM js-unescaped-html-sink apps/web/src/lib/player/player.ts:124
MEDIUM js-unescaped-html-sink apps/web/src/lib/player/player.ts:393
MEDIUM js-unescaped-html-sink apps/web/src/lib/player/player.ts:396
MEDIUM js-unescaped-html-sink apps/web/src/lib/player/player.ts:405
MEDIUM js-unescaped-html-sink apps/web/src/lib/player/player.ts:608
MEDIUM sql-template-interpolation packages/ai-core/src/prompts.ts:36
LOW secret-generic-credential apps/livekit/fly.toml:12
LOW secret-generic-credential apps/turn/fly.toml:11
LOW secret-generic-credential docs/API.md:747
LOW secret-generic-credential docs/API.md:753

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit 4d66dc4 into master Sep 22, 2026
13 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