Files
ShieldAI/plans/waitlist-email-sequence-implementation.md

4.3 KiB

Waitlist Email Sequence — Implementation Guide

Overview

This document describes how to integrate the waitlist email templates into the waitlist signup flow. The 4-email welcome sequence is designed for new ShieldAI waitlist signups.

Templates Added

# Template ID Timing Purpose
1 waitlist_confirmation Immediate Confirm waitlist signup, show position
2 waitlist_intro Day +1 Introduce ShieldAI and the problem it solves
3 waitlist_features Day +3 Deep dive into product features
4 waitlist_launch_teaser Day +7 Launch teaser, early adopter perks

File: packages/shared-notifications/src/templates/default-templates.ts

  • All 4 templates use buildEmailHtml() from waitlist-email-layout.ts for consistent dark-themed, responsive HTML email rendering with the ShieldAI brand (Inter font, #0a0f1e dark background, #3b82f6→#06b6d4 gradient accent).
  • Spanish locale (es) is provided for template 1.

Variables per Template

waitlist_confirmation

Variable Type Required Default
name string no "there"
position string yes
unsubscribe_url string no https://shieldai.com/unsubscribe

waitlist_intro

Variable Type Required Default
name string no "there"
unsubscribe_url string no https://shieldai.com/unsubscribe

waitlist_features

Variable Type Required Default
name string no "there"
unsubscribe_url string no https://shieldai.com/unsubscribe

waitlist_launch_teaser

Variable Type Required Default
name string no "there"
referral_url string no https://shieldai.com/waitlist
unsubscribe_url string no https://shieldai.com/unsubscribe

Integration Points

1. Immediate Email (on signup)

In packages/api/src/routes/waitlist.routes.ts, after prisma.waitlistEntry.create() succeeds:

import { EmailService } from '@shieldai/shared-notifications';

// Send confirmation immediately
await EmailService.getInstance().sendWithTemplate(email, {
  templateId: 'waitlist_confirmation',
  locale: 'en', // derive from request if available
  variables: {
    name: body.name || 'there',
    position: String(waitlistCount),
  },
});

2. Scheduled Emails (Day 1, 3, 7)

Use a job queue (BullMQ is already planned) to schedule the subsequent emails:

// On signup, enqueue 3 scheduled jobs
await emailQueue.add('send-waitlist-email', {
  email: body.email,
  name: body.name,
  templateId: 'waitlist_intro',
}, { delay: 24 * 60 * 60 * 1000 }); // +1 day

await emailQueue.add('send-waitlist-email', {
  email: body.email,
  name: body.name,
  templateId: 'waitlist_features',
}, { delay: 3 * 24 * 60 * 60 * 1000 }); // +3 days

await emailQueue.add('send-waitlist-email', {
  email: body.email,
  name: body.name,
  templateId: 'waitlist_launch_teaser',
}, { delay: 7 * 24 * 60 * 60 * 1000 }); // +7 days

If BullMQ is not yet available, use setTimeout or a simple cron-based approach:

// packages/api/src/jobs/waitlist-emails.ts
// Run on a cron every hour, check for pending scheduled emails
// Store scheduled_at in WaitlistEntry metadata or a separate table

3. Rate Limiting

The EmailService already enforces a default rate limit of 60 emails/minute per recipient. No additional rate limit config should be needed for the waitlist flow.

4. Unsubscribe Handling

The email footer includes an {{unsubscribe_url}} variable. Implement a standard unsubscribe endpoint:

  • GET /api/unsubscribe?token=<token> — one-click unsubscribe
  • Store unsubscribe preferences per email address

Testing

  1. Unit test: Verify template rendering with TemplateService.getInstance().resolveTemplate()
  2. Integration test: Call POST /api/waitlist/signup and verify email is sent (use Resend test API keys)
  3. Manual test: Use Resend email preview to verify rendering across Gmail, Outlook, Apple Mail

Rollout Checklist

  • Add RESEND_API_KEY to production environment
  • Verify templates render correctly via Resend API
  • Test unsubscribe flow
  • Verify rate limits for launch-day traffic spike
  • Monitor email delivery (bounce rate, open rate) post-launch