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.
- package/README.md +467 -467
- package/bin/fraim.js +12 -12
- package/dist/src/cli/mcp/fraim-mcp-latest-launcher.js +267 -182
- package/dist/src/cli/mcp/mcp-server-registry.js +11 -3
- package/dist/src/cli/setup/ide-invocation-surfaces.js +64 -64
- package/dist/src/cli/utils/agent-adapters.js +61 -61
- package/dist/src/core/handoff-contracts.js +39 -39
- package/dist/src/core/utils/stub-generator.js +53 -53
- package/dist/src/core/utils/windows-shim-path-search.js +56 -0
- package/dist/src/first-run/server.js +5 -1
- package/dist/src/first-run/session-service.js +48 -12
- package/dist/src/fraim/issues.js +4 -4
- package/dist/src/mcp/tool-schemas.js +40 -40
- package/dist/src/middleware/telemetry.js +21 -21
- package/dist/src/services/email-service.js +623 -623
- package/dist/src/services/installer-service.js +22 -22
- package/index.js +83 -83
- package/package.json +59 -59
- package/public/first-run/error-frame.js +100 -100
- package/public/first-run/index.html +35 -35
- package/public/first-run/script.js +747 -742
- package/public/first-run/styles.css +929 -929
- package/dist/src/cli/commands/learning-usage.js +0 -412
- package/dist/src/cli/commands/test-mcp.js +0 -171
- package/dist/src/cli/setup/first-run.js +0 -242
- package/dist/src/core/config-writer.js +0 -75
- package/dist/src/core/utils/job-aliases.js +0 -47
- package/dist/src/core/utils/workflow-parser.js +0 -174
- package/dist/src/services/email-service-clean.js +0 -782
|
@@ -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
|
}
|