> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cfosilvia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# RESEND INTEGRATION

# Resend Integration: Hybrid Approach

## Why Not Just Use Resend's Built-in Unsubscribe?

**Short Answer:** We need granular control that Resend doesn't provide.

### Resend's Limitations:

* **All-or-nothing suppression** - If user unsubscribes, they're blocked from ALL emails (or all emails in a list)
* **No category distinction** - Can't differentiate between marketing, operational, and transactional emails
* **External dependency** - Would need to call Resend API before every email send
* **Generic experience** - Their unsubscribe page is basic and can't explain "you'll still get daily snapshots"

### Our Requirements:

✅ User unsubscribes from **marketing** → Still gets **daily snapshots** and **alerts**\
✅ Database-first permission checks (fast, no external API calls)\
✅ Custom unsubscribe page with clear messaging\
✅ Granular preference management (2 marketing types, 4+ operational types)\
✅ Settings UI for users to manage individual email types\
✅ Both marketing types can be toggled independently in settings

***

## Our Hybrid Solution: Best of Both Worlds

We built a **custom database-backed system** but **enhanced it with Resend features**:

### What We Built Custom:

1. **Database schema** (2 tables)
   * `email_preferences` - Marketing preferences (feature\_announcements, marketing\_general)
   * `all_users` - Operational preferences (email\_daily\_summary, email\_spending\_spikes, etc.)
   * Fast permission checks without API calls

2. **Permission system** (`EmailSubscriptionManager`)
   * Checks if user allows specific email types
   * Handles unsubscribe logic (marketing vs operational)
   * Generates secure unsubscribe tokens (90-day expiry)

3. **Custom unsubscribe page** (`/app/unsubscribe/page.tsx`)
   * Shows clear messaging about what continues
   * Links to settings for granular control
   * No chat widget to prevent distractions

4. **Settings UI** (`/app/settings/page.tsx → Email Notifications`)
   * Individual toggles for each email type
   * Marketing emails with blue "Marketing" badges
   * Real-time updates with toast notifications
   * Separate sections for operational vs marketing emails

5. **API Endpoints**
   * `/api/unsubscribe` - Token-based unsubscribe processing
   * `/api/marketing-preferences` - CRUD for marketing preferences
   * Works without authentication (token proves identity)

### What We Use from Resend:

1. **List-Unsubscribe Headers** ⭐
   ```typescript theme={null}
   headers: {
     'List-Unsubscribe': `<${unsubscribeLink}>`,
     'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click',
   }
   ```
   **Result:** Gmail/Outlook show native "Unsubscribe" button next to email

2. **Email Tags** 📊
   ```typescript theme={null}
   tags: [
     { name: 'category', value: 'marketing' },
     { name: 'campaign', value: 'security-winback' }
   ]
   ```
   **Result:** Track performance in Resend dashboard

***

## How It Works

### Sending a Marketing Email (Complete Example):

```typescript theme={null}
import { emailSubscriptionManager } from '@/lib/email-subscription-manager'
import { resend } from '@/lib/resend'
import FeatureAnnouncementEmail from '@/emails/feature-announcement-email'

export async function sendFeatureAnnouncement(userId: string, userEmail: string) {
  // 1. Check our database for permission
  const canSend = await emailSubscriptionManager.canSendEmail(
    userId,
    'feature_announcements' // or 'marketing_general'
  )
  
  if (!canSend) {
    console.log(`User ${userId} has unsubscribed from feature announcements`)
    return { skipped: true }
  }
  
  // 2. Generate our custom unsubscribe link (creates new token every time)
  const unsubscribeLink = await emailSubscriptionManager.generateUnsubscribeLink(
    userId,
    'feature_announcements'
  )
  
  // 3. Send via Resend with headers + tags
  const { data, error } = await resend.emails.send({
    from: 'Silvia <no-reply@cfosilvia.com>',
    to: userEmail,
    subject: 'New Feature: Enhanced Account Types',
    react: FeatureAnnouncementEmail({ unsubscribeLink }),
    
    // 🎯 Resend integration for email client unsubscribe button
    headers: emailSubscriptionManager.getResendHeaders(unsubscribeLink),
    
    // 📊 Resend analytics tags
    tags: emailSubscriptionManager.getResendTags(
      'feature_announcements',
      'account-types-launch'
    ),
  })
  
  if (error) {
    console.error('Failed to send email:', error)
    return { error }
  }
  
  return { success: true, messageId: data.id }
}
```

### When User Clicks Unsubscribe:

**Option A: Email Client Button (Gmail/Outlook)**

```
User clicks "Unsubscribe" button in Gmail
  ↓
Email client sends POST to our unsubscribe URL
  ↓
Our API validates token → Updates OUR database
  ↓
User redirected to our custom confirmation page
```

**Option B: Email Footer Link**

```
User clicks "Unsubscribe" link in email footer
  ↓
Goes directly to /api/unsubscribe?token=xxx
  ↓
Our API validates token → Updates OUR database
  ↓
User redirected to our custom confirmation page
```

***

## Benefits of This Approach

### ✅ Advantages:

1. **Email Client Integration**
   * Gmail/Outlook users see native "Unsubscribe" button
   * One-click unsubscribe (no page visit required for some clients)
   * Improves email deliverability (ISPs like seeing proper unsubscribe headers)

2. **Granular Control**
   * Marketing unsubscribe doesn't affect operational emails
   * Database-first permission checks (fast, no external dependency)
   * Custom business logic (e.g., "unsubscribe from ALL marketing at once")

3. **User Experience**
   * Custom unsubscribe page with clear messaging
   * Users understand they'll still get important emails
   * Settings UI with individual toggles for each email type:
     * Feature Announcements (Marketing)
     * Marketing & Promotions (Marketing)
     * Portfolio Summary (Operational)
     * Spending Alerts (Operational)
     * Stock Price Alerts (Operational)
     * Financial Statements (Operational)
   * Real-time updates with toast notifications
   * Blue badges distinguish marketing from operational emails

4. **Analytics**
   * Track email performance by category and campaign in Resend
   * Monitor unsubscribe rates per email type
   * A/B test different email approaches

5. **Independence**
   * Not locked into Resend's suppression system
   * Can switch email providers without losing preference data
   * Full control over permission logic

### ⚠️ Trade-offs:

1. **Maintenance** - We maintain our own permission system
2. **Complexity** - More code than using Resend alone (but necessary for our requirements)
3. **No auto-sync** - We don't sync suppression back to Resend audiences (could add if needed)

***

## Helper Methods & Hooks

### For Sending Marketing Emails:

```typescript theme={null}
import { emailSubscriptionManager } from '@/lib/email-subscription-manager'

// Check permission
const canSend = await emailSubscriptionManager.canSendEmail(
  clerkId,
  'feature_announcements' // or 'marketing_general'
)

// Generate unsubscribe link (new token each time)
const unsubscribeLink = await emailSubscriptionManager.generateUnsubscribeLink(
  clerkId, 
  'feature_announcements'
)

// Send with Resend integration
await resend.emails.send({
  // ... other fields ...
  headers: emailSubscriptionManager.getResendHeaders(unsubscribeLink),
  tags: emailSubscriptionManager.getResendTags('feature_announcements', 'campaign-name'),
})
```

### For Settings UI (Frontend):

```typescript theme={null}
import { useMarketingPreferences } from '@/hooks/queries/use-marketing-preferences'
import { useEmailPreferences } from '@/hooks/queries/use-email-preferences'

// Marketing preferences (feature_announcements, marketing_general)
const {
  preferences: marketingPrefs,
  updatePreference: updateMarketing,
  isLoading,
} = useMarketingPreferences()

// Operational preferences (daily summaries, alerts, etc.)
const {
  preferences: emailPrefs,
  updatePreference: updateEmail,
} = useEmailPreferences()

// Toggle marketing preference
<Switch
  checked={marketingPrefs.feature_announcements}
  onCheckedChange={(checked) =>
    updateMarketing('feature_announcements', checked)
  }
/>
```

***

## Optional: Sync to Resend Audiences

If you want extra safety, you can also suppress in Resend:

```typescript theme={null}
// After successful unsubscribe in our system
if (result.success && isMarketingEmail) {
  // Also mark as unsubscribed in Resend for belt-and-suspenders
  try {
    await resend.contacts.update({
      email: userEmail,
      unsubscribed: true,
      audienceId: process.env.RESEND_MARKETING_AUDIENCE_ID,
    })
  } catch (error) {
    console.error('Failed to sync to Resend:', error)
    // Not critical - our database is source of truth
  }
}
```

***

## Key Files

### Backend

* `/lib/email-subscription-manager.ts` - Core permission system and token generation
* `/app/api/unsubscribe/route.ts` - Token processing endpoint
* `/app/api/marketing-preferences/route.ts` - Marketing preferences CRUD
* `/sql-queries/email-preferences-schema.sql` - Database schema

### Frontend

* `/app/settings/page.tsx` - Settings UI with email toggles
* `/app/unsubscribe/page.tsx` - Unsubscribe confirmation page
* `/hooks/queries/use-marketing-preferences.ts` - Marketing preferences hook
* `/hooks/queries/use-email-preferences.ts` - Operational email preferences hook

### Email Templates

* `/emails/feature-announcement-email.tsx` - Feature announcements
* `/emails/daily-email.tsx` - Daily portfolio summaries

***

## Summary

| Aspect | Custom Only | Resend Only | Our Hybrid ✅ |
| - | - | - | - |
| Granular control (marketing vs operational) | ✅ | ❌ | ✅ |
| Individual toggles in Settings UI | ✅ | ❌ | ✅ |
| Email client unsubscribe button | ❌ | ✅ | ✅ |
| Custom unsubscribe page | ✅ | ❌ | ✅ |
| Fast permission checks (database-first) | ✅ | ❌ | ✅ |
| Email analytics & tags | ❌ | ✅ | ✅ |
| Legal compliance (CAN-SPAM, GDPR) | ✅ | ✅ | ✅ |
| User-friendly Settings UI | ✅ | ❌ | ✅ |
| Maintenance burden | High | Low | Medium |

**We chose the hybrid approach** because it gives us:

1. ✅ Granular control users want (turn off marketing, keep operational)
2. ✅ Native email client integration for better deliverability
3. ✅ Settings UI for managing all preferences in one place
4. ✅ Full control over unsubscribe logic and messaging
5. ✅ Analytics via Resend tags for email performance tracking


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.