rspace-online/server/welcome-email.ts

100 lines
5.1 KiB
TypeScript

/**
* Welcome Email — sent once when a user first connects their email address.
*/
import { getSmtpTransport } from "./notification-service";
export async function sendWelcomeEmail(email: string, username: string): Promise<void> {
const transport = await getSmtpTransport();
if (!transport) {
console.warn("[welcome-email] No SMTP transport available");
return;
}
const displayName = username || "there";
const demoUrl = "https://demo.rspace.online";
const createUrl = "https://rspace.online/create";
const html = `
<div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 520px; margin: 0 auto; padding: 24px;">
<div style="background: #1e293b; border-radius: 12px; padding: 28px; color: #e2e8f0;">
<h1 style="margin: 0 0 4px; font-size: 22px; color: #f1f5f9;">
Welcome to <span style="color: #f97316;">r</span><span style="color: #14b8a6;">Space</span>, ${escapeHtml(displayName)}!
</h1>
<p style="margin: 0 0 24px; font-size: 15px; color: #94a3b8;">
Reclaim (you)<span style="color: #f97316;">r</span><span style="color: #14b8a6;">Space</span> on the internet &mdash; one place for your group to coordinate around what you care about.
</p>
<div style="background: #0f172a; border-radius: 8px; padding: 16px; margin-bottom: 20px;">
<p style="margin: 0 0 12px; font-size: 14px; color: #e2e8f0; line-height: 1.6;">
Instead of scattering your group across Slack, Google Docs, Trello, Zoom, Splitwise, and a dozen other apps &mdash;
<strong style="color: #14b8a6;">(you)rSpace puts it all in one shared workspace</strong> that your group actually owns.
</p>
<p style="margin: 0; font-size: 14px; color: #94a3b8; line-height: 1.6;">
Plan together. Decide together. Fund together. Build together. No corporate middlemen.
</p>
</div>
<p style="margin: 0 0 12px; font-size: 13px; color: #94a3b8; text-transform: uppercase; letter-spacing: 0.05em;">How groups use rSpace</p>
<table style="width: 100%; border-collapse: collapse; margin-bottom: 20px;">
<tr>
<td style="padding: 8px; font-size: 14px; color: #e2e8f0; line-height: 1.5; border-bottom: 1px solid #334155;">
<strong style="color: #f1f5f9;">Plan &amp; Decide</strong><br>
<span style="color: #94a3b8; font-size: 13px;">Schedule, vote, set priorities &mdash; decisions flow into tasks automatically</span>
</td>
</tr>
<tr>
<td style="padding: 8px; font-size: 14px; color: #e2e8f0; line-height: 1.5; border-bottom: 1px solid #334155;">
<strong style="color: #f1f5f9;">Create &amp; Share</strong><br>
<span style="color: #94a3b8; font-size: 13px;">Docs, maps, data &mdash; all synced, all encrypted, all yours</span>
</td>
</tr>
<tr>
<td style="padding: 8px; font-size: 14px; color: #e2e8f0; line-height: 1.5; border-bottom: 1px solid #334155;">
<strong style="color: #f1f5f9;">Fund &amp; Sustain</strong><br>
<span style="color: #94a3b8; font-size: 13px;">Shared wallets, resource flows, transparent budgets</span>
</td>
</tr>
<tr>
<td style="padding: 8px; font-size: 14px; color: #e2e8f0; line-height: 1.5;">
<strong style="color: #f1f5f9;">Stay Connected</strong><br>
<span style="color: #94a3b8; font-size: 13px;">Chat, meet, coordinate &mdash; without giving your conversations to ad companies</span>
</td>
</tr>
</table>
<div style="background: #0f172a; border-radius: 8px; padding: 12px 16px; margin-bottom: 20px;">
<p style="margin: 0; font-size: 13px; color: #94a3b8; line-height: 1.5;">
&#x1f510; <strong style="color: #e2e8f0;">Your identity is yours.</strong>
One passkey &mdash; no passwords, no seeds, no email loops. Works everywhere, owned by nobody but you.
</p>
</div>
<div style="text-align: center;">
<a href="${demoUrl}" style="display: inline-block; padding: 10px 22px; background: linear-gradient(135deg, #14b8a6, #0d9488); color: white; text-decoration: none; border-radius: 6px; font-size: 14px; font-weight: 600; margin-right: 8px;">Explore the Demo Space</a>
<a href="${createUrl}" style="display: inline-block; padding: 10px 22px; background: transparent; color: #14b8a6; text-decoration: none; border-radius: 6px; font-size: 14px; font-weight: 600; border: 1px solid #14b8a6;">Create Your Space</a>
</div>
</div>
<p style="margin: 14px 0 0; font-size: 11px; color: #64748b; text-align: center;">
You can manage your email in profile settings at any time.
</p>
</div>`;
try {
await transport.sendMail({
from: "rSpace <hello@rspace.online>",
to: email,
subject: `Welcome to rSpace, ${displayName} — your group's new home`,
html,
replyTo: "hello@rspace.online",
});
console.log(`[welcome-email] Sent to ${email}`);
} catch (err: any) {
console.error(`[welcome-email] Failed to send to ${email}:`, err.message);
}
}
function escapeHtml(s: string): string {
return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
}