Skip to content

Commit 7d1d5a2

Browse files
bloveclaude
andauthored
Email brand pass: drop gradient header, use new palette (#277)
* refactor(website): email brand pass — drop gradient header, use new palette (Group B.1) Migrates the shared wrapEmail() and lead-notification templates off the legacy aesthetic (pastel gradient header band + zinc-200/400 palette) to the Statusbrew-shaped tokens used by the marketing site: - email-wrapper.ts: drops the 4-stop pastel linear-gradient header band for a white header with a hairline #e6e8ee bottom border. Body background switches from #e8eaf0 to #f4f6fb (surfaceTinted). Card drops the box-shadow in favor of a 1px #e6e8ee border with border-radius bumped 12px → 14px. Footer divider + text colors unified to #e6e8ee + #8b8fa3. - lead-notification.ts: same palette swap (3 references). - /api/email-preview dev route: matching swap so the preview wrapper doesn't read like two different brands. All 7 dev preview endpoints (whitepaper-download, newsletter-welcome, lead-notification, drip-day-{2,5,10,20}) return HTTP 200 and a grep of the rendered HTML for the legacy palette returns zero matches. Per-library accent colors (#004090 LangGraph blue, #5a00c8 chat purple, #1a7a40 render green, #DD0031 angular red) intentionally preserved in template bodies — those are brand signals, not chrome. Whitepaper-PDF covers are Group B.2 (separate PR — requires figuring out the PDF build pipeline). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(website): whitepaper PDF cover brand pass (Group B.2) Updates apps/website/scripts/generate-whitepaper.ts so the next regen of the 4 whitepapers produces covers matching the Statusbrew-shaped marketing aesthetic. - coverGradient per paper: 4-stop pastel rainbows replaced with subtle two-stop gradients in the new palette. Each paper carries a light hint of its library's brand accent: - whitepaper.pdf (agent): #fafbfc → #eaf3ff (LangGraph blue) - angular.pdf: #fafbfc → #eaf3ff (LangGraph blue) - render.pdf: #fafbfc → #e8f5e9 (render green) - chat.pdf: #fafbfc → #f3e8ff (chat purple) - Cover footer cacheplane.ai text: #888 → #8b8fa3 (textMuted) - TOC row border + meta color: rgba(0,0,0,.06)/#444 → #e6e8ee/#555770 (border + textSecondary) The committed PDF artifacts under apps/website/public/whitepaper*.pdf and public/whitepapers/*.pdf are unchanged — they regenerate next time someone runs the whitepaper script (requires ANTHROPIC_API_KEY). Until then the deployed PDFs continue to use the legacy cover; the source of truth for the new cover lives in this script. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 55951ce commit 7d1d5a2

4 files changed

Lines changed: 24 additions & 21 deletions

File tree

apps/website/emails/email-wrapper.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
/**
22
* Shared HTML wrapper for all email templates.
3-
* Gradient header band with logo, white body, footer.
3+
*
4+
* Brand pass: drops the pastel gradient header band (legacy aesthetic) for
5+
* a clean white card with hairline borders, matching the Statusbrew-inspired
6+
* marketing surface. Inline-only styles for cross-client compatibility.
47
*/
58
export function wrapEmail(opts: {
69
body: string;
710
showUnsubscribe?: boolean;
811
}): string {
912
return `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head>
10-
<body style="font-family:Inter,Arial,sans-serif;background-color:#e8eaf0;padding:40px 0;margin:0">
11-
<div style="max-width:520px;margin:0 auto;border-radius:12px;overflow:hidden;box-shadow:0 2px 12px rgba(0,0,0,0.08)">
12-
<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)">
13-
<div style="font-size:13px;font-weight:700;color:#1a1a2e;letter-spacing:-0.01em">🛩️ Angular Agent Framework</div>
13+
<body style="font-family:Inter,Arial,sans-serif;background-color:#f4f6fb;padding:40px 16px;margin:0">
14+
<div style="max-width:520px;margin:0 auto;background:#ffffff;border:1px solid #e6e8ee;border-radius:14px;overflow:hidden">
15+
<div style="padding:20px 32px;border-bottom:1px solid #e6e8ee">
16+
<div style="font-size:14px;font-weight:700;color:#1a1a2e;letter-spacing:-0.01em">🛩️ Angular Agent Framework</div>
1417
</div>
15-
<div style="background:#fff;padding:28px 32px 32px">
18+
<div style="padding:32px">
1619
${opts.body}
17-
<div style="border-top:1px solid #e4e4e7;margin-top:28px;padding-top:16px">
18-
<p style="font-size:11px;color:#a1a1aa;line-height:1.5;margin:0">Angular Agent Framework — Signal-native streaming for LangGraph.</p>
19-
${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>' : ''}
20+
<div style="border-top:1px solid #e6e8ee;margin-top:28px;padding-top:16px">
21+
<p style="font-size:11px;color:#8b8fa3;line-height:1.5;margin:0">Angular Agent Framework — Signal-native streaming for LangGraph.</p>
22+
${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>' : ''}
2023
</div>
2124
</div>
2225
</div>

apps/website/emails/lead-notification.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ export function leadNotificationHtml({ name, email, company, message, ts }: Lead
1414
<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>
1515
<p style="font-size:20px;font-weight:700;color:#1a1a2e;margin:0 0 4px">${esc(name)}</p>
1616
<p style="font-size:14px;color:#8b8fa3;margin:0 0 16px">${esc(email)}${company ? ` — ${esc(company)}` : ''}</p>
17-
${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>` : ''}
18-
<div style="border-top:1px solid #e4e4e7;padding-top:14px;margin-top:14px">
19-
<p style="font-size:11px;color:#a1a1aa;margin:0">Received ${esc(ts)}</p>
17+
${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>` : ''}
18+
<div style="border-top:1px solid #e6e8ee;padding-top:14px;margin-top:14px">
19+
<p style="font-size:11px;color:#8b8fa3;margin:0">Received ${esc(ts)}</p>
2020
</div>
2121
`,
2222
});

apps/website/scripts/generate-whitepaper.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ const WHITEPAPERS: Record<string, WhitepaperConfig> = {
7070
title: 'From Prototype to Production',
7171
subtitle: 'The Angular Agent Readiness Guide',
7272
eyebrow: '@ngaf/langgraph · Production Readiness Guide',
73-
coverGradient: 'linear-gradient(135deg,#fef0f3 0%,#f4f0ff 45%,#eaf3ff 70%,#e6f4ff 100%)',
73+
coverGradient: 'linear-gradient(135deg, #fafbfc 0%, #eaf3ff 100%)',
7474
outputPdf: 'apps/website/public/whitepaper.pdf',
7575
outputHtml: 'apps/website/public/whitepaper-preview.html',
7676
chapters: [
@@ -196,7 +196,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
196196
title: 'The Enterprise Guide to Agent Streaming in Angular',
197197
subtitle: 'Ship LangGraph agents in Angular — without building the plumbing',
198198
eyebrow: '@ngaf/langgraph · Enterprise Guide',
199-
coverGradient: 'linear-gradient(135deg, #eaf3ff 0%, #e6f4ff 45%, #f4f0ff 70%, #fef0f3 100%)',
199+
coverGradient: 'linear-gradient(135deg, #fafbfc 0%, #eaf3ff 100%)',
200200
outputPdf: 'apps/website/public/whitepapers/angular.pdf',
201201
outputHtml: 'apps/website/public/whitepapers/angular-preview.html',
202202
chapters: [
@@ -323,7 +323,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
323323
title: 'The Enterprise Guide to Generative UI in Angular',
324324
subtitle: 'Agents that render UI — without coupling to your frontend',
325325
eyebrow: '@ngaf/render · Enterprise Guide',
326-
coverGradient: 'linear-gradient(135deg, #e8f5e9 0%, #eaf3ff 45%, #f4f0ff 70%, #fef0f3 100%)',
326+
coverGradient: 'linear-gradient(135deg, #fafbfc 0%, #e8f5e9 100%)',
327327
outputPdf: 'apps/website/public/whitepapers/render.pdf',
328328
outputHtml: 'apps/website/public/whitepapers/render-preview.html',
329329
chapters: [
@@ -433,7 +433,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
433433
title: 'The Enterprise Guide to Agent Chat Interfaces in Angular',
434434
subtitle: 'Production agent chat UI in days, not sprints',
435435
eyebrow: '@ngaf/chat · Enterprise Guide',
436-
coverGradient: 'linear-gradient(135deg, #f3e8ff 0%, #f4f0ff 45%, #eaf3ff 70%, #e6f4ff 100%)',
436+
coverGradient: 'linear-gradient(135deg, #fafbfc 0%, #f3e8ff 100%)',
437437
outputPdf: 'apps/website/public/whitepapers/chat.pdf',
438438
outputHtml: 'apps/website/public/whitepapers/chat-preview.html',
439439
chapters: [
@@ -564,7 +564,7 @@ function buildHTML(
564564
config: WhitepaperConfig,
565565
): string {
566566
const tocHTML = chapters.map((ch, i) => `
567-
<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">
567+
<div style="display:flex;align-items:baseline;gap:8px;padding:10px 0;border-bottom:1px solid #e6e8ee;font-size:15px;color:#555770">
568568
<span style="font-family:monospace;font-size:11px;color:#004090;font-weight:700;min-width:24px">${String(i + 1).padStart(2, '0')}</span>
569569
<span style="flex:1">${ch.title}</span>
570570
</div>`).join('');
@@ -601,7 +601,7 @@ function buildHTML(
601601
<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>
602602
<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>
603603
<p style="font-family:'EB Garamond',serif;font-style:italic;font-size:20px;color:#555770;margin-bottom:40px">${config.subtitle}</p>
604-
<div style="font-size:13px;color:#888;font-family:monospace">cacheplane.ai · ${new Date().getFullYear()}</div>
604+
<div style="font-size:13px;color:#8b8fa3;font-family:monospace">cacheplane.ai · ${new Date().getFullYear()}</div>
605605
</div>
606606
607607
<!-- TOC -->

apps/website/src/app/api/email-preview/route.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ export async function GET(req: NextRequest) {
6464

6565
// Wrap in a preview frame showing subject line
6666
const preview = `<!DOCTYPE html><html><head><meta charset="utf-8"><title>Preview: ${subject}</title></head>
67-
<body style="margin:0;padding:0;background:#e4e4e7">
68-
<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">
67+
<body style="margin:0;padding:0;background:#f4f6fb">
68+
<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">
6969
<div>
70-
<span style="font-size:11px;color:#71717a;text-transform:uppercase;letter-spacing:0.06em">Subject:</span>
70+
<span style="font-size:11px;color:#8b8fa3;text-transform:uppercase;letter-spacing:0.06em">Subject:</span>
7171
<span style="font-size:14px;font-weight:600;color:#1a1a2e;margin-left:8px">${subject}</span>
7272
</div>
7373
<a href="/api/email-preview" style="font-size:12px;color:#004090;text-decoration:none">← All templates</a>

0 commit comments

Comments
 (0)