feat(emails): warmer copy across invite, welcome, and event emails

Friendlier tone + ghost emoji on invite/welcome subjects; invite
templates now offer a reply-to-this-email fallback; tighten OIDC
wiki sign-in and event registration confirmation copy.
This commit is contained in:
Jennie Robinson Faber 2026-04-20 13:48:38 +01:00
parent 91711aa39b
commit 0ce61756b7
6 changed files with 19 additions and 19 deletions

View file

@ -522,14 +522,14 @@ const inviteResults = ref(null);
const DEFAULT_INVITE_TEMPLATE = `Hi {name}, const DEFAULT_INVITE_TEMPLATE = `Hi {name},
You've been invited to Ghost Guild as a member of the {circle} circle. You've been invited to Ghost Guild.
Sign in here to get started: Sign in here to get started:
{loginLink} {loginLink}
This link expires in 48 hours. After that, you can always request a new login link at https://ghostguild.org/login. This link expires in 48 hours. After that, you can always request a new login link at https://ghostguild.org/login.
See you inside.`; Reply to this email if you have any trouble!`;
const inviteTemplate = ref(DEFAULT_INVITE_TEMPLATE); const inviteTemplate = ref(DEFAULT_INVITE_TEMPLATE);

View file

@ -247,9 +247,11 @@ Click below to accept your invitation, choose your circle, and set your contribu
{acceptLink} {acceptLink}
This link expires in 48 hours. If it expires, we can send you a new one. This link expires in 48 hours. If it expires, we can send you a new one. Just reply to this email.
See you inside.`; See you soon!
Ghost Guild`;
const inviteTemplate = ref(DEFAULT_INVITE_TEMPLATE); const inviteTemplate = ref(DEFAULT_INVITE_TEMPLATE);

View file

@ -75,7 +75,7 @@ export default defineEventHandler(async (event) => {
const { error: emailError } = await resend.emails.send({ const { error: emailError } = await resend.emails.send({
from: 'Ghost Guild <welcome@babyghosts.org>', from: 'Ghost Guild <welcome@babyghosts.org>',
to: [member.email], to: [member.email],
subject: "You're invited to Ghost Guild", subject: "You're invited to Ghost Guild! 👻",
text: emailText, text: emailText,
html: emailHtml, html: emailHtml,
}) })
@ -102,7 +102,7 @@ export default defineEventHandler(async (event) => {
logActivity(member._id, 'email_sent', { logActivity(member._id, 'email_sent', {
emailType: 'invite', emailType: 'invite',
subject: "You're invited to Ghost Guild", subject: "You're invited to Ghost Guild! 👻",
body: emailText body: emailText
}) })

View file

@ -66,7 +66,7 @@ export default defineEventHandler(async (event) => {
const { error: emailError } = await resend.emails.send({ const { error: emailError } = await resend.emails.send({
from: 'Ghost Guild <welcome@babyghosts.org>', from: 'Ghost Guild <welcome@babyghosts.org>',
to: [preReg.email], to: [preReg.email],
subject: "You're invited to Ghost Guild", subject: "You're invited to Ghost Guild! 👻",
text: emailText, text: emailText,
html: emailHtml, html: emailHtml,
}) })

View file

@ -50,9 +50,7 @@ export default defineEventHandler(async (event) => {
from: "Ghost Guild <ghostguild@babyghosts.org>", from: "Ghost Guild <ghostguild@babyghosts.org>",
to: email, to: email,
subject: "Sign in to Ghost Guild Wiki", subject: "Sign in to Ghost Guild Wiki",
text: `Sign in to the Ghost Guild Wiki text: `Use this link to sign in to the Ghost Guild Wiki:
Use this link to sign in:
${baseUrl}/oidc/interaction/verify?token=${token} ${baseUrl}/oidc/interaction/verify?token=${token}

View file

@ -62,9 +62,9 @@ Paid: $${registration.amountPaid.toFixed(2)} CAD`;
from: "Ghost Guild <events@babyghosts.org>", from: "Ghost Guild <events@babyghosts.org>",
to: [registration.email], to: [registration.email],
subject: `You're registered for ${eventData.title}`, subject: `You're registered for ${eventData.title}`,
text: `Hi ${registration.name}, text: `Hi ${registration.name}!
You're registered for ${eventData.title}. You're now registered for ${eventData.title}.
Date: ${formatDate(eventData.startDate)} Date: ${formatDate(eventData.startDate)}
Time: ${formatTime(eventData.startDate, eventData.endDate)} Time: ${formatTime(eventData.startDate, eventData.endDate)}
@ -72,7 +72,9 @@ Location: ${eventData.location}
${eventData.description ? `\n${eventData.description}\n` : ""}${ticketSection}${signInSection} ${eventData.description ? `\n${eventData.description}\n` : ""}${ticketSection}${signInSection}
View event: ${eventUrl} View event: ${eventUrl}
To cancel, visit the event page and click "Cancel Registration."`, To cancel, visit the event page and click "Cancel Registration."
We look forward to seeing you there!`,
}); });
if (error) { if (error) {
@ -272,17 +274,15 @@ export async function sendWelcomeEmail(member) {
const { data, error } = await resend.emails.send({ const { data, error } = await resend.emails.send({
from: "Ghost Guild <ghostguild@babyghosts.org>", from: "Ghost Guild <ghostguild@babyghosts.org>",
to: [member.email], to: [member.email],
subject: "Welcome to Ghost Guild", subject: "Welcome to Ghost Guild! 👻",
text: `Hi ${member.name}, text: `Hi ${member.name}!
Welcome to Ghost Guild! You're now part of the ${member.circle} circle. Welcome to Ghost Guild! You're now part of the ${member.circle} circle.
Sign in to your dashboard: Sign in to your dashboard to get started:
${baseUrl}/member/dashboard ${baseUrl}/member/dashboard
If you have questions, reach out on Slack or reply to this email. If you have questions, reach out to jennie + eileen on Slack or reply to this email.`,
Ghost Guild`,
}); });
if (error) { if (error) {