## Context The Journal has passkey auth (primary) and magic link login (fallback). Magic links work in dev (auto-redirect) but in production the link is only logged to console — users never receive it. No email infrastructure exists. ## Goals / Non-Goals **Goals:** - Actually deliver magic link emails in production - Send a welcome email after registration - Provider-agnostic email interface (easy to swap providers) - HTML templates with plain-text fallback - Easy to add new email types in the future (just add a template + call) - Dev mode: still log to console / return devLink (no real emails) **Non-Goals:** - Marketing emails or newsletters - Email preferences / unsubscribe (only transactional) - Inline CSS / complex email layouts (keep it simple text-focused) - Queuing or retry logic (provider handles delivery) ## Decisions ### D1: Resend as email provider Use [Resend](https://resend.com) — simple API, generous free tier (3k emails/month), good developer experience. Single dependency: `resend` npm package. **Alternative considered**: Nodemailer + SMTP. More complex setup, requires SMTP server. Resend is simpler for a small project. **Alternative considered**: Postmark. Similar to Resend but less ergonomic API. ### D2: Email module in apps/journal/app/lib/email.server.ts Not a shared package — only the Journal sends emails. Keep it simple: - `sendEmail(to, subject, html, text)` — low-level sender - `sendMagicLink(email, link)` — template wrapper - `sendWelcome(email, username)` — template wrapper In dev mode, `sendEmail` logs to console instead of calling Resend. ### D3: Inline HTML templates Simple functions returning HTML strings. No template engine. Each email type is a function: `magicLinkTemplate(link)`, `welcomeTemplate(username)`. Plain text generated by stripping tags. ### D4: Sender domain: noreply@trails.cool Requires DNS verification (DKIM/SPF records) with Resend. Add TXT records via Terraform or manually in Hetzner DNS. ## Risks / Trade-offs - **Resend vendor lock-in** → Low risk. The `sendEmail` wrapper abstracts it. Swapping to nodemailer later is a one-file change. - **DNS verification required** → Must add DKIM/SPF records before emails work. Can use Resend's test domain initially. - **Free tier limits** → 3k/month is plenty for <100 users.