From ad8d3a4940943ff7dd14bdf9700657e3eae6ccff Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 18 May 2026 19:47:55 -0700 Subject: [PATCH] Audit ThreadPlane domain migration and lead forms --- .env.example | 8 +- apps/website/.env.example | 4 +- apps/website/e2e/website.spec.ts | 96 +++++++++ apps/website/public/whitepaper.pdf | Bin 442646 -> 442854 bytes apps/website/public/whitepapers/angular.pdf | Bin 500522 -> 500730 bytes apps/website/public/whitepapers/chat.pdf | Bin 442995 -> 443203 bytes apps/website/public/whitepapers/render.pdf | Bin 497124 -> 497329 bytes .../scripts/refresh-whitepaper-covers.ts | 5 +- apps/website/src/app/api/leads/route.spec.ts | 192 ++++++++++++++++++ apps/website/src/app/api/leads/route.ts | 12 +- .../components/landing/WhitePaperBlock.tsx | 5 +- scripts/examples-middleware.ts | 2 +- scripts/langgraph-proxy.ts | 6 +- 13 files changed, 312 insertions(+), 18 deletions(-) create mode 100644 apps/website/src/app/api/leads/route.spec.ts diff --git a/.env.example b/.env.example index 16e79bcf3..e988e8440 100644 --- a/.env.example +++ b/.env.example @@ -7,9 +7,9 @@ POSTHOG_HOST=https://us.i.posthog.com POSTHOG_PROJECT_ID= # @ngaf/telemetry (libs/telemetry) -# Default ingest URL points to the Cacheplane website reverse proxy. Self-hosters +# Default ingest URL points to the ThreadPlane website reverse proxy. Self-hosters # can redirect to their own ingest. See libs/telemetry/README.md. -# NGAF_TELEMETRY_INGEST_URL=https://cacheplane.ai/api/ingest +# NGAF_TELEMETRY_INGEST_URL=https://threadplane.ai/api/ingest # NGAF_TELEMETRY_SAMPLE_RATE=1.0 # DO_NOT_TRACK=1 # cross-vendor opt-out # NGAF_TELEMETRY_DISABLED=1 # package-specific opt-out @@ -19,11 +19,11 @@ NEXT_PUBLIC_COCKPIT_POSTHOG_TOKEN= NEXT_PUBLIC_COCKPIT_CAPTURE_LOCAL=false # Cockpit iframe → cockpit-shell /ingest proxy (Spec 1D). -# Production: full absolute URL (e.g. https://cockpit.cacheplane.ai/ingest). +# Production: full absolute URL (e.g. https://cockpit.threadplane.ai/ingest). # Leave empty in dev to let RunMode derive it from window.location.origin. NEXT_PUBLIC_COCKPIT_INGEST_HOST= # CORS origin allowed to POST to cockpit's /ingest from iframes (Spec 1D). -# Production: https://examples.cacheplane.ai +# Production: https://examples.threadplane.ai # Leave empty in dev — wildcard '*' is used. NEXT_PUBLIC_COCKPIT_IFRAME_ORIGIN= diff --git a/apps/website/.env.example b/apps/website/.env.example index 55153d89e..ce2ca8ae2 100644 --- a/apps/website/.env.example +++ b/apps/website/.env.example @@ -15,8 +15,8 @@ ANTHROPIC_MODEL=claude-sonnet-4-6 # Resend (https://resend.com — free tier: 3,000 emails/month) RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxxxxxxxxxx RESEND_AUDIENCE_ID=aud_xxxxxxxxxxxxxxxxxxxxxxxxxxxx -RESEND_FROM="Angular Stream Resource " -RESEND_NOTIFY_TO=hello@cacheplane.io +RESEND_FROM="Agent UI for Angular " +RESEND_NOTIFY_TO=hello@cacheplane.ai # Loops.so (https://loops.so — free tier: 1,000 contacts) LOOPS_API_KEY= diff --git a/apps/website/e2e/website.spec.ts b/apps/website/e2e/website.spec.ts index d99e768eb..8e4bb59d7 100644 --- a/apps/website/e2e/website.spec.ts +++ b/apps/website/e2e/website.spec.ts @@ -33,6 +33,102 @@ test('pricing page lead form validates required fields', async ({ page }) => { await expect(page.locator('form').first()).toBeVisible(); }); +test('contact page submits a lead payload and renders success state', async ({ page }) => { + let leadPayload: Record | undefined; + await page.route('**/api/leads', async (route) => { + leadPayload = route.request().postDataJSON(); + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ ok: true }), + }); + }); + + await page.goto('/contact?source=e2e_contact&track=enterprise'); + const contactForm = page.locator('main form').first(); + await contactForm.getByRole('textbox', { name: 'Email', exact: true }).fill('jane@acme.com'); + await contactForm.getByRole('textbox', { name: 'Name' }).fill('Jane Smith'); + await contactForm.getByRole('textbox', { name: 'Company' }).fill('Acme'); + await contactForm.getByRole('textbox', { name: 'Message' }).fill('We are evaluating Agent UI for Angular.'); + await contactForm.getByRole('button', { name: 'Send' }).click(); + + await expect(page.getByText("Thanks. We'll be in touch within one business day.")).toBeVisible(); + expect(leadPayload).toMatchObject({ + email: 'jane@acme.com', + name: 'Jane Smith', + company: 'Acme', + message: 'We are evaluating Agent UI for Angular.', + source_page: 'e2e_contact', + track: 'enterprise', + }); +}); + +test('pricing lead form posts to /api/leads and renders success state', async ({ page }) => { + let leadPayload: Record | undefined; + await page.route('**/api/leads', async (route) => { + leadPayload = route.request().postDataJSON(); + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ ok: true }), + }); + }); + + await page.goto('/pricing#lead-form'); + await page.getByLabel('Name').fill('Jane Smith'); + await page.getByLabel('Work email').fill('jane@acme.com'); + await page.getByLabel('Company').fill('Acme'); + await page.getByLabel('Tell us about your use case').fill('Volume seats and security review.'); + await page.getByRole('button', { name: 'Get in touch' }).click(); + + await expect(page.getByText(/we'll be in touch within one business day/i)).toBeVisible(); + expect(leadPayload).toMatchObject({ + email: 'jane@acme.com', + name: 'Jane Smith', + company: 'Acme', + message: 'Volume seats and security review.', + }); +}); + +test('footer newsletter form posts to /api/newsletter and renders success state', async ({ page }) => { + let payload: Record | undefined; + await page.route('**/api/newsletter', async (route) => { + payload = route.request().postDataJSON(); + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ ok: true }), + }); + }); + + await page.goto('/'); + const footer = page.locator('footer'); + await footer.getByLabel('Email address').fill('reader@acme.com'); + await footer.getByRole('button', { name: 'Subscribe' }).click(); + + await expect(page.getByText("✓ You're subscribed!")).toBeVisible(); + expect(payload).toEqual({ email: 'reader@acme.com' }); +}); + +test('whitepaper signup form posts to /api/whitepaper-signup and renders success state', async ({ page }) => { + let payload: Record | undefined; + await page.route('**/api/whitepaper-signup', async (route) => { + payload = route.request().postDataJSON(); + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ ok: true }), + }); + }); + + await page.goto('/chat'); + await page.locator('#whitepaper-block').getByLabel('Email address').fill('reader@acme.com'); + await page.locator('#whitepaper-block').getByRole('button', { name: 'Download (free)' }).click(); + + await expect(page.getByText(/check your inbox/i)).toBeVisible(); + expect(payload).toEqual({ email: 'reader@acme.com', paper: 'chat' }); +}); + test('docs page renders sidebar and content', async ({ page }) => { await page.goto('/docs/agent/getting-started/introduction'); await expect(page.locator('aside').first()).toBeVisible(); diff --git a/apps/website/public/whitepaper.pdf b/apps/website/public/whitepaper.pdf index 1295bdff024e200fcd4a769517028d69538a50e4..e16c53e5d93ed440b2cc7fcda2f5d9acc9a86809 100644 GIT binary patch delta 21731 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�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 WizMof^0+Qw)3l0?&g7X>RQ?aL-#PjK diff --git a/apps/website/public/whitepapers/angular.pdf b/apps/website/public/whitepapers/angular.pdf index a439dc90968d91e5ac7d75626f19c39b637f7828..3a2520306e08435d7412179d32bf38c87f0544a8 100644 GIT binary patch delta 23940 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 vo-wL3(D21Y2USLtTM$(L<3guDD#|QGD3PoP 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 NO>V@9@l#CY{s-SBNpt`J delta 23632 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 eWiINklLYbxvdhrVH9 diff --git a/apps/website/public/whitepapers/render.pdf b/apps/website/public/whitepapers/render.pdf index 3559958d51ef6073805b108e7770c7e34399bf17..8cd4adedabb128db87dbc8827accfd3e21efdc0a 100644 GIT binary patch delta 15854 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 delta 15637 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 F{|5-j^=kkC diff --git a/apps/website/scripts/refresh-whitepaper-covers.ts b/apps/website/scripts/refresh-whitepaper-covers.ts index 4abbccf43..8e6d92114 100644 --- a/apps/website/scripts/refresh-whitepaper-covers.ts +++ b/apps/website/scripts/refresh-whitepaper-covers.ts @@ -61,10 +61,9 @@ const LEGACY_GRADIENT_RE = function refreshHtml(html: string, paper: Paper): string { let out = html; - if (!LEGACY_GRADIENT_RE.test(out)) { - throw new Error(`No legacy gradient found in ${paper.htmlPath}`); + if (LEGACY_GRADIENT_RE.test(out)) { + out = out.replace(LEGACY_GRADIENT_RE, `background:${paper.newGradient}`); } - out = out.replace(LEGACY_GRADIENT_RE, `background:${paper.newGradient}`); // Cover footer: #888 → #8b8fa3 (textMuted) out = out.replace(/font-size:13px;color:#888/g, 'font-size:13px;color:#8b8fa3'); diff --git a/apps/website/src/app/api/leads/route.spec.ts b/apps/website/src/app/api/leads/route.spec.ts new file mode 100644 index 000000000..d011fe78f --- /dev/null +++ b/apps/website/src/app/api/leads/route.spec.ts @@ -0,0 +1,192 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +const sendEmailMock = vi.hoisted(() => vi.fn()); +const addToAudienceMock = vi.hoisted(() => vi.fn()); +const loopsUpsertContactMock = vi.hoisted(() => vi.fn()); +const loopsSendEventMock = vi.hoisted(() => vi.fn()); +const scheduleWhitepaperDripMock = vi.hoisted(() => vi.fn()); +const captureLeadConversionMock = vi.hoisted(() => vi.fn()); +const captureLeadQualifiedMock = vi.hoisted(() => vi.fn()); +const captureNewsletterConversionMock = vi.hoisted(() => vi.fn()); +const captureWhitepaperConversionMock = vi.hoisted(() => vi.fn()); +const mkdirSyncMock = vi.hoisted(() => vi.fn()); +const appendFileSyncMock = vi.hoisted(() => vi.fn()); + +vi.mock('fs', () => ({ + default: { + mkdirSync: mkdirSyncMock, + appendFileSync: appendFileSyncMock, + }, +})); + +vi.mock('../../../../lib/resend', () => ({ + FROM: 'Agent UI for Angular ', + NOTIFY_TO: 'hello@cacheplane.ai', + sendEmail: sendEmailMock, + addToAudience: addToAudienceMock, +})); + +vi.mock('../../../../lib/loops', () => ({ + loopsUpsertContact: loopsUpsertContactMock, + loopsSendEvent: loopsSendEventMock, +})); + +vi.mock('../../../../lib/drip', () => ({ + scheduleWhitepaperDrip: scheduleWhitepaperDripMock, +})); + +vi.mock('../../../lib/analytics/server', () => ({ + captureLeadConversion: captureLeadConversionMock, + captureLeadQualified: captureLeadQualifiedMock, + captureNewsletterConversion: captureNewsletterConversionMock, + captureWhitepaperConversion: captureWhitepaperConversionMock, +})); + +import { POST as postLead } from './route'; +import { POST as postNewsletter } from '../newsletter/route'; +import { POST as postWhitepaperSignup } from '../whitepaper-signup/route'; + +function jsonRequest(path: string, body: unknown): Request { + return new Request(`https://threadplane.ai${path}`, { + method: 'POST', + headers: { + 'content-type': 'application/json', + referer: 'https://threadplane.ai/pricing', + }, + body: JSON.stringify(body), + }); +} + +beforeEach(() => { + vi.clearAllMocks(); + sendEmailMock.mockResolvedValue(undefined); + addToAudienceMock.mockResolvedValue(undefined); + loopsUpsertContactMock.mockResolvedValue(undefined); + loopsSendEventMock.mockResolvedValue(undefined); + scheduleWhitepaperDripMock.mockResolvedValue(undefined); + captureLeadConversionMock.mockResolvedValue(undefined); + captureLeadQualifiedMock.mockResolvedValue(undefined); + captureNewsletterConversionMock.mockResolvedValue(undefined); + captureWhitepaperConversionMock.mockResolvedValue(undefined); +}); + +describe('/api/leads', () => { + it('persists the lead, notifies the team, syncs audience systems, and records analytics', async () => { + const response = await postLead(jsonRequest('/api/leads', { + name: 'Jane Smith', + email: 'jane@acme.com', + company: 'Acme', + message: 'We are evaluating Agent UI for Angular.', + }) as never); + + expect(response.status).toBe(200); + expect(await response.json()).toEqual({ ok: true }); + expect(appendFileSyncMock).toHaveBeenCalledWith( + expect.stringContaining('data/leads.ndjson'), + expect.stringContaining('"email":"jane@acme.com"'), + 'utf8', + ); + expect(sendEmailMock).toHaveBeenCalledWith(expect.objectContaining({ + from: 'Agent UI for Angular ', + to: 'hello@cacheplane.ai', + subject: 'New lead: Jane Smith at Acme', + html: expect.stringContaining('jane@acme.com'), + })); + expect(addToAudienceMock).toHaveBeenCalledWith('jane@acme.com', 'Jane Smith'); + expect(loopsUpsertContactMock).toHaveBeenCalledWith(expect.objectContaining({ + email: 'jane@acme.com', + firstName: 'Jane Smith', + source: 'lead-form', + properties: { company: 'Acme' }, + })); + expect(loopsSendEventMock).toHaveBeenCalledWith(expect.objectContaining({ + email: 'jane@acme.com', + eventName: 'lead_submitted', + })); + expect(captureLeadConversionMock).toHaveBeenCalledWith(expect.objectContaining({ + email: 'jane@acme.com', + company: 'Acme', + sourcePage: '/pricing', + })); + expect(captureLeadQualifiedMock).toHaveBeenCalledWith(expect.objectContaining({ + email: 'jane@acme.com', + company: 'Acme', + sourcePage: '/pricing', + })); + }); + + it('rejects malformed lead emails before sending or persisting anything', async () => { + const response = await postLead(jsonRequest('/api/leads', { email: 'not-an-email' }) as never); + + expect(response.status).toBe(400); + expect(sendEmailMock).not.toHaveBeenCalled(); + expect(addToAudienceMock).not.toHaveBeenCalled(); + expect(appendFileSyncMock).not.toHaveBeenCalled(); + }); +}); + +describe('/api/newsletter', () => { + it('sends the welcome email, adds the contact to Resend, and records analytics', async () => { + const response = await postNewsletter(jsonRequest('/api/newsletter', { email: 'reader@acme.com' }) as never); + + expect(response.status).toBe(200); + expect(sendEmailMock).toHaveBeenCalledWith(expect.objectContaining({ + from: 'Agent UI for Angular ', + to: 'reader@acme.com', + subject: 'Welcome to Agent UI for Angular updates', + })); + expect(addToAudienceMock).toHaveBeenCalledWith('reader@acme.com'); + expect(loopsUpsertContactMock).toHaveBeenCalledWith(expect.objectContaining({ + email: 'reader@acme.com', + source: 'newsletter', + })); + expect(loopsSendEventMock).toHaveBeenCalledWith(expect.objectContaining({ + email: 'reader@acme.com', + eventName: 'newsletter_subscribed', + })); + expect(captureNewsletterConversionMock).toHaveBeenCalledWith({ + email: 'reader@acme.com', + sourcePage: '/pricing', + }); + }); +}); + +describe('/api/whitepaper-signup', () => { + it('sends the requested download, schedules drip, syncs the audience, and records analytics', async () => { + const response = await postWhitepaperSignup(jsonRequest('/api/whitepaper-signup', { + name: 'Reader', + email: 'reader@acme.com', + paper: 'chat', + }) as never); + + expect(response.status).toBe(200); + expect(appendFileSyncMock).toHaveBeenCalledWith( + expect.stringContaining('data/whitepaper-signups.ndjson'), + expect.stringContaining('"paper":"chat"'), + 'utf8', + ); + expect(sendEmailMock).toHaveBeenCalledWith(expect.objectContaining({ + from: 'Agent UI for Angular ', + to: 'reader@acme.com', + subject: 'Your Enterprise Guide to Agent Chat Interfaces', + html: expect.stringContaining('https://threadplane.ai/whitepapers/chat.pdf'), + })); + expect(scheduleWhitepaperDripMock).toHaveBeenCalledWith('reader@acme.com', 'chat'); + expect(addToAudienceMock).toHaveBeenCalledWith('reader@acme.com', 'Reader'); + expect(loopsUpsertContactMock).toHaveBeenCalledWith(expect.objectContaining({ + email: 'reader@acme.com', + firstName: 'Reader', + source: 'whitepaper-chat', + })); + expect(loopsSendEventMock).toHaveBeenCalledWith(expect.objectContaining({ + email: 'reader@acme.com', + eventName: 'whitepaper_downloaded', + properties: { paper: 'chat' }, + })); + expect(captureWhitepaperConversionMock).toHaveBeenCalledWith({ + email: 'reader@acme.com', + paper: 'chat', + sourcePage: '/pricing', + }); + }); +}); diff --git a/apps/website/src/app/api/leads/route.ts b/apps/website/src/app/api/leads/route.ts index 27a905593..f8cd7dd10 100644 --- a/apps/website/src/app/api/leads/route.ts +++ b/apps/website/src/app/api/leads/route.ts @@ -10,7 +10,13 @@ import { getSourcePage } from '@ngaf/telemetry/shared'; const LEADS_FILE = path.join(process.cwd(), 'data', 'leads.ndjson'); export async function POST(req: NextRequest) { - const body = await req.json() as { name?: unknown; email?: unknown; company?: unknown; message?: unknown }; + let body: { name?: unknown; email?: unknown; company?: unknown; message?: unknown }; + try { + body = await req.json(); + } catch { + return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 }); + } + const sanitize = (v: unknown, max = 500): string => typeof v === 'string' ? v.slice(0, max).trim() : ''; @@ -19,8 +25,8 @@ export async function POST(req: NextRequest) { const company = sanitize(body.company, 200); const message = sanitize(body.message, 2000); - if (!email) { - return NextResponse.json({ error: 'email required' }, { status: 400 }); + if (!email || !email.includes('@')) { + return NextResponse.json({ error: 'Valid email required' }, { status: 400 }); } const ts = new Date().toISOString(); diff --git a/apps/website/src/components/landing/WhitePaperBlock.tsx b/apps/website/src/components/landing/WhitePaperBlock.tsx index 991d95bac..c5dae0932 100644 --- a/apps/website/src/components/landing/WhitePaperBlock.tsx +++ b/apps/website/src/components/landing/WhitePaperBlock.tsx @@ -44,11 +44,12 @@ export function WhitePaperBlock({ paper = 'overview' }: WhitePaperBlockProps = { paper, }); try { - await fetch('/api/whitepaper-signup', { + const res = await fetch('/api/whitepaper-signup', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ email }), + body: JSON.stringify({ email, paper }), }); + if (!res.ok) throw new Error('whitepaper_signup_failed'); track(analyticsEvents.marketingWhitepaperSignupSuccess, { surface: 'home_whitepaper', source_section: 'whitepaper-block', diff --git a/scripts/examples-middleware.ts b/scripts/examples-middleware.ts index 0cc5d6383..b2ef44443 100644 --- a/scripts/examples-middleware.ts +++ b/scripts/examples-middleware.ts @@ -1,5 +1,5 @@ /** - * Vercel Serverless Function proxy for the cockpit-examples deployment. + * Vercel Serverless Function proxy for the threadplane-examples deployment. * * Thin wrapper around scripts/langgraph-proxy.ts that adds the * examples-specific Referer-based backend resolution. Today there's diff --git a/scripts/langgraph-proxy.ts b/scripts/langgraph-proxy.ts index d8f139a7b..4b387079c 100644 --- a/scripts/langgraph-proxy.ts +++ b/scripts/langgraph-proxy.ts @@ -6,7 +6,7 @@ * `LANGSMITH_API_KEY`, streams SSE responses chunk-by-chunk, and * forwards all other content types verbatim. * - * Shared between `scripts/examples-middleware.ts` (cockpit-examples + * Shared between `scripts/examples-middleware.ts` (threadplane-examples * deployment) and `scripts/demo-middleware.ts` (canonical demo * deployment). Per-deployment specifics — like the examples' * Referer-based backend routing — are passed in via `ProxyConfig`. @@ -45,7 +45,7 @@ export interface ProxyConfig { * it unset. */ readonly checkRateLimit?: (ip: string) => Promise<{ allowed: boolean; retryAfterSec: number; count: number }>; /** Origins to allow via CORS. If undefined, legacy wildcard `*` behavior - * preserved (used by cockpit-examples). Each entry is a full origin + * preserved (used by threadplane-examples). Each entry is a full origin * string, e.g. `https://demo.threadplane.ai`. Match is exact-string. */ readonly allowedOrigins?: readonly string[]; /** Maximum request body size in bytes. If undefined, no cap (legacy @@ -86,7 +86,7 @@ export function createProxyHandler(config: ProxyConfig = {}): (req: VercelReques return async function handler(req, res) { // CORS — echo matching Origin when allowedOrigins is configured; - // otherwise legacy * behavior preserved for cockpit-examples. + // otherwise legacy * behavior preserved for threadplane-examples. res.setHeader('access-control-allow-methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.setHeader('access-control-allow-headers', 'content-type, x-api-key, authorization');