This commit is contained in:
2025-12-31 17:45:49 +01:00
parent 42e8a02fde
commit 82ea760537
9 changed files with 689 additions and 129 deletions

View File

@@ -1,76 +1,140 @@
/**
* Email Templates - CRO-Optimized
*
* What's improved (based on email marketing best practices):
*
* Subject Lines:
* - More specific with urgency/outcome ("Expires in 1 Hour")
* - Emoji for visual attention in inbox
* - Clear value proposition
*
* Design & Copy:
* - Personal sender name ("Timo from QR Master")
* - Storytelling instead of feature lists
* - Trust elements (security badges, timelines)
* - Clear CTAs with action verbs ("Reset My Password →")
* - Objection handling built-in ("Didn't request this?")
* - Mobile-optimized (shorter paragraphs, more whitespace)
*
* How to measure if this works for YOUR audience:
* 1. Track baseline metrics (open rate, click rate, conversions)
* 2. A/B test old vs new templates
* 3. Measure with real users (minimum 100 emails per variant)
*
* No guarantees - only your data will tell what works for QR Master users.
*/
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
// Use a placeholder during build time, real key at runtime
const resendKey = process.env.RESEND_API_KEY || 're_placeholder_for_build';
const resend = new Resend(resendKey);
// Rate limiter for Resend Free Tier (1 email per second)
let lastEmailSent = 0;
const MIN_EMAIL_INTERVAL = 1000; // 1 second in milliseconds
async function waitForRateLimit() {
const now = Date.now();
const timeSinceLastEmail = now - lastEmailSent;
if (timeSinceLastEmail < MIN_EMAIL_INTERVAL) {
const waitTime = MIN_EMAIL_INTERVAL - timeSinceLastEmail;
await new Promise(resolve => setTimeout(resolve, waitTime));
}
lastEmailSent = Date.now();
}
/**
* Password Reset Email - Security focused with clear urgency
*/
export async function sendPasswordResetEmail(email: string, resetToken: string) {
await waitForRateLimit();
const appUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3050';
const resetUrl = `${appUrl}/reset-password?token=${resetToken}`;
try {
await resend.emails.send({
from: 'QR Master <onboarding@resend.dev>', // Use Resend's testing domain
from: 'QR Master Security <onboarding@resend.dev>',
replyTo: 'support@qrmaster.net',
to: email,
subject: 'Reset Your Password - QR Master',
subject: '🔐 Reset Your QR Master Password (Expires in 1 Hour)',
html: `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reset Your Password</title>
<title>Reset Your Password - QR Master</title>
</head>
<body style="margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f4f4f4;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f4f4f4; padding: 20px 0;">
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f4f4f4;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f4f4f4; padding: 40px 20px;">
<tr>
<td align="center">
<table width="600" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
<!-- Header -->
<!-- Main Container -->
<table width="600" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 12px rgba(0,0,0,0.08);">
<!-- Header with Security Badge -->
<tr>
<td style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 40px 30px; text-align: center;">
<h1 style="margin: 0; color: #ffffff; font-size: 28px; font-weight: bold;">QR Master</h1>
<td style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 50px 40px; text-align: center;">
<div style="display: inline-block; background-color: rgba(255,255,255,0.2); padding: 12px 24px; border-radius: 50px; margin-bottom: 20px;">
<span style="color: #ffffff; font-size: 14px; font-weight: 600; letter-spacing: 1px;">🔒 SECURITY ALERT</span>
</div>
<h1 style="margin: 0; color: #ffffff; font-size: 32px; font-weight: bold; line-height: 1.2;">Password Reset Request</h1>
<p style="margin: 15px 0 0 0; color: rgba(255,255,255,0.9); font-size: 16px;">Someone requested to reset your password</p>
</td>
</tr>
<!-- Content -->
<!-- Content Section -->
<tr>
<td style="padding: 40px 30px;">
<h2 style="margin: 0 0 20px 0; color: #333333; font-size: 24px;">Reset Your Password</h2>
<p style="margin: 0 0 20px 0; color: #666666; font-size: 16px; line-height: 1.5;">
<td style="padding: 50px 40px;">
<p style="margin: 0 0 20px 0; color: #333333; font-size: 16px; line-height: 1.6;">
Hi there,
</p>
<p style="margin: 0 0 30px 0; color: #666666; font-size: 16px; line-height: 1.5;">
You requested to reset your password for your QR Master account. Click the button below to choose a new password:
<p style="margin: 0 0 25px 0; color: #555555; font-size: 16px; line-height: 1.7;">
We received a request to reset the password for your QR Master account. If this was you, click the button below to create a new password:
</p>
<!-- Button -->
<table width="100%" cellpadding="0" cellspacing="0">
<!-- Primary CTA Button -->
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 35px 0;">
<tr>
<td align="center" style="padding: 20px 0;">
<a href="${resetUrl}" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; text-decoration: none; padding: 16px 40px; border-radius: 6px; font-size: 16px; font-weight: bold; display: inline-block;">
Reset Password
<td align="center">
<a href="${resetUrl}" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; text-decoration: none; padding: 18px 50px; border-radius: 8px; font-size: 17px; font-weight: 700; display: inline-block; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);">
🔐 Reset My Password
</a>
</td>
</tr>
</table>
<p style="margin: 30px 0 20px 0; color: #666666; font-size: 14px; line-height: 1.5;">
Or copy and paste this link into your browser:
</p>
<p style="margin: 0 0 30px 0; padding: 15px; background-color: #f8f8f8; border-radius: 4px; word-break: break-all;">
<a href="${resetUrl}" style="color: #667eea; text-decoration: none; font-size: 14px;">${resetUrl}</a>
</p>
<div style="border-top: 1px solid #eeeeee; padding-top: 20px; margin-top: 30px;">
<p style="margin: 0 0 10px 0; color: #999999; font-size: 13px; line-height: 1.5;">
<strong>This link will expire in 1 hour.</strong>
<!-- Security Info Box -->
<div style="background: linear-gradient(135deg, rgba(255, 107, 107, 0.08) 0%, rgba(255, 148, 148, 0.08) 100%); border-left: 4px solid #ff6b6b; padding: 20px 25px; margin: 35px 0; border-radius: 6px;">
<p style="margin: 0 0 12px 0; color: #d63031; font-size: 15px; font-weight: 700;">
⏱️ This link expires in 60 minutes
</p>
<p style="margin: 0; color: #666666; font-size: 14px; line-height: 1.6;">
For your security, this password reset link will only work once and expires after 1 hour. If you need a new link, you can request another one anytime.
</p>
</div>
<p style="margin: 0; color: #999999; font-size: 13px; line-height: 1.5;">
If you didn't request a password reset, you can safely ignore this email. Your password will not be changed.
<!-- Alternative Link -->
<p style="margin: 30px 0 15px 0; color: #888888; font-size: 14px; line-height: 1.5;">
🔗 Button not working? Copy and paste this link into your browser:
</p>
<p style="margin: 0 0 30px 0; padding: 18px 20px; background-color: #f8f9fa; border: 1px solid #e9ecef; border-radius: 6px; word-break: break-all;">
<a href="${resetUrl}" style="color: #667eea; text-decoration: none; font-size: 13px; font-family: monospace;">${resetUrl}</a>
</p>
<!-- Didn't Request This? -->
<div style="background-color: #f8f9fa; padding: 25px; border-radius: 8px; margin-top: 35px;">
<p style="margin: 0 0 12px 0; color: #333333; font-size: 15px; font-weight: 600;">
❓ Didn't request this?
</p>
<p style="margin: 0; color: #666666; font-size: 14px; line-height: 1.6;">
✅ You can safely ignore this email. Your password won't be changed unless you click the button above. If you're concerned about your account security, please contact us immediately at <a href="mailto:support@qrmaster.net" style="color: #667eea; text-decoration: none;">support@qrmaster.net</a>
</p>
</div>
</td>
@@ -78,15 +142,28 @@ export async function sendPasswordResetEmail(email: string, resetToken: string)
<!-- Footer -->
<tr>
<td style="background-color: #f8f8f8; padding: 30px; text-align: center; border-top: 1px solid #eeeeee;">
<p style="margin: 0 0 10px 0; color: #999999; font-size: 12px;">
© 2025 QR Master. All rights reserved.
</p>
<p style="margin: 0; color: #999999; font-size: 12px;">
This is an automated email. Please do not reply.
</p>
<td style="background-color: #f8f9fa; padding: 35px 40px; border-top: 1px solid #e9ecef;">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<p style="margin: 0 0 15px 0; color: #333333; font-size: 16px; font-weight: 600;">
QR Master
</p>
<p style="margin: 0 0 8px 0; color: #888888; font-size: 13px;">
Secure QR Code Analytics & Management
</p>
<p style="margin: 0; color: #999999; font-size: 12px;">
© 2025 QR Master. All rights reserved.
</p>
<p style="margin: 15px 0 0 0; color: #aaaaaa; font-size: 11px;">
This is an automated security email. Please do not reply.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
@@ -104,74 +181,161 @@ export async function sendPasswordResetEmail(email: string, resetToken: string)
}
}
/**
* Newsletter Welcome Email - Value-focused with clear expectations
*/
export async function sendNewsletterWelcomeEmail(email: string) {
await waitForRateLimit();
try {
await resend.emails.send({
from: 'QR Master <onboarding@resend.dev>',
from: 'Timo from QR Master <onboarding@resend.dev>',
replyTo: 'support@qrmaster.net',
to: email,
subject: '🎉 You\'re on the list! AI-Powered QR Features Coming Soon',
subject: '🎉 You\'re In! Here\'s What Happens Next (AI QR Features)',
html: `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to QR Master AI Newsletter</title>
<title>Welcome to QR Master AI Waitlist</title>
</head>
<body style="margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f4f4f4;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f4f4f4; padding: 20px 0;">
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f4f4f4;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f4f4f4; padding: 40px 20px;">
<tr>
<td align="center">
<table width="600" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
<!-- Header -->
<table width="600" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 12px rgba(0,0,0,0.08);">
<!-- Hero Header -->
<tr>
<td style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 40px 30px; text-align: center;">
<h1 style="margin: 0; color: #ffffff; font-size: 28px; font-weight: bold;">QR Master</h1>
<p style="margin: 10px 0 0 0; color: #ffffff; font-size: 16px; opacity: 0.9;">AI-Powered QR Features</p>
<td style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 50px 40px; text-align: center;">
<div style="display: inline-block; background-color: rgba(255,255,255,0.2); padding: 10px 20px; border-radius: 50px; margin-bottom: 20px;">
<span style="color: #ffffff; font-size: 13px; font-weight: 600; letter-spacing: 1px;">✨ EARLY ACCESS</span>
</div>
<h1 style="margin: 0; color: #ffffff; font-size: 36px; font-weight: bold; line-height: 1.2;">You're on the List! 🚀</h1>
<p style="margin: 20px 0 0 0; color: rgba(255,255,255,0.95); font-size: 18px; line-height: 1.5;">Get ready for AI-powered QR codes that work smarter, not harder</p>
</td>
</tr>
<!-- Content -->
<!-- Personal Note -->
<tr>
<td style="padding: 40px 30px;">
<h2 style="margin: 0 0 20px 0; color: #333333; font-size: 24px;">Welcome to the Future! 🚀</h2>
<p style="margin: 0 0 20px 0; color: #666666; font-size: 16px; line-height: 1.6;">
Thank you for signing up to be notified about our revolutionary AI-powered QR code features! You're among the first to know when these game-changing capabilities launch.
<td style="padding: 45px 40px 35px 40px;">
<p style="margin: 0 0 20px 0; color: #333333; font-size: 16px; line-height: 1.7;">
Hey there! 👋
</p>
<div style="background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%); border-left: 4px solid #667eea; padding: 20px; margin: 30px 0; border-radius: 4px;">
<h3 style="margin: 0 0 15px 0; color: #667eea; font-size: 18px;">What's Coming:</h3>
<ul style="margin: 0; padding-left: 20px; color: #666666; font-size: 15px; line-height: 1.8;">
<li><strong>Smart QR Generation</strong> - AI-powered content optimization & intelligent design suggestions</li>
<li><strong>Advanced Analytics</strong> - Scan predictions, anomaly detection & natural language queries</li>
<li><strong>Smart Content Management</strong> - AI chatbot, auto-categorization & smart bulk generation</li>
<li><strong>Creative & Marketing</strong> - AI-generated designs, copy generation & campaign optimization</li>
</ul>
<p style="margin: 0 0 25px 0; color: #555555; font-size: 16px; line-height: 1.7;">
Thanks for joining the waitlist for QR Master's AI-powered features. You're among the <strong>first to know</strong> when we launch something that'll completely change how you create and manage QR codes.
</p>
<p style="margin: 0 0 35px 0; color: #555555; font-size: 16px; line-height: 1.7;">
No fluff, no spam. Just a heads-up when these features go live.
</p>
<!-- What's Coming Section -->
<div style="background: linear-gradient(135deg, rgba(102, 126, 234, 0.08) 0%, rgba(118, 75, 162, 0.08) 100%); border-left: 4px solid #667eea; padding: 30px 30px; margin: 35px 0; border-radius: 8px;">
<h2 style="margin: 0 0 20px 0; color: #667eea; font-size: 20px; font-weight: 700;">
🎯 What You Can Expect
</h2>
<!-- Feature 1 -->
<div style="margin-bottom: 20px;">
<h3 style="margin: 0 0 8px 0; color: #333333; font-size: 16px; font-weight: 700;">
⚡ Smart QR Generation
</h3>
<p style="margin: 0; color: #666666; font-size: 15px; line-height: 1.6;">
AI analyzes your content and automatically suggests the optimal QR design, colors, and format for maximum scans. No more guessing what works.
</p>
</div>
<!-- Feature 2 -->
<div style="margin-bottom: 20px;">
<h3 style="margin: 0 0 8px 0; color: #333333; font-size: 16px; font-weight: 700;">
📊 Predictive Analytics
</h3>
<p style="margin: 0; color: #666666; font-size: 15px; line-height: 1.6;">
See scan forecasts, detect unusual patterns, and ask questions about your data in plain English. Your analytics become conversations, not spreadsheets.
</p>
</div>
<!-- Feature 3 -->
<div style="margin-bottom: 20px;">
<h3 style="margin: 0 0 8px 0; color: #333333; font-size: 16px; font-weight: 700;">
🤖 Auto-Organization
</h3>
<p style="margin: 0; color: #666666; font-size: 15px; line-height: 1.6;">
Your QR codes automatically get categorized, tagged, and organized. Spend less time managing, more time creating.
</p>
</div>
<!-- Feature 4 -->
<div>
<h3 style="margin: 0 0 8px 0; color: #333333; font-size: 16px; font-weight: 700;">
🎨 AI Design Studio
</h3>
<p style="margin: 0; color: #666666; font-size: 15px; line-height: 1.6;">
Generate unique, on-brand QR code designs in seconds. Just describe what you want, AI handles the rest.
</p>
</div>
</div>
<p style="margin: 20px 0; color: #666666; font-size: 16px; line-height: 1.6;">
We're working hard to bring these features to life and can't wait to share them with you. We'll send you an email as soon as they're ready to use!
<!-- Timeline -->
<div style="background-color: #fff3cd; border: 1px solid #ffc107; padding: 25px; border-radius: 8px; margin: 35px 0;">
<p style="margin: 0 0 12px 0; color: #856404; font-size: 15px; font-weight: 700;">
⏰ When Will This Happen?
</p>
<p style="margin: 0; color: #856404; font-size: 14px; line-height: 1.6;">
We're in active development and testing. You'll get an email the moment these features go live <strong>no waiting, no wondering</strong>. We respect your inbox.
</p>
</div>
<!-- Meanwhile CTA -->
<div style="background-color: #f8f9fa; padding: 30px; border-radius: 8px; margin: 35px 0; text-align: center;">
<h3 style="margin: 0 0 15px 0; color: #333333; font-size: 18px; font-weight: 700;">
💡 Want to Get Started Now?
</h3>
<p style="margin: 0 0 25px 0; color: #666666; font-size: 15px; line-height: 1.6;">
Our current platform already helps teams create, track, and manage dynamic QR codes. No AI needed just powerful tools that work today.
</p>
<a href="https://www.qrmaster.net/signup" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; text-decoration: none; padding: 16px 40px; border-radius: 8px; font-size: 16px; font-weight: 700; display: inline-block; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);">
🚀 Try QR Master Free →
</a>
</div>
<!-- Personal Sign-off -->
<p style="margin: 35px 0 0 0; color: #555555; font-size: 16px; line-height: 1.7;">
💌 Thanks for trusting us with your inbox. We'll make it worth it.
</p>
<p style="margin: 30px 0 0 0; color: #666666; font-size: 16px; line-height: 1.6;">
In the meantime, feel free to explore our existing features at <a href="https://www.qrmaster.net" style="color: #667eea; text-decoration: none;">qrmaster.net</a>
<p style="margin: 20px 0 0 0; color: #555555; font-size: 16px; line-height: 1.7;">
<strong>— Timo 👋</strong><br>
<span style="color: #888888; font-size: 14px;">Founder, QR Master</span>
</p>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background-color: #f8f8f8; padding: 30px; text-align: center; border-top: 1px solid #eeeeee;">
<p style="margin: 0 0 10px 0; color: #999999; font-size: 12px;">
© 2025 QR Master. All rights reserved.
</p>
<p style="margin: 0; color: #999999; font-size: 12px;">
You're receiving this email because you signed up for AI feature notifications.
</p>
<td style="background-color: #f8f9fa; padding: 35px 40px; border-top: 1px solid #e9ecef;">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<p style="margin: 0 0 8px 0; color: #888888; font-size: 13px;">
<a href="https://www.qrmaster.net" style="color: #667eea; text-decoration: none;">www.qrmaster.net</a>
</p>
<p style="margin: 0; color: #999999; font-size: 12px;">
© 2025 QR Master. All rights reserved.
</p>
<p style="margin: 15px 0 0 0; color: #aaaaaa; font-size: 11px;">
You're receiving this because you signed up for AI feature notifications.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
@@ -189,81 +353,169 @@ export async function sendNewsletterWelcomeEmail(email: string) {
}
}
/**
* AI Feature Launch Email - Excitement + clear CTA
*/
export async function sendAIFeatureLaunchEmail(email: string) {
await waitForRateLimit();
try {
await resend.emails.send({
from: 'QR Master <onboarding@resend.dev>',
from: 'Timo from QR Master <onboarding@resend.dev>',
replyTo: 'support@qrmaster.net',
to: email,
subject: '🚀 AI-Powered Features Are Here! QR Master Gets Smarter',
subject: '🚀 They\'re Live! Your AI QR Features Are Ready',
html: `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Features Launched!</title>
<title>AI Features Are Live - QR Master</title>
</head>
<body style="margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f4f4f4;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f4f4f4; padding: 20px 0;">
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f4f4f4;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f4f4f4; padding: 40px 20px;">
<tr>
<td align="center">
<table width="600" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
<!-- Header -->
<table width="600" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 12px rgba(0,0,0,0.08);">
<!-- Celebration Header -->
<tr>
<td style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 40px 30px; text-align: center;">
<h1 style="margin: 0; color: #ffffff; font-size: 32px; font-weight: bold;">🚀 They're Here!</h1>
<p style="margin: 10px 0 0 0; color: #ffffff; font-size: 18px; opacity: 0.95;">AI-Powered QR Features Are Live</p>
<td style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px 30px; text-align: center;">
<div style="font-size: 32px; margin-bottom: 10px;">🎉</div>
<div style="display: inline-block; background-color: rgba(255,255,255,0.2); padding: 6px 14px; border-radius: 50px; margin-bottom: 12px;">
<span style="color: #ffffff; font-size: 11px; font-weight: 600; letter-spacing: 1px;">✨ NOW LIVE</span>
</div>
<h1 style="margin: 0; color: #ffffff; font-size: 24px; font-weight: bold; line-height: 1.2;">AI Features Are Here! 🚀</h1>
<p style="margin: 10px 0 0 0; color: rgba(255,255,255,0.95); font-size: 14px; line-height: 1.4;">Ready to use in your dashboard</p>
</td>
</tr>
<!-- Content -->
<!-- Main Content -->
<tr>
<td style="padding: 40px 30px;">
<h2 style="margin: 0 0 20px 0; color: #333333; font-size: 24px;">The wait is over! ✨</h2>
<td style="padding: 50px 40px;">
<p style="margin: 0 0 20px 0; color: #666666; font-size: 16px; line-height: 1.6;">
We're excited to announce that the AI-powered features you've been waiting for are now live on QR Master! Your QR code creation just got a whole lot smarter.
<!-- Opening -->
<p style="margin: 0 0 25px 0; color: #333333; font-size: 17px; line-height: 1.7;">
Remember when you signed up to be notified about our AI features?
</p>
<div style="background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%); border-left: 4px solid #667eea; padding: 20px; margin: 30px 0; border-radius: 4px;">
<h3 style="margin: 0 0 15px 0; color: #667eea; font-size: 18px;">✨ What's New:</h3>
<ul style="margin: 0; padding-left: 20px; color: #666666; font-size: 15px; line-height: 1.8;">
<li><strong>Smart QR Generation</strong> - AI optimizes your content and suggests the best designs automatically</li>
<li><strong>Advanced Analytics</strong> - Predictive insights and natural language queries for your scan data</li>
<li><strong>Auto-Organization</strong> - Your QR codes get categorized and tagged automatically</li>
<li><strong>AI Design Studio</strong> - Generate unique, custom QR code designs with AI</li>
</ul>
<p style="margin: 0 0 25px 0; color: #333333; font-size: 17px; line-height: 1.7; font-weight: 700;">
Well, today's that day. 🎯
</p>
<p style="margin: 0 0 35px 0; color: #555555; font-size: 16px; line-height: 1.7;">
We've been building, testing, and polishing these features for months. And they're finally ready for you to use. Right now. No beta, no waitlist, no BS.
</p>
<!-- What's New Highlight Box -->
<div style="background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%); border: 2px solid #667eea; padding: 35px 30px; margin: 40px 0; border-radius: 10px;">
<h2 style="margin: 0 0 25px 0; color: #667eea; font-size: 22px; font-weight: 700; text-align: center;">
✨ What's New in Your Dashboard
</h2>
<!-- Feature Cards -->
<div style="background-color: #ffffff; padding: 25px; margin-bottom: 15px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">
<h3 style="margin: 0 0 10px 0; color: #333333; font-size: 17px; font-weight: 700;">
⚡ Smart QR Generation
</h3>
<p style="margin: 0; color: #666666; font-size: 15px; line-height: 1.6;">
AI analyzes your content and suggests optimal designs automatically. Just paste your link, we handle the optimization.
</p>
</div>
<div style="background-color: #ffffff; padding: 25px; margin-bottom: 15px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">
<h3 style="margin: 0 0 10px 0; color: #333333; font-size: 17px; font-weight: 700;">
📊 Predictive Analytics
</h3>
<p style="margin: 0; color: #666666; font-size: 15px; line-height: 1.6;">
Ask questions about your scan data in plain English. "Which campaign performed best last month?" Done.
</p>
</div>
<div style="background-color: #ffffff; padding: 25px; margin-bottom: 15px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">
<h3 style="margin: 0 0 10px 0; color: #333333; font-size: 17px; font-weight: 700;">
🤖 Auto-Organization
</h3>
<p style="margin: 0; color: #666666; font-size: 15px; line-height: 1.6;">
QR codes automatically categorized and tagged. Your library stays organized without manual work.
</p>
</div>
<div style="background-color: #ffffff; padding: 25px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">
<h3 style="margin: 0 0 10px 0; color: #333333; font-size: 17px; font-weight: 700;">
🎨 AI Design Studio
</h3>
<p style="margin: 0; color: #666666; font-size: 15px; line-height: 1.6;">
Generate custom QR designs by describing what you want. "Make it modern and blue" → Done in 3 seconds.
</p>
</div>
</div>
<!-- CTA Button -->
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 30px 0;">
<!-- How to Access -->
<div style="background-color: #fff3cd; border: 2px solid #ffc107; padding: 30px; border-radius: 10px; margin: 40px 0;">
<h3 style="margin: 0 0 15px 0; color: #856404; font-size: 18px; font-weight: 700;">
🎯 How to Get Started
</h3>
<ol style="margin: 0; padding-left: 20px; color: #856404; font-size: 15px; line-height: 1.8;">
<li style="margin-bottom: 10px;">🔐 Log in to your QR Master account</li>
<li style="margin-bottom: 10px;">👀 Look for the "✨ AI" badge on supported features</li>
<li style="margin-bottom: 10px;">✏️ Try creating a QR code you'll see AI suggestions automatically</li>
<li>📈 Check your Analytics tab for the new AI query interface</li>
</ol>
</div>
<!-- Primary CTA -->
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 45px 0 40px 0;">
<tr>
<td align="center">
<a href="https://www.qrmaster.net/create" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; text-decoration: none; padding: 16px 40px; border-radius: 8px; font-size: 16px; font-weight: bold; display: inline-block;">
Try AI Features Now
<a href="https://www.qrmaster.net/create" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; text-decoration: none; padding: 20px 60px; border-radius: 10px; font-size: 18px; font-weight: 700; display: inline-block; box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);">
Try AI Features Now
</a>
<p style="margin: 20px 0 0 0; color: #888888; font-size: 13px;">
✅ Available on all plans • ⚡ No extra setup required
</p>
</td>
</tr>
</table>
<p style="margin: 20px 0 0 0; color: #666666; font-size: 16px; line-height: 1.6;">
Log in to your QR Master account and start exploring the new AI capabilities. We can't wait to see what you create!
</p>
<!-- Personal Note -->
<div style="background-color: #f8f9fa; padding: 30px; border-radius: 8px; margin: 40px 0;">
<p style="margin: 0 0 20px 0; color: #555555; font-size: 15px; line-height: 1.7;">
💬 We're excited to see what you build with these new tools. If you have questions, ideas, or just want to share what you created <a href="mailto:support@qrmaster.net" style="color: #667eea; text-decoration: none;">hit reply</a>. I read every email.
</p>
<p style="margin: 0; color: #555555; font-size: 15px; line-height: 1.7;">
<strong>— Timo 👋</strong><br>
<span style="color: #888888; font-size: 13px;">Founder, QR Master</span>
</p>
</div>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background-color: #f8f8f8; padding: 30px; text-align: center; border-top: 1px solid #eeeeee;">
<p style="margin: 0 0 10px 0; color: #999999; font-size: 12px;">
© 2025 QR Master. All rights reserved.
</p>
<p style="margin: 0; color: #999999; font-size: 12px;">
You received this email because you subscribed to AI feature notifications.
</p>
<td style="background-color: #f8f9fa; padding: 35px 40px; border-top: 1px solid #e9ecef;">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<p style="margin: 0 0 8px 0; color: #888888; font-size: 13px;">
<a href="https://www.qrmaster.net" style="color: #667eea; text-decoration: none;">www.qrmaster.net</a> •
<a href="https://www.qrmaster.net/dashboard" style="color: #667eea; text-decoration: none;">Dashboard</a> •
<a href="https://www.qrmaster.net/faq" style="color: #667eea; text-decoration: none;">Help</a>
</p>
<p style="margin: 0; color: #999999; font-size: 12px;">
© 2025 QR Master. All rights reserved.
</p>
<p style="margin: 15px 0 0 0; color: #aaaaaa; font-size: 11px;">
You received this because you subscribed to AI feature launch notifications.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>

View File

@@ -1,14 +1,20 @@
import Stripe from 'stripe';
if (!process.env.STRIPE_SECRET_KEY) {
throw new Error('STRIPE_SECRET_KEY is not set');
}
// Use a placeholder during build time, real key at runtime
const stripeKey = process.env.STRIPE_SECRET_KEY || 'sk_test_placeholder_for_build';
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: '2025-09-30.clover',
export const stripe = new Stripe(stripeKey, {
apiVersion: '2025-10-29.clover',
typescript: true,
});
// Runtime validation (will throw when actually used in production if not set)
export function validateStripeKey() {
if (!process.env.STRIPE_SECRET_KEY) {
throw new Error('STRIPE_SECRET_KEY is not set');
}
}
export const STRIPE_PLANS = {
FREE: {
name: 'Free / Starter',