Skip to content

Conversation

@waleedlatif1
Copy link
Collaborator

Summary

  • update unsub page, standardize unsub process

Type of Change

  • Improvement
  • New feature

Testing

N/A

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link

vercel bot commented Jan 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Review Updated (UTC)
docs Skipped Skipped Jan 19, 2026 4:37am

Request Review

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 19, 2026

Greptile Summary

This PR refactors the unsubscribe system to use a placeholder-based approach and updates the unsubscribe page UI for better consistency with the rest of the application.

Key Changes:

  • Standardized unsubscribe link generation: Email footer now uses {{UNSUBSCRIBE_TOKEN}} and {{UNSUBSCRIBE_EMAIL}} placeholders that are replaced by the mailer when sending emails, eliminating the need to pass unsubscribe data through component props
  • Simplified unsubscribe page: Replaced verbose Card-based UI with InviteLayout component for consistency with auth pages, reducing code from ~400 to ~300 lines
  • Email template updates: All 23 email templates now explicitly specify showUnsubscribe prop (true for marketing/notifications, false for transactional emails like auth/invitations)
  • Improved mailer logic: Enhanced batch email handling to apply unsubscribe placeholder replacement correctly, ensuring the email parameter is properly encoded in URLs
  • Code cleanup: Removed redundant comments from utility functions and tests for better readability

Architecture improvements:

  • The placeholder approach decouples email template rendering from runtime unsubscribe data, making templates more reusable and testable
  • Backward compatibility maintained for legacy 2-part tokens (without email type)
  • Cleaner separation between transactional and non-transactional email handling

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • Well-structured refactor that improves consistency across email templates and simplifies the unsubscribe page UI. Changes are focused, backward-compatible (supports legacy tokens), and well-tested. The standardization approach with placeholders is cleaner than prop-passing.
  • No files require special attention

Important Files Changed

Filename Overview
apps/sim/app/unsubscribe/unsubscribe.tsx Significantly simplified UI from Card-based layout to InviteLayout, reduced ~400 lines to ~300, better consistency with auth pages
apps/sim/lib/messaging/email/mailer.ts Added {{UNSUBSCRIBE_EMAIL}} placeholder replacement for standardized footer links, improved batch email handling logic
apps/sim/components/emails/components/email-footer.tsx Replaced prop-based unsubscribe data with placeholder-based system using {{UNSUBSCRIBE_TOKEN}} and {{UNSUBSCRIBE_EMAIL}}, added showUnsubscribe flag
apps/sim/components/emails/components/email-layout.tsx Added required showUnsubscribe prop to control unsubscribe link visibility in footer

Sequence Diagram

sequenceDiagram
    participant User
    participant EmailTemplate
    participant Mailer
    participant UnsubUtils
    participant EmailClient
    participant UnsubPage
    participant API
    participant DB

    Note over EmailTemplate,Mailer: Email Sending Flow
    EmailTemplate->>Mailer: sendEmail(options)
    Mailer->>UnsubUtils: isUnsubscribed(email, type)
    UnsubUtils->>DB: Check email preferences
    DB-->>UnsubUtils: Return preferences
    alt User has unsubscribed
        UnsubUtils-->>Mailer: true
        Mailer-->>EmailTemplate: Skip email
    else User subscribed
        UnsubUtils-->>Mailer: false
        Mailer->>UnsubUtils: generateUnsubscribeToken(email, emailType)
        UnsubUtils-->>Mailer: token
        Mailer->>Mailer: Replace {{UNSUBSCRIBE_TOKEN}} and {{UNSUBSCRIBE_EMAIL}}
        Mailer->>EmailClient: Send email with unsubscribe link
        EmailClient-->>User: Email delivered
    end

    Note over User,DB: Unsubscribe Flow
    User->>UnsubPage: Click unsubscribe link (email + token)
    UnsubPage->>API: GET /api/users/me/settings/unsubscribe
    API->>UnsubUtils: verifyUnsubscribeToken(email, token)
    UnsubUtils-->>API: {valid: true, emailType}
    API->>UnsubUtils: getEmailPreferences(email)
    UnsubUtils->>DB: Query preferences
    DB-->>UnsubUtils: Current preferences
    UnsubUtils-->>API: Preferences
    API-->>UnsubPage: {success, emailType, isTransactional, currentPreferences}
    
    alt Transactional Email
        UnsubPage->>User: Show cannot unsubscribe message
    else Non-transactional Email
        User->>UnsubPage: Select unsubscribe option
        UnsubPage->>API: POST /api/users/me/settings/unsubscribe
        API->>UnsubUtils: verifyUnsubscribeToken(email, token)
        UnsubUtils-->>API: {valid: true}
        API->>UnsubUtils: updateEmailPreferences(email, prefs)
        UnsubUtils->>DB: Upsert settings with new preferences
        DB-->>UnsubUtils: Success
        UnsubUtils-->>API: true
        API-->>UnsubPage: {success: true}
        UnsubPage->>User: Show success message
    end
Loading

@waleedlatif1 waleedlatif1 merged commit b4c2294 into staging Jan 19, 2026
11 checks passed
@waleedlatif1 waleedlatif1 deleted the feat/unsub branch January 19, 2026 04:42
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.

2 participants