Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions apps/website/emails/email-wrapper.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
/**
* Shared HTML wrapper for all email templates.
* Gradient header band with logo, white body, footer.
*
* Brand pass: drops the pastel gradient header band (legacy aesthetic) for
* a clean white card with hairline borders, matching the Statusbrew-inspired
* marketing surface. Inline-only styles for cross-client compatibility.
*/
export function wrapEmail(opts: {
body: string;
showUnsubscribe?: boolean;
}): string {
return `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head>
<body style="font-family:Inter,Arial,sans-serif;background-color:#e8eaf0;padding:40px 0;margin:0">
<div style="max-width:520px;margin:0 auto;border-radius:12px;overflow:hidden;box-shadow:0 2px 12px rgba(0,0,0,0.08)">
<div style="background:linear-gradient(135deg, #fef0f3 0%, #f4f0ff 45%, #eaf3ff 70%, #e6f4ff 100%);padding:28px 32px 20px;border-bottom:1px solid rgba(0,64,144,0.1)">
<div style="font-size:13px;font-weight:700;color:#1a1a2e;letter-spacing:-0.01em">🛩️ Angular Agent Framework</div>
<body style="font-family:Inter,Arial,sans-serif;background-color:#f4f6fb;padding:40px 16px;margin:0">
<div style="max-width:520px;margin:0 auto;background:#ffffff;border:1px solid #e6e8ee;border-radius:14px;overflow:hidden">
<div style="padding:20px 32px;border-bottom:1px solid #e6e8ee">
<div style="font-size:14px;font-weight:700;color:#1a1a2e;letter-spacing:-0.01em">🛩️ Angular Agent Framework</div>
</div>
<div style="background:#fff;padding:28px 32px 32px">
<div style="padding:32px">
${opts.body}
<div style="border-top:1px solid #e4e4e7;margin-top:28px;padding-top:16px">
<p style="font-size:11px;color:#a1a1aa;line-height:1.5;margin:0">Angular Agent Framework — Signal-native streaming for LangGraph.</p>
${opts.showUnsubscribe ? '<p style="font-size:10px;color:#d4d4d8;margin:6px 0 0"><a href="https://cacheplane.ai/api/unsubscribe?email=RECIPIENT" style="color:#d4d4d8;text-decoration:underline">Unsubscribe</a></p>' : ''}
<div style="border-top:1px solid #e6e8ee;margin-top:28px;padding-top:16px">
<p style="font-size:11px;color:#8b8fa3;line-height:1.5;margin:0">Angular Agent Framework — Signal-native streaming for LangGraph.</p>
${opts.showUnsubscribe ? '<p style="font-size:10px;color:#8b8fa3;margin:6px 0 0"><a href="https://cacheplane.ai/api/unsubscribe?email=RECIPIENT" style="color:#8b8fa3;text-decoration:underline">Unsubscribe</a></p>' : ''}
</div>
</div>
</div>
Expand Down
6 changes: 3 additions & 3 deletions apps/website/emails/lead-notification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ export function leadNotificationHtml({ name, email, company, message, ts }: Lead
<p style="font-size:11px;font-family:monospace;text-transform:uppercase;letter-spacing:0.08em;color:#DD0031;font-weight:700;margin:0 0 8px">New Lead</p>
<p style="font-size:20px;font-weight:700;color:#1a1a2e;margin:0 0 4px">${esc(name)}</p>
<p style="font-size:14px;color:#8b8fa3;margin:0 0 16px">${esc(email)}${company ? ` — ${esc(company)}` : ''}</p>
${message ? `<div style="border-top:1px solid #e4e4e7;padding-top:14px;margin-bottom:4px"><p style="font-size:14px;color:#555770;line-height:1.7;margin:0">${esc(message)}</p></div>` : ''}
<div style="border-top:1px solid #e4e4e7;padding-top:14px;margin-top:14px">
<p style="font-size:11px;color:#a1a1aa;margin:0">Received ${esc(ts)}</p>
${message ? `<div style="border-top:1px solid #e6e8ee;padding-top:14px;margin-bottom:4px"><p style="font-size:14px;color:#555770;line-height:1.7;margin:0">${esc(message)}</p></div>` : ''}
<div style="border-top:1px solid #e6e8ee;padding-top:14px;margin-top:14px">
<p style="font-size:11px;color:#8b8fa3;margin:0">Received ${esc(ts)}</p>
</div>
`,
});
Expand Down
12 changes: 6 additions & 6 deletions apps/website/scripts/generate-whitepaper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const WHITEPAPERS: Record<string, WhitepaperConfig> = {
title: 'From Prototype to Production',
subtitle: 'The Angular Agent Readiness Guide',
eyebrow: '@ngaf/langgraph · Production Readiness Guide',
coverGradient: 'linear-gradient(135deg,#fef0f3 0%,#f4f0ff 45%,#eaf3ff 70%,#e6f4ff 100%)',
coverGradient: 'linear-gradient(135deg, #fafbfc 0%, #eaf3ff 100%)',
outputPdf: 'apps/website/public/whitepaper.pdf',
outputHtml: 'apps/website/public/whitepaper-preview.html',
chapters: [
Expand Down Expand Up @@ -196,7 +196,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
title: 'The Enterprise Guide to Agent Streaming in Angular',
subtitle: 'Ship LangGraph agents in Angular — without building the plumbing',
eyebrow: '@ngaf/langgraph · Enterprise Guide',
coverGradient: 'linear-gradient(135deg, #eaf3ff 0%, #e6f4ff 45%, #f4f0ff 70%, #fef0f3 100%)',
coverGradient: 'linear-gradient(135deg, #fafbfc 0%, #eaf3ff 100%)',
outputPdf: 'apps/website/public/whitepapers/angular.pdf',
outputHtml: 'apps/website/public/whitepapers/angular-preview.html',
chapters: [
Expand Down Expand Up @@ -323,7 +323,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
title: 'The Enterprise Guide to Generative UI in Angular',
subtitle: 'Agents that render UI — without coupling to your frontend',
eyebrow: '@ngaf/render · Enterprise Guide',
coverGradient: 'linear-gradient(135deg, #e8f5e9 0%, #eaf3ff 45%, #f4f0ff 70%, #fef0f3 100%)',
coverGradient: 'linear-gradient(135deg, #fafbfc 0%, #e8f5e9 100%)',
outputPdf: 'apps/website/public/whitepapers/render.pdf',
outputHtml: 'apps/website/public/whitepapers/render-preview.html',
chapters: [
Expand Down Expand Up @@ -433,7 +433,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
title: 'The Enterprise Guide to Agent Chat Interfaces in Angular',
subtitle: 'Production agent chat UI in days, not sprints',
eyebrow: '@ngaf/chat · Enterprise Guide',
coverGradient: 'linear-gradient(135deg, #f3e8ff 0%, #f4f0ff 45%, #eaf3ff 70%, #e6f4ff 100%)',
coverGradient: 'linear-gradient(135deg, #fafbfc 0%, #f3e8ff 100%)',
outputPdf: 'apps/website/public/whitepapers/chat.pdf',
outputHtml: 'apps/website/public/whitepapers/chat-preview.html',
chapters: [
Expand Down Expand Up @@ -564,7 +564,7 @@ function buildHTML(
config: WhitepaperConfig,
): string {
const tocHTML = chapters.map((ch, i) => `
<div style="display:flex;align-items:baseline;gap:8px;padding:10px 0;border-bottom:1px solid rgba(0,0,0,.06);font-size:15px;color:#444">
<div style="display:flex;align-items:baseline;gap:8px;padding:10px 0;border-bottom:1px solid #e6e8ee;font-size:15px;color:#555770">
<span style="font-family:monospace;font-size:11px;color:#004090;font-weight:700;min-width:24px">${String(i + 1).padStart(2, '0')}</span>
<span style="flex:1">${ch.title}</span>
</div>`).join('');
Expand Down Expand Up @@ -601,7 +601,7 @@ function buildHTML(
<div style="font-family:monospace;font-size:11px;text-transform:uppercase;letter-spacing:0.12em;color:#004090;font-weight:700;margin-bottom:24px">${config.eyebrow}</div>
<h1 style="font-family:'EB Garamond',serif;font-size:52px;font-weight:800;line-height:1.1;color:#1a1a2e;margin-bottom:20px">${config.title.replace(/ /g, '<br>')}</h1>
<p style="font-family:'EB Garamond',serif;font-style:italic;font-size:20px;color:#555770;margin-bottom:40px">${config.subtitle}</p>
<div style="font-size:13px;color:#888;font-family:monospace">cacheplane.ai · ${new Date().getFullYear()}</div>
<div style="font-size:13px;color:#8b8fa3;font-family:monospace">cacheplane.ai · ${new Date().getFullYear()}</div>
</div>

<!-- TOC -->
Expand Down
6 changes: 3 additions & 3 deletions apps/website/src/app/api/email-preview/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ export async function GET(req: NextRequest) {

// Wrap in a preview frame showing subject line
const preview = `<!DOCTYPE html><html><head><meta charset="utf-8"><title>Preview: ${subject}</title></head>
<body style="margin:0;padding:0;background:#e4e4e7">
<div style="background:#fff;padding:12px 24px;border-bottom:1px solid #e4e4e7;font-family:Inter,Arial,sans-serif;display:flex;align-items:center;justify-content:space-between">
<body style="margin:0;padding:0;background:#f4f6fb">
<div style="background:#fff;padding:12px 24px;border-bottom:1px solid #e6e8ee;font-family:Inter,Arial,sans-serif;display:flex;align-items:center;justify-content:space-between">
<div>
<span style="font-size:11px;color:#71717a;text-transform:uppercase;letter-spacing:0.06em">Subject:</span>
<span style="font-size:11px;color:#8b8fa3;text-transform:uppercase;letter-spacing:0.06em">Subject:</span>
<span style="font-size:14px;font-weight:600;color:#1a1a2e;margin-left:8px">${subject}</span>
</div>
<a href="/api/email-preview" style="font-size:12px;color:#004090;text-decoration:none">← All templates</a>
Expand Down
Loading