fraim 2.0.281 → 2.0.284

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -227,40 +227,40 @@ class EmailService {
227
227
  const codeText = `Open ${actionUrl} and enter this code:\n\n${code}`;
228
228
  return {
229
229
  subject: isRequestAccess ? 'Your FRAIM verification code' : 'Sign in to FRAIM',
230
- html: `
231
- <!DOCTYPE html>
232
- <html>
233
- <head>
234
- <style>
235
- body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
236
- .container { max-width: 600px; margin: 0 auto; padding: 20px; }
237
- .button {
238
- display: inline-block;
239
- padding: 12px 24px;
240
- background-color: #10b981;
241
- color: #ffffff !important;
242
- text-decoration: none;
243
- border-radius: 5px;
244
- margin: 20px 0;
245
- }
246
- .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
247
- </style>
248
- </head>
249
- <body>
250
- <div class="container">
251
- <h2>${heading}</h2>
252
- <p>${introText}</p>
253
- <div style="font-size:28px;letter-spacing:4px;font-weight:bold;background:#f3f4f6;border:1px solid #d1d5db;border-radius:6px;padding:12px 16px;display:inline-block;color:#111827">${code}</div>
254
- <p><a href="${actionUrl}" style="display:inline-block;padding:12px 24px;background-color:#10b981;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">${buttonText}</a></p>
255
- <p>This code expires in ${expiresInMinutes} minutes.</p>
256
- <p>If you didn't request this, you can safely ignore this email.</p>
257
- <div class="footer">
258
- <p>FRAIM - Framework for Rigor-based AI Management<br>
259
- <a href="${this.baseUrl}">fraimworks.ai</a></p>
260
- </div>
261
- </div>
262
- </body>
263
- </html>
230
+ html: `
231
+ <!DOCTYPE html>
232
+ <html>
233
+ <head>
234
+ <style>
235
+ body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
236
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
237
+ .button {
238
+ display: inline-block;
239
+ padding: 12px 24px;
240
+ background-color: #10b981;
241
+ color: #ffffff !important;
242
+ text-decoration: none;
243
+ border-radius: 5px;
244
+ margin: 20px 0;
245
+ }
246
+ .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
247
+ </style>
248
+ </head>
249
+ <body>
250
+ <div class="container">
251
+ <h2>${heading}</h2>
252
+ <p>${introText}</p>
253
+ <div style="font-size:28px;letter-spacing:4px;font-weight:bold;background:#f3f4f6;border:1px solid #d1d5db;border-radius:6px;padding:12px 16px;display:inline-block;color:#111827">${code}</div>
254
+ <p><a href="${actionUrl}" style="display:inline-block;padding:12px 24px;background-color:#10b981;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">${buttonText}</a></p>
255
+ <p>This code expires in ${expiresInMinutes} minutes.</p>
256
+ <p>If you didn't request this, you can safely ignore this email.</p>
257
+ <div class="footer">
258
+ <p>FRAIM - Framework for Rigor-based AI Management<br>
259
+ <a href="${this.baseUrl}">fraimworks.ai</a></p>
260
+ </div>
261
+ </div>
262
+ </body>
263
+ </html>
264
264
  `,
265
265
  text: `${heading}\n\n${codeText}\n\nThis code expires in ${expiresInMinutes} minutes.\n\nIf you didn't request this, you can safely ignore this email.\n\nFRAIM - Framework for Rigor-based AI Management\n${this.baseUrl}`
266
266
  };
@@ -269,62 +269,62 @@ class EmailService {
269
269
  const daysRemaining = Math.ceil((expiresAt.getTime() - Date.now()) / (1000 * 60 * 60 * 24));
270
270
  return {
271
271
  subject: 'Welcome to FRAIM! Your 14-day trial starts now',
272
- html: `
273
- <!DOCTYPE html>
274
- <html>
275
- <head>
276
- <style>
277
- body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
278
- .container { max-width: 600px; margin: 0 auto; padding: 20px; }
279
- .api-key {
280
- background: #f5f5f5;
281
- padding: 15px;
282
- border-radius: 5px;
283
- font-family: monospace;
284
- word-break: break-all;
285
- margin: 20px 0;
286
- }
287
- .button {
288
- display: inline-block;
289
- padding: 12px 24px;
290
- background-color: #10b981;
291
- color: #ffffff !important;
292
- text-decoration: none;
293
- border-radius: 5px;
294
- margin: 20px 0;
295
- }
296
- .highlight { background: #fff3cd; padding: 15px; border-left: 4px solid #ffc107; margin: 20px 0; }
297
- .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
298
- </style>
299
- </head>
300
- <body>
301
- <div class="container">
302
- <h2>🎉 Welcome to FRAIM!</h2>
303
- <p>Your 14-day free trial is now active. Here's your API key:</p>
304
- <div class="api-key">${apiKey}</div>
305
-
306
- <div class="highlight">
307
- <strong>Trial expires:</strong> ${expiresAt.toLocaleDateString()} (${daysRemaining} days remaining)
308
- </div>
309
-
310
- <h3>Get Started:</h3>
311
- <ol>
312
- <li><a href="${this.baseUrl}/dashboard">Access your dashboard</a></li>
313
- <li>Download the installer for your platform</li>
314
- <li>Run your first AI-managed workflow</li>
315
- </ol>
316
-
317
- <a href="${this.baseUrl}/docs/quickstart" style="display:inline-block;padding:12px 24px;background-color:#10b981;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">View Quickstart Guide</a>
318
- <p>Prefer a walkthrough first? Watch the onboarding videos on the FRAIM website:</p>
319
- <p><a href="${this.baseUrl}/resources.html#videos">${this.baseUrl}/resources.html#videos</a></p>
320
-
321
- <div class="footer">
322
- <p>Questions? Reply to this email or visit <a href="${this.baseUrl}/docs">our docs</a>.</p>
323
- <p>FRAIM - Framework for Rigor-based AI Management</p>
324
- </div>
325
- </div>
326
- </body>
327
- </html>
272
+ html: `
273
+ <!DOCTYPE html>
274
+ <html>
275
+ <head>
276
+ <style>
277
+ body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
278
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
279
+ .api-key {
280
+ background: #f5f5f5;
281
+ padding: 15px;
282
+ border-radius: 5px;
283
+ font-family: monospace;
284
+ word-break: break-all;
285
+ margin: 20px 0;
286
+ }
287
+ .button {
288
+ display: inline-block;
289
+ padding: 12px 24px;
290
+ background-color: #10b981;
291
+ color: #ffffff !important;
292
+ text-decoration: none;
293
+ border-radius: 5px;
294
+ margin: 20px 0;
295
+ }
296
+ .highlight { background: #fff3cd; padding: 15px; border-left: 4px solid #ffc107; margin: 20px 0; }
297
+ .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
298
+ </style>
299
+ </head>
300
+ <body>
301
+ <div class="container">
302
+ <h2>🎉 Welcome to FRAIM!</h2>
303
+ <p>Your 14-day free trial is now active. Here's your API key:</p>
304
+ <div class="api-key">${apiKey}</div>
305
+
306
+ <div class="highlight">
307
+ <strong>Trial expires:</strong> ${expiresAt.toLocaleDateString()} (${daysRemaining} days remaining)
308
+ </div>
309
+
310
+ <h3>Get Started:</h3>
311
+ <ol>
312
+ <li><a href="${this.baseUrl}/dashboard">Access your dashboard</a></li>
313
+ <li>Download the installer for your platform</li>
314
+ <li>Run your first AI-managed workflow</li>
315
+ </ol>
316
+
317
+ <a href="${this.baseUrl}/docs/quickstart" style="display:inline-block;padding:12px 24px;background-color:#10b981;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">View Quickstart Guide</a>
318
+ <p>Prefer a walkthrough first? Watch the onboarding videos on the FRAIM website:</p>
319
+ <p><a href="${this.baseUrl}/resources.html#videos">${this.baseUrl}/resources.html#videos</a></p>
320
+
321
+ <div class="footer">
322
+ <p>Questions? Reply to this email or visit <a href="${this.baseUrl}/docs">our docs</a>.</p>
323
+ <p>FRAIM - Framework for Rigor-based AI Management</p>
324
+ </div>
325
+ </div>
326
+ </body>
327
+ </html>
328
328
  `,
329
329
  text: `Welcome to FRAIM!\n\nYour 14-day free trial is now active. Here's your API key:\n\n${apiKey}\n\nTrial expires: ${expiresAt.toLocaleDateString()} (${daysRemaining} days remaining)\n\nGet Started:\n1. Access your dashboard: ${this.baseUrl}/dashboard\n2. Download the installer for your platform\n3. Run your first AI-managed workflow\n\nView Quickstart Guide: ${this.baseUrl}/docs/quickstart\nWatch onboarding videos: ${this.baseUrl}/resources.html#videos\n\nQuestions? Reply to this email or visit our docs.`
330
330
  };
@@ -333,50 +333,50 @@ class EmailService {
333
333
  const daysRemaining = Math.ceil((expiresAt.getTime() - Date.now()) / (1000 * 60 * 60 * 24));
334
334
  return {
335
335
  subject: "You've been using FRAIM for a week!",
336
- html: `
337
- <!DOCTYPE html>
338
- <html>
339
- <head>
340
- <style>
341
- body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
342
- .container { max-width: 600px; margin: 0 auto; padding: 20px; }
343
- .button {
344
- display: inline-block;
345
- padding: 12px 24px;
346
- background-color: #10b981;
347
- color: #ffffff !important;
348
- text-decoration: none;
349
- border-radius: 5px;
350
- margin: 20px 0;
351
- }
352
- .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
353
- </style>
354
- </head>
355
- <body>
356
- <div class="container">
357
- <h2>How's FRAIM working for you?</h2>
358
- <p>You've been using FRAIM for a week now. We hope it's helping you manage your AI agents more effectively!</p>
359
-
360
- <p><strong>Your trial ends in ${daysRemaining} days</strong> (${expiresAt.toLocaleDateString()})</p>
361
-
362
- <h3>Upgrade to Pro for:</h3>
363
- <ul>
364
- <li>Unlimited usage (no expiration)</li>
365
- <li>Priority support</li>
366
- <li>Advanced workflows</li>
367
- <li>Team collaboration features</li>
368
- </ul>
369
-
370
- <p><strong>Special offer for early adopters:</strong> 90% off for pre-seed, pre-revenue founders!</p>
371
-
372
- <a href="${this.baseUrl}/upgrade" style="display:inline-block;padding:12px 24px;background-color:#10b981;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">Upgrade to Pro</a>
373
-
374
- <div class="footer">
375
- <p>FRAIM - Framework for Rigor-based AI Management</p>
376
- </div>
377
- </div>
378
- </body>
379
- </html>
336
+ html: `
337
+ <!DOCTYPE html>
338
+ <html>
339
+ <head>
340
+ <style>
341
+ body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
342
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
343
+ .button {
344
+ display: inline-block;
345
+ padding: 12px 24px;
346
+ background-color: #10b981;
347
+ color: #ffffff !important;
348
+ text-decoration: none;
349
+ border-radius: 5px;
350
+ margin: 20px 0;
351
+ }
352
+ .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
353
+ </style>
354
+ </head>
355
+ <body>
356
+ <div class="container">
357
+ <h2>How's FRAIM working for you?</h2>
358
+ <p>You've been using FRAIM for a week now. We hope it's helping you manage your AI agents more effectively!</p>
359
+
360
+ <p><strong>Your trial ends in ${daysRemaining} days</strong> (${expiresAt.toLocaleDateString()})</p>
361
+
362
+ <h3>Upgrade to Pro for:</h3>
363
+ <ul>
364
+ <li>Unlimited usage (no expiration)</li>
365
+ <li>Priority support</li>
366
+ <li>Advanced workflows</li>
367
+ <li>Team collaboration features</li>
368
+ </ul>
369
+
370
+ <p><strong>Special offer for early adopters:</strong> 90% off for pre-seed, pre-revenue founders!</p>
371
+
372
+ <a href="${this.baseUrl}/upgrade" style="display:inline-block;padding:12px 24px;background-color:#10b981;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">Upgrade to Pro</a>
373
+
374
+ <div class="footer">
375
+ <p>FRAIM - Framework for Rigor-based AI Management</p>
376
+ </div>
377
+ </div>
378
+ </body>
379
+ </html>
380
380
  `,
381
381
  text: `How's FRAIM working for you?\n\nYou've been using FRAIM for a week now. We hope it's helping you manage your AI agents more effectively!\n\nYour trial ends in ${daysRemaining} days (${expiresAt.toLocaleDateString()})\n\nUpgrade to Pro for:\n- Unlimited usage (no expiration)\n- Priority support\n- Advanced workflows\n- Team collaboration features\n\nSpecial offer for early adopters: 90% off for pre-seed, pre-revenue founders!\n\nUpgrade: ${this.baseUrl}/upgrade`
382
382
  };
@@ -385,59 +385,59 @@ class EmailService {
385
385
  const urgency = daysRemaining <= 1 ? '🚨 Last day' : '⚠️ Trial ending soon';
386
386
  return {
387
387
  subject: `${urgency} - Your FRAIM trial expires in ${daysRemaining} day${daysRemaining !== 1 ? 's' : ''}`,
388
- html: `
389
- <!DOCTYPE html>
390
- <html>
391
- <head>
392
- <style>
393
- body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
394
- .container { max-width: 600px; margin: 0 auto; padding: 20px; }
395
- .button {
396
- display: inline-block;
397
- padding: 12px 24px;
398
- background-color: #dc3545;
399
- color: #ffffff !important;
400
- text-decoration: none;
401
- border-radius: 5px;
402
- margin: 20px 0;
403
- }
404
- .warning { background: #fff3cd; padding: 20px; border-left: 4px solid #ffc107; margin: 20px 0; }
405
- .pricing { background: #f8f9fa; padding: 20px; border-radius: 5px; margin: 20px 0; }
406
- .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
407
- </style>
408
- </head>
409
- <body>
410
- <div class="container">
411
- <h2>${urgency}</h2>
412
-
413
- <div class="warning">
414
- <strong>Your FRAIM trial expires on ${expiresAt.toLocaleDateString()}</strong><br>
415
- (${daysRemaining} day${daysRemaining !== 1 ? 's' : ''} remaining)
416
- </div>
417
-
418
- <p><strong>What happens when your trial ends:</strong></p>
419
- <ul>
420
- <li>Your API key will stop working</li>
421
- <li>You won't be able to run workflows</li>
422
- <li>Your data is preserved - upgrade anytime to reactivate</li>
423
- </ul>
424
-
425
- <div class="pricing">
426
- <h3>Choose your plan:</h3>
427
- <p><strong>Regular pricing:</strong> $200/month or $2,000/year (save 17%)</p>
428
- <p><strong>Founder discount (90% off):</strong> $20/month or $200/year<br>
429
- <em>Available to pre-seed, pre-revenue founders with corporate email</em></p>
430
- </div>
431
-
432
- <a href="${this.baseUrl}/upgrade" style="display:inline-block;padding:12px 24px;background-color:#dc3545;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">Upgrade Now - Don't Lose Access</a>
433
-
434
- <div class="footer">
435
- <p>Questions? Reply to this email.</p>
436
- <p>FRAIM - Framework for Rigor-based AI Management</p>
437
- </div>
438
- </div>
439
- </body>
440
- </html>
388
+ html: `
389
+ <!DOCTYPE html>
390
+ <html>
391
+ <head>
392
+ <style>
393
+ body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
394
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
395
+ .button {
396
+ display: inline-block;
397
+ padding: 12px 24px;
398
+ background-color: #dc3545;
399
+ color: #ffffff !important;
400
+ text-decoration: none;
401
+ border-radius: 5px;
402
+ margin: 20px 0;
403
+ }
404
+ .warning { background: #fff3cd; padding: 20px; border-left: 4px solid #ffc107; margin: 20px 0; }
405
+ .pricing { background: #f8f9fa; padding: 20px; border-radius: 5px; margin: 20px 0; }
406
+ .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
407
+ </style>
408
+ </head>
409
+ <body>
410
+ <div class="container">
411
+ <h2>${urgency}</h2>
412
+
413
+ <div class="warning">
414
+ <strong>Your FRAIM trial expires on ${expiresAt.toLocaleDateString()}</strong><br>
415
+ (${daysRemaining} day${daysRemaining !== 1 ? 's' : ''} remaining)
416
+ </div>
417
+
418
+ <p><strong>What happens when your trial ends:</strong></p>
419
+ <ul>
420
+ <li>Your API key will stop working</li>
421
+ <li>You won't be able to run workflows</li>
422
+ <li>Your data is preserved - upgrade anytime to reactivate</li>
423
+ </ul>
424
+
425
+ <div class="pricing">
426
+ <h3>Choose your plan:</h3>
427
+ <p><strong>Regular pricing:</strong> $200/month or $2,000/year (save 17%)</p>
428
+ <p><strong>Founder discount (90% off):</strong> $20/month or $200/year<br>
429
+ <em>Available to pre-seed, pre-revenue founders with corporate email</em></p>
430
+ </div>
431
+
432
+ <a href="${this.baseUrl}/upgrade" style="display:inline-block;padding:12px 24px;background-color:#dc3545;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">Upgrade Now - Don't Lose Access</a>
433
+
434
+ <div class="footer">
435
+ <p>Questions? Reply to this email.</p>
436
+ <p>FRAIM - Framework for Rigor-based AI Management</p>
437
+ </div>
438
+ </div>
439
+ </body>
440
+ </html>
441
441
  `,
442
442
  text: `${urgency}\n\nYour FRAIM trial expires on ${expiresAt.toLocaleDateString()} (${daysRemaining} day${daysRemaining !== 1 ? 's' : ''} remaining)\n\nWhat happens when your trial ends:\n- Your API key will stop working\n- You won't be able to run workflows\n- Your data is preserved - upgrade anytime to reactivate\n\nChoose your plan:\n\nRegular pricing: $200/month or $2,000/year (save 17%)\n\nFounder discount (90% off): $20/month or $200/year\nAvailable to pre-seed, pre-revenue founders with corporate email\n\nUpgrade now: ${this.baseUrl}/upgrade`
443
443
  };
@@ -445,50 +445,50 @@ class EmailService {
445
445
  generateTrialExpiredTemplate(expiredAt) {
446
446
  return {
447
447
  subject: 'Your FRAIM trial has ended',
448
- html: `
449
- <!DOCTYPE html>
450
- <html>
451
- <head>
452
- <style>
453
- body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
454
- .container { max-width: 600px; margin: 0 auto; padding: 20px; }
455
- .button {
456
- display: inline-block;
457
- padding: 12px 24px;
458
- background-color: #10b981;
459
- color: #ffffff !important;
460
- text-decoration: none;
461
- border-radius: 5px;
462
- margin: 20px 0;
463
- }
464
- .highlight { background: #e7f3ff; padding: 20px; border-left: 4px solid #0066cc; margin: 20px 0; }
465
- .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
466
- </style>
467
- </head>
468
- <body>
469
- <div class="container">
470
- <h2>Your FRAIM trial has ended</h2>
471
- <p>Your 14-day trial expired on ${expiredAt.toLocaleDateString()}.</p>
472
-
473
- <div class="highlight">
474
- <p><strong>Your data is safe and preserved.</strong></p>
475
- <p>Upgrade now to reactivate your account and continue using FRAIM.</p>
476
- </div>
477
-
478
- <h3>Pricing plans:</h3>
479
- <ul>
480
- <li><strong>Regular:</strong> $200/month or $2,000/year</li>
481
- <li><strong>Founders (90% off):</strong> $20/month or $200/year</li>
482
- </ul>
483
-
484
- <a href="${this.baseUrl}/upgrade" style="display:inline-block;padding:12px 24px;background-color:#10b981;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">Reactivate Your Account</a>
485
-
486
- <div class="footer">
487
- <p>FRAIM - Framework for Rigor-based AI Management</p>
488
- </div>
489
- </div>
490
- </body>
491
- </html>
448
+ html: `
449
+ <!DOCTYPE html>
450
+ <html>
451
+ <head>
452
+ <style>
453
+ body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
454
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
455
+ .button {
456
+ display: inline-block;
457
+ padding: 12px 24px;
458
+ background-color: #10b981;
459
+ color: #ffffff !important;
460
+ text-decoration: none;
461
+ border-radius: 5px;
462
+ margin: 20px 0;
463
+ }
464
+ .highlight { background: #e7f3ff; padding: 20px; border-left: 4px solid #0066cc; margin: 20px 0; }
465
+ .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
466
+ </style>
467
+ </head>
468
+ <body>
469
+ <div class="container">
470
+ <h2>Your FRAIM trial has ended</h2>
471
+ <p>Your 14-day trial expired on ${expiredAt.toLocaleDateString()}.</p>
472
+
473
+ <div class="highlight">
474
+ <p><strong>Your data is safe and preserved.</strong></p>
475
+ <p>Upgrade now to reactivate your account and continue using FRAIM.</p>
476
+ </div>
477
+
478
+ <h3>Pricing plans:</h3>
479
+ <ul>
480
+ <li><strong>Regular:</strong> $200/month or $2,000/year</li>
481
+ <li><strong>Founders (90% off):</strong> $20/month or $200/year</li>
482
+ </ul>
483
+
484
+ <a href="${this.baseUrl}/upgrade" style="display:inline-block;padding:12px 24px;background-color:#10b981;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">Reactivate Your Account</a>
485
+
486
+ <div class="footer">
487
+ <p>FRAIM - Framework for Rigor-based AI Management</p>
488
+ </div>
489
+ </div>
490
+ </body>
491
+ </html>
492
492
  `,
493
493
  text: `Your FRAIM trial has ended\n\nYour 14-day trial expired on ${expiredAt.toLocaleDateString()}.\n\nYour data is safe and preserved. Upgrade now to reactivate your account and continue using FRAIM.\n\nPricing plans:\n- Regular: $200/month or $2,000/year\n- Founders (90% off): $20/month or $200/year\n\nReactivate your account: ${this.baseUrl}/upgrade`
494
494
  };
@@ -500,66 +500,66 @@ class EmailService {
500
500
  const dashboardAccess = this.generateDashboardAccessSection(dashboardUrl, 'Access Your Dashboard');
501
501
  return {
502
502
  subject: '🎉 Welcome to FRAIM Pro!',
503
- html: `
504
- <!DOCTYPE html>
505
- <html>
506
- <head>
507
- <style>
508
- body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
509
- .container { max-width: 600px; margin: 0 auto; padding: 20px; }
510
- .success { background: #d4edda; padding: 20px; border-left: 4px solid #28a745; margin: 20px 0; }
511
- .api-key {
512
- background: #f5f5f5;
513
- padding: 15px;
514
- border-radius: 5px;
515
- font-family: monospace;
516
- word-break: break-all;
517
- margin: 20px 0;
518
- }
519
- .button {
520
- display: inline-block;
521
- padding: 12px 24px;
522
- background-color: #10b981;
523
- color: #ffffff !important;
524
- text-decoration: none;
525
- border-radius: 5px;
526
- margin: 20px 0;
527
- }
528
- .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
529
- </style>
530
- </head>
531
- <body>
532
- <div class="container">
533
- <h2>🎉 Welcome to FRAIM Pro!</h2>
534
-
535
- <div class="success">
536
- <strong>Payment confirmed!</strong><br>
537
- Your subscription is now active.
538
- </div>
539
-
540
- <h3>Subscription Details:</h3>
541
- <ul>
542
- <li><strong>Plan:</strong> ${plan}${founderDiscount ? ' (Founder Discount - 90% off)' : ''}</li>
543
- <li><strong>Amount:</strong> ${displayAmount}/${cycleText}</li>
544
- <li><strong>Next billing date:</strong> ${nextBillingDate.toLocaleDateString()}</li>
545
- </ul>
546
-
547
- <p>${dashboardAccess.lead}</p>
548
- ${dashboardAccess.buttonHtml}
549
-
550
- <p>Need a walkthrough? Watch the onboarding videos on the FRAIM website:</p>
551
- <p><a href="${this.baseUrl}/resources.html#videos">${this.baseUrl}/resources.html#videos</a></p>
552
-
553
- <p>Manage your subscription (update payment method, change plan, etc.):</p>
554
- <a href="${this.baseUrl}/billing">Billing Portal</a>
555
-
556
- <div class="footer">
557
- <p>Questions? Reply to this email.</p>
558
- <p>FRAIM - Framework for Rigor-based AI Management</p>
559
- </div>
560
- </div>
561
- </body>
562
- </html>
503
+ html: `
504
+ <!DOCTYPE html>
505
+ <html>
506
+ <head>
507
+ <style>
508
+ body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
509
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
510
+ .success { background: #d4edda; padding: 20px; border-left: 4px solid #28a745; margin: 20px 0; }
511
+ .api-key {
512
+ background: #f5f5f5;
513
+ padding: 15px;
514
+ border-radius: 5px;
515
+ font-family: monospace;
516
+ word-break: break-all;
517
+ margin: 20px 0;
518
+ }
519
+ .button {
520
+ display: inline-block;
521
+ padding: 12px 24px;
522
+ background-color: #10b981;
523
+ color: #ffffff !important;
524
+ text-decoration: none;
525
+ border-radius: 5px;
526
+ margin: 20px 0;
527
+ }
528
+ .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
529
+ </style>
530
+ </head>
531
+ <body>
532
+ <div class="container">
533
+ <h2>🎉 Welcome to FRAIM Pro!</h2>
534
+
535
+ <div class="success">
536
+ <strong>Payment confirmed!</strong><br>
537
+ Your subscription is now active.
538
+ </div>
539
+
540
+ <h3>Subscription Details:</h3>
541
+ <ul>
542
+ <li><strong>Plan:</strong> ${plan}${founderDiscount ? ' (Founder Discount - 90% off)' : ''}</li>
543
+ <li><strong>Amount:</strong> ${displayAmount}/${cycleText}</li>
544
+ <li><strong>Next billing date:</strong> ${nextBillingDate.toLocaleDateString()}</li>
545
+ </ul>
546
+
547
+ <p>${dashboardAccess.lead}</p>
548
+ ${dashboardAccess.buttonHtml}
549
+
550
+ <p>Need a walkthrough? Watch the onboarding videos on the FRAIM website:</p>
551
+ <p><a href="${this.baseUrl}/resources.html#videos">${this.baseUrl}/resources.html#videos</a></p>
552
+
553
+ <p>Manage your subscription (update payment method, change plan, etc.):</p>
554
+ <a href="${this.baseUrl}/billing">Billing Portal</a>
555
+
556
+ <div class="footer">
557
+ <p>Questions? Reply to this email.</p>
558
+ <p>FRAIM - Framework for Rigor-based AI Management</p>
559
+ </div>
560
+ </div>
561
+ </body>
562
+ </html>
563
563
  `,
564
564
  text: `Welcome to FRAIM Pro!\n\nPayment confirmed! Your subscription is now active.\n\nSubscription Details:\n- Plan: ${plan}${founderDiscount ? ' (Founder Discount - 90% off)' : ''}\n- Amount: ${displayAmount}/${cycleText}\n- Next billing date: ${nextBillingDate.toLocaleDateString()}\n\n${dashboardAccess.lead}\n${dashboardAccess.buttonText}\nWatch onboarding videos: ${this.baseUrl}/resources.html#videos\n\nManage subscription: ${this.baseUrl}/billing`
565
565
  };
@@ -576,38 +576,38 @@ class EmailService {
576
576
  const formattedAmount = (amount / 100).toFixed(2);
577
577
  return {
578
578
  subject: `Receipt for FRAIM Pro - ${formattedAmount}`,
579
- html: `
580
- <!DOCTYPE html>
581
- <html>
582
- <head>
583
- <style>
584
- body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
585
- .container { max-width: 600px; margin: 0 auto; padding: 20px; }
586
- .receipt { background: #f8f9fa; padding: 20px; border-radius: 5px; margin: 20px 0; }
587
- .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
588
- </style>
589
- </head>
590
- <body>
591
- <div class="container">
592
- <h2>Payment Receipt</h2>
593
- <p>Thank you for your continued subscription to FRAIM Pro!</p>
594
-
595
- <div class="receipt">
596
- <h3>Receipt Details:</h3>
597
- <p><strong>Amount charged:</strong> ${formattedAmount}</p>
598
- <p><strong>Next billing date:</strong> ${nextBillingDate.toLocaleDateString()}</p>
599
- ${invoiceUrl ? `<p><a href="${invoiceUrl}">Download Invoice</a></p>` : ''}
600
- </div>
601
-
602
- <p>Your subscription remains active with no changes.</p>
603
-
604
- <div class="footer">
605
- <p>Manage your subscription: <a href="${this.baseUrl}/billing">Billing Portal</a></p>
606
- <p>FRAIM - Framework for Rigor-based AI Management</p>
607
- </div>
608
- </div>
609
- </body>
610
- </html>
579
+ html: `
580
+ <!DOCTYPE html>
581
+ <html>
582
+ <head>
583
+ <style>
584
+ body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
585
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
586
+ .receipt { background: #f8f9fa; padding: 20px; border-radius: 5px; margin: 20px 0; }
587
+ .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
588
+ </style>
589
+ </head>
590
+ <body>
591
+ <div class="container">
592
+ <h2>Payment Receipt</h2>
593
+ <p>Thank you for your continued subscription to FRAIM Pro!</p>
594
+
595
+ <div class="receipt">
596
+ <h3>Receipt Details:</h3>
597
+ <p><strong>Amount charged:</strong> ${formattedAmount}</p>
598
+ <p><strong>Next billing date:</strong> ${nextBillingDate.toLocaleDateString()}</p>
599
+ ${invoiceUrl ? `<p><a href="${invoiceUrl}">Download Invoice</a></p>` : ''}
600
+ </div>
601
+
602
+ <p>Your subscription remains active with no changes.</p>
603
+
604
+ <div class="footer">
605
+ <p>Manage your subscription: <a href="${this.baseUrl}/billing">Billing Portal</a></p>
606
+ <p>FRAIM - Framework for Rigor-based AI Management</p>
607
+ </div>
608
+ </div>
609
+ </body>
610
+ </html>
611
611
  `,
612
612
  text: `Payment Receipt\n\nThank you for your continued subscription to FRAIM Pro!\n\nReceipt Details:\n- Amount charged: ${formattedAmount}\n- Next billing date: ${nextBillingDate.toLocaleDateString()}\n${invoiceUrl ? `- Invoice: ${invoiceUrl}\n` : ''}\nYour subscription remains active with no changes.\n\nManage subscription: ${this.baseUrl}/billing`
613
613
  };
@@ -616,58 +616,58 @@ class EmailService {
616
616
  const daysRemaining = Math.ceil((gracePeriodEndsAt.getTime() - Date.now()) / (1000 * 60 * 60 * 24));
617
617
  return {
618
618
  subject: '🚨 FRAIM: Payment Failed - Action Required',
619
- html: `
620
- <!DOCTYPE html>
621
- <html>
622
- <head>
623
- <style>
624
- body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
625
- .container { max-width: 600px; margin: 0 auto; padding: 20px; }
626
- .alert { background: #f8d7da; padding: 20px; border-left: 4px solid #dc3545; margin: 20px 0; }
627
- .button {
628
- display: inline-block;
629
- padding: 12px 24px;
630
- background-color: #dc3545;
631
- color: #ffffff !important;
632
- text-decoration: none;
633
- border-radius: 5px;
634
- margin: 20px 0;
635
- }
636
- .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
637
- </style>
638
- </head>
639
- <body>
640
- <div class="container">
641
- <h2>⚠️ Payment Failed</h2>
642
-
643
- <div class="alert">
644
- <strong>Your FRAIM subscription payment was declined.</strong><br>
645
- Your access has been suspended.
646
- </div>
647
-
648
- <p><strong>What this means:</strong></p>
649
- <ul>
650
- <li>Your API key has been suspended and won't work</li>
651
- <li>You have ${daysRemaining} days to update your payment method</li>
652
- <li>After ${gracePeriodEndsAt.toLocaleDateString()}, your subscription will be cancelled</li>
653
- </ul>
654
-
655
- <p><strong>To restore access:</strong></p>
656
- <ol>
657
- <li>Click the button below to update your payment method</li>
658
- <li>Your subscription will be automatically renewed</li>
659
- <li>Your API key will be reactivated immediately</li>
660
- </ol>
661
-
662
- <a href="${billingPortalUrl}" style="display:inline-block;padding:12px 24px;background-color:#dc3545;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">Update Payment Method</a>
663
-
664
- <div class="footer">
665
- <p>Need help? Reply to this email.</p>
666
- <p>FRAIM - Framework for Rigor-based AI Management</p>
667
- </div>
668
- </div>
669
- </body>
670
- </html>
619
+ html: `
620
+ <!DOCTYPE html>
621
+ <html>
622
+ <head>
623
+ <style>
624
+ body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
625
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
626
+ .alert { background: #f8d7da; padding: 20px; border-left: 4px solid #dc3545; margin: 20px 0; }
627
+ .button {
628
+ display: inline-block;
629
+ padding: 12px 24px;
630
+ background-color: #dc3545;
631
+ color: #ffffff !important;
632
+ text-decoration: none;
633
+ border-radius: 5px;
634
+ margin: 20px 0;
635
+ }
636
+ .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
637
+ </style>
638
+ </head>
639
+ <body>
640
+ <div class="container">
641
+ <h2>⚠️ Payment Failed</h2>
642
+
643
+ <div class="alert">
644
+ <strong>Your FRAIM subscription payment was declined.</strong><br>
645
+ Your access has been suspended.
646
+ </div>
647
+
648
+ <p><strong>What this means:</strong></p>
649
+ <ul>
650
+ <li>Your API key has been suspended and won't work</li>
651
+ <li>You have ${daysRemaining} days to update your payment method</li>
652
+ <li>After ${gracePeriodEndsAt.toLocaleDateString()}, your subscription will be cancelled</li>
653
+ </ul>
654
+
655
+ <p><strong>To restore access:</strong></p>
656
+ <ol>
657
+ <li>Click the button below to update your payment method</li>
658
+ <li>Your subscription will be automatically renewed</li>
659
+ <li>Your API key will be reactivated immediately</li>
660
+ </ol>
661
+
662
+ <a href="${billingPortalUrl}" style="display:inline-block;padding:12px 24px;background-color:#dc3545;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">Update Payment Method</a>
663
+
664
+ <div class="footer">
665
+ <p>Need help? Reply to this email.</p>
666
+ <p>FRAIM - Framework for Rigor-based AI Management</p>
667
+ </div>
668
+ </div>
669
+ </body>
670
+ </html>
671
671
  `,
672
672
  text: `⚠️ Payment Failed\n\nYour FRAIM subscription payment was declined. Your access has been suspended.\n\nWhat this means:\n- Your API key has been suspended and won't work\n- You have ${daysRemaining} days to update your payment method\n- After ${gracePeriodEndsAt.toLocaleDateString()}, your subscription will be cancelled\n\nTo restore access:\n1. Update your payment method: ${billingPortalUrl}\n2. Your subscription will be automatically renewed\n3. Your API key will be reactivated immediately\n\nNeed help? Reply to this email.`
673
673
  };
@@ -675,46 +675,46 @@ class EmailService {
675
675
  generatePaymentRestoredTemplate(nextBillingDate) {
676
676
  return {
677
677
  subject: '✅ Payment successful - FRAIM access restored',
678
- html: `
679
- <!DOCTYPE html>
680
- <html>
681
- <head>
682
- <style>
683
- body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
684
- .container { max-width: 600px; margin: 0 auto; padding: 20px; }
685
- .success { background: #d4edda; padding: 20px; border-left: 4px solid #28a745; margin: 20px 0; }
686
- .button {
687
- display: inline-block;
688
- padding: 12px 24px;
689
- background-color: #10b981;
690
- color: #ffffff !important;
691
- text-decoration: none;
692
- border-radius: 5px;
693
- margin: 20px 0;
694
- }
695
- .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
696
- </style>
697
- </head>
698
- <body>
699
- <div class="container">
700
- <h2>✅ Access Restored!</h2>
701
-
702
- <div class="success">
703
- <strong>Payment successful!</strong><br>
704
- Your FRAIM subscription has been renewed.
705
- </div>
706
-
707
- <p>Your API key is now active again and you can continue using FRAIM.</p>
708
- <p><strong>Next billing date:</strong> ${nextBillingDate.toLocaleDateString()}</p>
709
-
710
- <a href="${this.baseUrl}/dashboard" style="display:inline-block;padding:12px 24px;background-color:#10b981;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">Continue Using FRAIM</a>
711
-
712
- <div class="footer">
713
- <p>FRAIM - Framework for Rigor-based AI Management</p>
714
- </div>
715
- </div>
716
- </body>
717
- </html>
678
+ html: `
679
+ <!DOCTYPE html>
680
+ <html>
681
+ <head>
682
+ <style>
683
+ body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
684
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
685
+ .success { background: #d4edda; padding: 20px; border-left: 4px solid #28a745; margin: 20px 0; }
686
+ .button {
687
+ display: inline-block;
688
+ padding: 12px 24px;
689
+ background-color: #10b981;
690
+ color: #ffffff !important;
691
+ text-decoration: none;
692
+ border-radius: 5px;
693
+ margin: 20px 0;
694
+ }
695
+ .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
696
+ </style>
697
+ </head>
698
+ <body>
699
+ <div class="container">
700
+ <h2>✅ Access Restored!</h2>
701
+
702
+ <div class="success">
703
+ <strong>Payment successful!</strong><br>
704
+ Your FRAIM subscription has been renewed.
705
+ </div>
706
+
707
+ <p>Your API key is now active again and you can continue using FRAIM.</p>
708
+ <p><strong>Next billing date:</strong> ${nextBillingDate.toLocaleDateString()}</p>
709
+
710
+ <a href="${this.baseUrl}/dashboard" style="display:inline-block;padding:12px 24px;background-color:#10b981;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">Continue Using FRAIM</a>
711
+
712
+ <div class="footer">
713
+ <p>FRAIM - Framework for Rigor-based AI Management</p>
714
+ </div>
715
+ </div>
716
+ </body>
717
+ </html>
718
718
  `,
719
719
  text: `✅ Access Restored!\n\nPayment successful! Your FRAIM subscription has been renewed.\n\nYour API key is now active again and you can continue using FRAIM.\n\nNext billing date: ${nextBillingDate.toLocaleDateString()}\n\nContinue using FRAIM: ${this.baseUrl}/dashboard`
720
720
  };
@@ -722,53 +722,53 @@ class EmailService {
722
722
  generateSubscriptionCancelledTemplate(endsAt) {
723
723
  return {
724
724
  subject: 'FRAIM subscription cancelled',
725
- html: `
726
- <!DOCTYPE html>
727
- <html>
728
- <head>
729
- <style>
730
- body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
731
- .container { max-width: 600px; margin: 0 auto; padding: 20px; }
732
- .info { background: #fff3cd; padding: 20px; border-left: 4px solid #ffc107; margin: 20px 0; }
733
- .button {
734
- display: inline-block;
735
- padding: 12px 24px;
736
- background-color: #10b981;
737
- color: #ffffff !important;
738
- text-decoration: none;
739
- border-radius: 5px;
740
- margin: 20px 0;
741
- }
742
- .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
743
- </style>
744
- </head>
745
- <body>
746
- <div class="container">
747
- <h2>Subscription Cancelled</h2>
748
-
749
- <div class="info">
750
- <p><strong>Your subscription has been cancelled.</strong></p>
751
- <p>Your access remains active until: ${endsAt.toLocaleDateString()}</p>
752
- </div>
753
-
754
- <p>After this date:</p>
755
- <ul>
756
- <li>Your API key will stop working</li>
757
- <li>You won't be able to run workflows</li>
758
- <li>Your data will be preserved for 30 days</li>
759
- </ul>
760
-
761
- <p><strong>Changed your mind?</strong> You can reactivate your subscription anytime before ${endsAt.toLocaleDateString()}.</p>
762
-
763
- <a href="${this.baseUrl}/billing" style="display:inline-block;padding:12px 24px;background-color:#10b981;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">Reactivate Subscription</a>
764
-
765
- <div class="footer">
766
- <p>We're sorry to see you go. Reply to this email to let us know how we can improve.</p>
767
- <p>FRAIM - Framework for Rigor-based AI Management</p>
768
- </div>
769
- </div>
770
- </body>
771
- </html>
725
+ html: `
726
+ <!DOCTYPE html>
727
+ <html>
728
+ <head>
729
+ <style>
730
+ body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
731
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
732
+ .info { background: #fff3cd; padding: 20px; border-left: 4px solid #ffc107; margin: 20px 0; }
733
+ .button {
734
+ display: inline-block;
735
+ padding: 12px 24px;
736
+ background-color: #10b981;
737
+ color: #ffffff !important;
738
+ text-decoration: none;
739
+ border-radius: 5px;
740
+ margin: 20px 0;
741
+ }
742
+ .footer { font-size: 12px; color: #666; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; }
743
+ </style>
744
+ </head>
745
+ <body>
746
+ <div class="container">
747
+ <h2>Subscription Cancelled</h2>
748
+
749
+ <div class="info">
750
+ <p><strong>Your subscription has been cancelled.</strong></p>
751
+ <p>Your access remains active until: ${endsAt.toLocaleDateString()}</p>
752
+ </div>
753
+
754
+ <p>After this date:</p>
755
+ <ul>
756
+ <li>Your API key will stop working</li>
757
+ <li>You won't be able to run workflows</li>
758
+ <li>Your data will be preserved for 30 days</li>
759
+ </ul>
760
+
761
+ <p><strong>Changed your mind?</strong> You can reactivate your subscription anytime before ${endsAt.toLocaleDateString()}.</p>
762
+
763
+ <a href="${this.baseUrl}/billing" style="display:inline-block;padding:12px 24px;background-color:#10b981;color:#ffffff !important;text-decoration:none;border-radius:5px;margin:20px 0;font-weight:bold">Reactivate Subscription</a>
764
+
765
+ <div class="footer">
766
+ <p>We're sorry to see you go. Reply to this email to let us know how we can improve.</p>
767
+ <p>FRAIM - Framework for Rigor-based AI Management</p>
768
+ </div>
769
+ </div>
770
+ </body>
771
+ </html>
772
772
  `,
773
773
  text: `Subscription Cancelled\n\nYour subscription has been cancelled.\n\nYour access remains active until: ${endsAt.toLocaleDateString()}\n\nAfter this date:\n- Your API key will stop working\n- You won't be able to run workflows\n- Your data will be preserved for 30 days\n\nChanged your mind? You can reactivate your subscription anytime before ${endsAt.toLocaleDateString()}.\n\nReactivate: ${this.baseUrl}/billing\n\nWe're sorry to see you go. Reply to this email to let us know how we can improve.`
774
774
  };
@@ -777,177 +777,177 @@ class EmailService {
777
777
  const improvementsList = improvements.map(item => `• ${item}`).join('\n');
778
778
  return {
779
779
  subject: `Thank you for making FRAIM better! 🎉`,
780
- html: `
781
- <div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
782
- <div style="text-align: center; margin-bottom: 30px;">
783
- <h1 style="color: #2563eb; margin: 0;">Thank you for making FRAIM better!</h1>
784
- </div>
785
-
786
- <p style="font-size: 16px; line-height: 1.6; color: #374151;">Hi ${customerName},</p>
787
-
788
- <p style="font-size: 16px; line-height: 1.6; color: #374151;">
789
- I wanted to personally thank you for reporting the issue: <strong>"${issueTitle}"</strong>
790
- </p>
791
-
792
- <p style="font-size: 16px; line-height: 1.6; color: #374151;">
793
- Your feedback has been implemented and FRAIM is now better because of you! Here's what we improved:
794
- </p>
795
-
796
- <div style="background-color: #f3f4f6; padding: 20px; border-radius: 8px; margin: 20px 0;">
797
- <pre style="font-family: inherit; white-space: pre-wrap; margin: 0; color: #374151;">${improvementsList}</pre>
798
- </div>
799
-
800
- <p style="font-size: 16px; line-height: 1.6; color: #374151;">
801
- Your input helps us build a better AI development framework for everyone. Please keep the feedback coming!
802
- </p>
803
-
804
- <div style="text-align: center; margin: 30px 0;">
805
- <a href="https://github.com/mathursrus/FRAIM/issues/new"
806
- style="background-color: #2563eb; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; display: inline-block;">
807
- Report Another Issue
808
- </a>
809
- </div>
810
-
811
- <p style="font-size: 14px; color: #6b7280; text-align: center; margin-top: 30px;">
812
- Thank you for being part of the FRAIM community!<br>
813
- — Sid Mathur, FRAIM Creator
814
- </p>
815
- </div>
780
+ html: `
781
+ <div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
782
+ <div style="text-align: center; margin-bottom: 30px;">
783
+ <h1 style="color: #2563eb; margin: 0;">Thank you for making FRAIM better!</h1>
784
+ </div>
785
+
786
+ <p style="font-size: 16px; line-height: 1.6; color: #374151;">Hi ${customerName},</p>
787
+
788
+ <p style="font-size: 16px; line-height: 1.6; color: #374151;">
789
+ I wanted to personally thank you for reporting the issue: <strong>"${issueTitle}"</strong>
790
+ </p>
791
+
792
+ <p style="font-size: 16px; line-height: 1.6; color: #374151;">
793
+ Your feedback has been implemented and FRAIM is now better because of you! Here's what we improved:
794
+ </p>
795
+
796
+ <div style="background-color: #f3f4f6; padding: 20px; border-radius: 8px; margin: 20px 0;">
797
+ <pre style="font-family: inherit; white-space: pre-wrap; margin: 0; color: #374151;">${improvementsList}</pre>
798
+ </div>
799
+
800
+ <p style="font-size: 16px; line-height: 1.6; color: #374151;">
801
+ Your input helps us build a better AI development framework for everyone. Please keep the feedback coming!
802
+ </p>
803
+
804
+ <div style="text-align: center; margin: 30px 0;">
805
+ <a href="https://github.com/mathursrus/FRAIM/issues/new"
806
+ style="background-color: #2563eb; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; display: inline-block;">
807
+ Report Another Issue
808
+ </a>
809
+ </div>
810
+
811
+ <p style="font-size: 14px; color: #6b7280; text-align: center; margin-top: 30px;">
812
+ Thank you for being part of the FRAIM community!<br>
813
+ — Sid Mathur, FRAIM Creator
814
+ </p>
815
+ </div>
816
816
  `,
817
- text: `Hi ${customerName},
818
-
819
- Thank you for making FRAIM better!
820
-
821
- I wanted to personally thank you for reporting the issue: "${issueTitle}"
822
-
823
- Your feedback has been implemented and FRAIM is now better because of you! Here's what we improved:
824
-
825
- ${improvementsList}
826
-
827
- Your input helps us build a better AI development framework for everyone. Please keep the feedback coming!
828
-
829
- Report another issue: https://github.com/mathursrus/FRAIM/issues/new
830
-
831
- Thank you for being part of the FRAIM community!
817
+ text: `Hi ${customerName},
818
+
819
+ Thank you for making FRAIM better!
820
+
821
+ I wanted to personally thank you for reporting the issue: "${issueTitle}"
822
+
823
+ Your feedback has been implemented and FRAIM is now better because of you! Here's what we improved:
824
+
825
+ ${improvementsList}
826
+
827
+ Your input helps us build a better AI development framework for everyone. Please keep the feedback coming!
828
+
829
+ Report another issue: https://github.com/mathursrus/FRAIM/issues/new
830
+
831
+ Thank you for being part of the FRAIM community!
832
832
  — Sid Mathur, FRAIM Creator`
833
833
  };
834
834
  }
835
835
  generateNewsletterTemplate(recipientName, features, bugFixes, weekRange) {
836
- const featuresHtml = features.length > 0 ? features.map(f => `
837
- <tr>
838
- <td style="padding: 16px 18px; background-color: #f0f7ff; border-radius: 8px; border-left: 4px solid #4A90E2;">
839
- <strong style="color: #1e3a5f; font-size: 15px;">${f.title}</strong>
840
- <p style="margin: 6px 0 0 0; color: #4a5568; font-size: 14px; line-height: 1.6;">${f.description}</p>
841
- </td>
842
- </tr>
843
- <tr><td style="height: 10px;"></td></tr>
836
+ const featuresHtml = features.length > 0 ? features.map(f => `
837
+ <tr>
838
+ <td style="padding: 16px 18px; background-color: #f0f7ff; border-radius: 8px; border-left: 4px solid #4A90E2;">
839
+ <strong style="color: #1e3a5f; font-size: 15px;">${f.title}</strong>
840
+ <p style="margin: 6px 0 0 0; color: #4a5568; font-size: 14px; line-height: 1.6;">${f.description}</p>
841
+ </td>
842
+ </tr>
843
+ <tr><td style="height: 10px;"></td></tr>
844
844
  `).join('') : '<tr><td style="color: #94a3b8; font-size: 14px; padding: 8px 0;">No new features this week.</td></tr>';
845
- const bugFixesHtml = bugFixes.length > 0 ? bugFixes.map(b => `
846
- <tr>
847
- <td style="padding: 14px 18px; background-color: #fff8f0; border-radius: 8px; border-left: 4px solid #e08a2e;">
848
- <strong style="color: #7c4a03; font-size: 15px;">${b.title}</strong>
849
- <p style="margin: 5px 0 0 0; color: #4a5568; font-size: 14px; line-height: 1.5;">${b.description}</p>
850
- </td>
851
- </tr>
852
- <tr><td style="height: 10px;"></td></tr>
845
+ const bugFixesHtml = bugFixes.length > 0 ? bugFixes.map(b => `
846
+ <tr>
847
+ <td style="padding: 14px 18px; background-color: #fff8f0; border-radius: 8px; border-left: 4px solid #e08a2e;">
848
+ <strong style="color: #7c4a03; font-size: 15px;">${b.title}</strong>
849
+ <p style="margin: 5px 0 0 0; color: #4a5568; font-size: 14px; line-height: 1.5;">${b.description}</p>
850
+ </td>
851
+ </tr>
852
+ <tr><td style="height: 10px;"></td></tr>
853
853
  `).join('') : '<tr><td style="color: #94a3b8; font-size: 14px; padding: 8px 0;">No bug fixes this week.</td></tr>';
854
854
  return {
855
855
  subject: `FRAIM Weekly Update - ${weekRange} 🚀`,
856
- html: `
857
- <!DOCTYPE html>
858
- <html lang="en">
859
- <head>
860
- <meta charset="UTF-8">
861
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
862
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
863
- <title>FRAIM Weekly Update - ${weekRange}</title>
864
- <style>
865
- body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; font-size: 14px; line-height: 1.6; color: #333; background-color: #f1f5f9; }
866
- .email-container { max-width: 600px; margin: 0 auto; background-color: #ffffff; }
867
- .header { background-color: #4A90E2; color: #ffffff; padding: 30px 40px; text-align: center; }
868
- .header h1 { margin: 0 0 8px 0; font-size: 24px; font-weight: 700; }
869
- .header p { margin: 0; font-size: 15px; opacity: 0.9; }
870
- .greeting { padding: 28px 40px 20px 40px; }
871
- .greeting p { margin: 0 0 10px 0; font-size: 15px; color: #334155; line-height: 1.7; }
872
- .section-header { background-color: #2C3E50; color: #ffffff; padding: 12px 40px; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; }
873
- .section-content { padding: 20px 40px; border-bottom: 1px solid #e2e8f0; }
874
- .footer { padding: 24px 40px; text-align: center; background-color: #f8fafc; border-top: 1px solid #e2e8f0; }
875
- .footer-btn { display: inline-block; margin: 0 5px 8px 5px; padding: 11px 22px; background-color: #4A90E2; color: #ffffff !important; text-decoration: none; border-radius: 5px; font-weight: 600; font-size: 14px; }
876
- .footer-btn.secondary { background-color: #2C3E50; }
877
- @media only screen and (max-width: 600px) {
878
- .email-container { width: 100% !important; }
879
- .header, .greeting, .section-header, .section-content, .footer { padding-left: 20px !important; padding-right: 20px !important; }
880
- .footer-btn { display: block; margin: 8px 0; }
881
- }
882
- </style>
883
- </head>
884
- <body>
885
- <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
886
- <tr>
887
- <td align="center" style="padding: 30px 20px;">
888
- <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="600" class="email-container" style="max-width: 600px; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.08);">
889
-
890
- <!-- Header -->
891
- <tr><td class="header">
892
- <h1>FRAIM Weekly Update</h1>
893
- <p>${weekRange}</p>
894
- </td></tr>
895
-
896
- <!-- Greeting -->
897
- <tr><td class="greeting">
898
- <p>Hi ${recipientName},</p>
899
- <p>Here's what's new in FRAIM this week — we've been working hard to make your AI development experience even better.</p>
900
- </td></tr>
901
-
902
- <!-- New Features Section -->
903
- <tr><td class="section-header">🎉 NEW FEATURES</td></tr>
904
- <tr><td class="section-content">
905
- <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
906
- ${featuresHtml}
907
- </table>
908
- </td></tr>
909
-
910
- <!-- Bug Fixes Section -->
911
- <tr><td class="section-header">🐛 BUG FIXES</td></tr>
912
- <tr><td class="section-content">
913
- <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
914
- ${bugFixesHtml}
915
- </table>
916
- </td></tr>
917
-
918
- <!-- Footer -->
919
- <tr><td class="footer">
920
- <p style="margin: 0 0 14px 0; font-weight: 600; color: #1e293b; font-size: 14px;">Want to explore or contribute?</p>
921
- <a href="https://github.com/mathursrus/FRAIM" class="footer-btn">View on GitHub</a>
922
- <a href="https://github.com/mathursrus/FRAIM/issues/new" class="footer-btn secondary">Report an Issue</a>
923
- <p style="margin: 14px 0 0 0; font-size: 12px; color: #94a3b8;">────────────────────────</p>
924
- <p style="margin: 5px 0 0 0; font-size: 12px; font-weight: 600; color: #64748b;">FRAIM — Framework for Rigor-based AI Management</p>
925
- </td></tr>
926
-
927
- </table>
928
- </td>
929
- </tr>
930
- </table>
931
- </body>
932
- </html>
856
+ html: `
857
+ <!DOCTYPE html>
858
+ <html lang="en">
859
+ <head>
860
+ <meta charset="UTF-8">
861
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
862
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
863
+ <title>FRAIM Weekly Update - ${weekRange}</title>
864
+ <style>
865
+ body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; font-size: 14px; line-height: 1.6; color: #333; background-color: #f1f5f9; }
866
+ .email-container { max-width: 600px; margin: 0 auto; background-color: #ffffff; }
867
+ .header { background-color: #4A90E2; color: #ffffff; padding: 30px 40px; text-align: center; }
868
+ .header h1 { margin: 0 0 8px 0; font-size: 24px; font-weight: 700; }
869
+ .header p { margin: 0; font-size: 15px; opacity: 0.9; }
870
+ .greeting { padding: 28px 40px 20px 40px; }
871
+ .greeting p { margin: 0 0 10px 0; font-size: 15px; color: #334155; line-height: 1.7; }
872
+ .section-header { background-color: #2C3E50; color: #ffffff; padding: 12px 40px; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; }
873
+ .section-content { padding: 20px 40px; border-bottom: 1px solid #e2e8f0; }
874
+ .footer { padding: 24px 40px; text-align: center; background-color: #f8fafc; border-top: 1px solid #e2e8f0; }
875
+ .footer-btn { display: inline-block; margin: 0 5px 8px 5px; padding: 11px 22px; background-color: #4A90E2; color: #ffffff !important; text-decoration: none; border-radius: 5px; font-weight: 600; font-size: 14px; }
876
+ .footer-btn.secondary { background-color: #2C3E50; }
877
+ @media only screen and (max-width: 600px) {
878
+ .email-container { width: 100% !important; }
879
+ .header, .greeting, .section-header, .section-content, .footer { padding-left: 20px !important; padding-right: 20px !important; }
880
+ .footer-btn { display: block; margin: 8px 0; }
881
+ }
882
+ </style>
883
+ </head>
884
+ <body>
885
+ <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
886
+ <tr>
887
+ <td align="center" style="padding: 30px 20px;">
888
+ <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="600" class="email-container" style="max-width: 600px; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.08);">
889
+
890
+ <!-- Header -->
891
+ <tr><td class="header">
892
+ <h1>FRAIM Weekly Update</h1>
893
+ <p>${weekRange}</p>
894
+ </td></tr>
895
+
896
+ <!-- Greeting -->
897
+ <tr><td class="greeting">
898
+ <p>Hi ${recipientName},</p>
899
+ <p>Here's what's new in FRAIM this week — we've been working hard to make your AI development experience even better.</p>
900
+ </td></tr>
901
+
902
+ <!-- New Features Section -->
903
+ <tr><td class="section-header">🎉 NEW FEATURES</td></tr>
904
+ <tr><td class="section-content">
905
+ <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
906
+ ${featuresHtml}
907
+ </table>
908
+ </td></tr>
909
+
910
+ <!-- Bug Fixes Section -->
911
+ <tr><td class="section-header">🐛 BUG FIXES</td></tr>
912
+ <tr><td class="section-content">
913
+ <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
914
+ ${bugFixesHtml}
915
+ </table>
916
+ </td></tr>
917
+
918
+ <!-- Footer -->
919
+ <tr><td class="footer">
920
+ <p style="margin: 0 0 14px 0; font-weight: 600; color: #1e293b; font-size: 14px;">Want to explore or contribute?</p>
921
+ <a href="https://github.com/mathursrus/FRAIM" class="footer-btn">View on GitHub</a>
922
+ <a href="https://github.com/mathursrus/FRAIM/issues/new" class="footer-btn secondary">Report an Issue</a>
923
+ <p style="margin: 14px 0 0 0; font-size: 12px; color: #94a3b8;">────────────────────────</p>
924
+ <p style="margin: 5px 0 0 0; font-size: 12px; font-weight: 600; color: #64748b;">FRAIM — Framework for Rigor-based AI Management</p>
925
+ </td></tr>
926
+
927
+ </table>
928
+ </td>
929
+ </tr>
930
+ </table>
931
+ </body>
932
+ </html>
933
933
  `,
934
- text: `FRAIM Weekly Update - ${weekRange}
935
-
936
- Hi ${recipientName},
937
-
938
- Here's what's new in FRAIM this week!
939
-
940
- NEW FEATURES:
941
- ${features.length > 0 ? features.map(f => `• ${f.title}: ${f.description}`).join('\n') : '• No new features this week.'}
942
-
943
- BUG FIXES:
944
- ${bugFixes.length > 0 ? bugFixes.map(b => `• ${b.title}: ${b.description}`).join('\n') : '• No bug fixes this week.'}
945
-
946
- ────────────────────────
947
-
948
- View on GitHub: https://github.com/mathursrus/FRAIM
949
- Report an Issue: https://github.com/mathursrus/FRAIM/issues/new
950
-
934
+ text: `FRAIM Weekly Update - ${weekRange}
935
+
936
+ Hi ${recipientName},
937
+
938
+ Here's what's new in FRAIM this week!
939
+
940
+ NEW FEATURES:
941
+ ${features.length > 0 ? features.map(f => `• ${f.title}: ${f.description}`).join('\n') : '• No new features this week.'}
942
+
943
+ BUG FIXES:
944
+ ${bugFixes.length > 0 ? bugFixes.map(b => `• ${b.title}: ${b.description}`).join('\n') : '• No bug fixes this week.'}
945
+
946
+ ────────────────────────
947
+
948
+ View on GitHub: https://github.com/mathursrus/FRAIM
949
+ Report an Issue: https://github.com/mathursrus/FRAIM/issues/new
950
+
951
951
  FRAIM — Framework for Rigor-based AI Management`
952
952
  };
953
953
  }