toga-ai 1.0.635 → 1.0.637
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/knowledge/2.0/apps/ai-bdr/INDEX.md +2 -1
- package/knowledge/2.0/apps/ai-bdr/features/security-landing-page.md +202 -0
- package/knowledge/2.0/apps/ai-bdr/features/web-funnel-app.md +50 -1
- package/knowledge/INDEX.md +1 -1
- package/knowledge/sessions/2026-08-24-bdr-landing-update-tcox.md +76 -0
- package/package.json +1 -1
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
| [BDR Web Funnel — Full Implementation Plan](features/bdr-web-funnel-plan.md) | > **Execution status (2026-07-16):** PLAN **Phases 0–5 are BUILT and QA'd**, Phase 6 > was **mostly already built** (the `info` contract was implemented at comm | bdr/PLAN.md, bdr/mockup/app.jsx, bdr/mockup/screens.jsx, bdr/mockup/components.jsx |
|
|
7
7
|
| [Call Orchestration — PHP Worker ↔ Vapi (the integration seam)](features/call-orchestration.md) | The **PHP worker** is the orchestrator; **Vapi** is the actor. | ai-bdr/docs/client-onboarding-sop.md, ai-bdr/docs/vapi-firstmessage-timing-fix.md, ai-bdr/docs/vapi-inbound-callback-assistant-request.md, ai-bdr/docs/vapi-voicemail-iphone-screening.md, ai-bdr/scripts/update_structured_output.py |
|
|
8
8
|
| [Live Call Status — Vapi call API → funnel Success screen lifecycle](features/live-call-status.md) | The BDR funnel's Success screen shows the **real** state of the call it just requested — dialing / ringing / answered-and-talking / ended / not-answered — inste | bdr/src/server/vapiCall.ts, bdr/src/server/callStatus.ts, bdr/src/server/statusToken.ts, bdr/src/server/callbackService.ts, bdr/src/server/workerDialer.ts, bdr/src/lib/callStatus.ts, bdr/src/app/api/call-status/route.ts, bdr/src/app/api/call-now/route.ts, bdr/src/flow/useCallStatusViewModel.ts, bdr/src/flow/callStatusApi.ts, bdr/src/flow/screens/Success.tsx, bdr/src/content/schema.ts, bdr/src/content/default.ts, bdr/src/proxy.ts |
|
|
9
|
+
| [Cybersecurity Landing Page (/landing — the site's current main page)](features/security-landing-page.md) | A single-page **cybersecurity services marketing landing page** at **`/landing`** in the `bdr` repo — and, as of 2026-08-24, **the site's main page**: `/` **307 | bdr/src/app/landing/page.tsx, bdr/src/app/security.css, bdr/src/flow/screens/SecurityLanding.tsx, bdr/src/content/security.ts, bdr/src/components/LogoSymbol.tsx, bdr/src/components/AssistantMark.tsx, bdr/src/components/Ico.tsx, bdr/src/components/Particles.tsx, bdr/next.config.ts, bdr/eslint.config.mjs |
|
|
9
10
|
| [Vapi Integration — Assistants, Tools, Structured Output](features/vapi-integration.md) | Everything inside Vapi: the three assistants, the three shared tools, the shared structured-output schema, the Liquid-templated system prompt, and the Python sc | ai-bdr/vapi/templates/assistant.template.json, ai-bdr/vapi/templates/system-prompt.template.md, ai-bdr/prompts/archive/prompt-may-15.txt, ai-bdr/prompts/campaigns/healthcare-2026-03-18.md, ai-bdr/prompts/campaigns/healthcare-v2-2026-03-25.md, ai-bdr/prompts/templates/campaign-template.md, ai-bdr/scripts/update_assistant.py, ai-bdr/scripts/update_system_prompt.py, ai-bdr/scripts/update_structured_output.py, ai-bdr/scripts/update_call_summary_context.py, ai-bdr/scripts/fix_booking_guardrails.py, ai-bdr/scripts/get_assistant.py, ai-bdr/docs/vapi-firstmessage-timing-fix.md, ai-bdr/docs/vapi-voicemail-iphone-screening.md |
|
|
10
|
-
| [Web Funnel — Built Next.js App (structure, stack, how to run)](features/web-funnel-app.md) |
|
|
11
|
+
| [Web Funnel — Built Next.js App (structure, stack, how to run)](features/web-funnel-app.md) | > **READ FIRST (2026-08-24) — the funnel is currently UNREACHABLE.** `/` now > **307-redirects to `/landing`**, the new cybersecurity landing page > ([security- | bdr/PLAN.md, bdr/next.config.ts, bdr/.gitignore, bdr/src/server/hubspot.ts, bdr/src/server/leadSink.ts, bdr/src/server/callbackService.ts, bdr/src/server/workerDialer.ts, bdr/src/server/mailer.ts, bdr/src/server/statusToken.ts, bdr/src/server/vapiCall.ts, bdr/src/server/callStatus.ts, bdr/src/lib/summaryText.ts, bdr/src/lib/emailFormat.ts, bdr/src/lib/callStatus.ts, bdr/src/app/api/share-summary/route.ts, bdr/src/app/api/call-status/route.ts, bdr/src/flow/shareSummaryApi.ts, bdr/src/flow/callStatusApi.ts, bdr/src/flow/useCallStatusViewModel.ts, bdr/src/flow/screens/Success.tsx, bdr/src/flow/screens/CallNow.tsx, bdr/src/flow/screens/Schedule.tsx, bdr/src/flow/screens/CallSummary.tsx, bdr/src/content/schema.ts, bdr/src/content/default.ts, bdr/test/togaEnrichment.test.ts, bdr/test/fastDial.test.ts, bdr/eslint.config.mjs, bdr/amplify.yml, bdr/src/app, bdr/src/app/layout.tsx, bdr/src/app/page.tsx, bdr/src/app/studio.css, bdr/src/lib/resolveCampaignId.ts, bdr/src/lib/scheduleSlots.ts, bdr/src/lib/formatPhone.ts, bdr/src/lib/analytics.ts, bdr/src/lib/rateLimit.ts, bdr/src/lib/clientIp.ts, bdr/src/proxy.ts, bdr/.env.example, bdr/src/components/GoogleAnalytics.tsx, bdr/src/components/RichText.tsx, bdr/src/content, bdr/src/components, bdr/src/flow, bdr/src/server, bdr/src/server/toga.ts, bdr/src/app/api, bdr/test, bdr/test/togaPrimaryPhone.test.ts, bdr/public, bdr/mockup/styles.css |
|
|
11
12
|
| [Web Funnel — Next.js UI + Config-Driven Campaign Content](features/web-funnel-content-model.md) | > **Status note (RESOLVED 2026-07-16):** the content **contract** below (schema, > provider seam, adapters) is BUILT and QA'd (PLAN Phases 0–5). | bdr/src/content/schema.ts, bdr/src/content/provider.ts, bdr/src/content/useCampaign.ts, bdr/src/content/default.ts, bdr/src/lib/resolveCampaignId.ts, bdr/src/server/leadSink.ts, bdr/src/server/callbackService.ts, bdr/src/app/api/call-now/route.ts, bdr/src/app/api/call-later/route.ts, bdr/src/app/api/contact/route.ts |
|
|
12
13
|
| [New-Campaign Onboarding (6-phase runbook)](workflows/new-campaign-onboarding.md) | The end-to-end procedure for launching a new outbound BDR campaign (industry, offer, target persona, geography). | ai-bdr/docs/client-onboarding-sop.md, ai-bdr/docs/calcom-new-campaign-event-guide.md, ai-bdr/prompts/templates/campaign-template.md, ai-bdr/scripts/update_assistant.py, ai-bdr/scripts/update_system_prompt.py |
|
|
13
14
|
| [Safe AI-BDR Call-Loop Testing (isolated test-campaign runbook)](workflows/safe-call-loop-testing.md) | How to prove the AI-BDR **dialer → Vapi → end-of-call webhook** loop end-to-end **without dialing real prospects**. | dbchanges2/Client_True/2026-07-20a - AiBdrTcoxTestCampaign.sql, worker2/Worker/Ai/Bdr/Vapi.php, worker2/Worker/Ai/Bdr/ZoomInfo.php, worker2/Config/beta.ini |
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Cybersecurity Landing Page (/landing — the site's current main page)
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: ai-bdr
|
|
5
|
+
project: AI-BDR
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-08-24
|
|
10
|
+
owners: [tcox]
|
|
11
|
+
files:
|
|
12
|
+
- bdr/src/app/landing/page.tsx
|
|
13
|
+
- bdr/src/app/security.css
|
|
14
|
+
- bdr/src/flow/screens/SecurityLanding.tsx
|
|
15
|
+
- bdr/src/content/security.ts
|
|
16
|
+
- bdr/src/components/LogoSymbol.tsx
|
|
17
|
+
- bdr/src/components/AssistantMark.tsx
|
|
18
|
+
- bdr/src/components/Ico.tsx
|
|
19
|
+
- bdr/src/components/Particles.tsx
|
|
20
|
+
- bdr/next.config.ts
|
|
21
|
+
- bdr/eslint.config.mjs
|
|
22
|
+
related:
|
|
23
|
+
- web-funnel-app.md
|
|
24
|
+
- web-funnel-content-model.md
|
|
25
|
+
- ../architecture.md
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## What this is
|
|
29
|
+
|
|
30
|
+
A single-page **cybersecurity services marketing landing page** at **`/landing`** in the
|
|
31
|
+
`bdr` repo — and, as of 2026-08-24, **the site's main page**: `/` **307-redirects** to it
|
|
32
|
+
and the 7-screen Agent Studio funnel is parked (see `web-funnel-app.md`). Its job is one
|
|
33
|
+
conversion: *"Book your free risk assessment."*
|
|
34
|
+
|
|
35
|
+
It is a **pixel-faithful port of a new designer mockup**, not new design work. Source
|
|
36
|
+
mockup: `BDR/AI BDR - Security/` (a React 18 UMD + in-browser Babel prototype —
|
|
37
|
+
`app.jsx`, `screens.jsx`, `components.jsx`, `styles.css`, plus a
|
|
38
|
+
`ground-truth-tokens-and-stack.md` token spec). The landing is that mockup's
|
|
39
|
+
**`Capabilities` screen**; because `src/flow/screens/Capabilities.tsx` already exists as a
|
|
40
|
+
studio screen, it was ported under the name **`SecurityLanding`**.
|
|
41
|
+
|
|
42
|
+
**Status: UI only.** Nothing is wired to a backend — no lead capture, no Toga/HubSpot
|
|
43
|
+
call, no analytics events of its own. Wiring is a later decision (see *CTA wiring* below).
|
|
44
|
+
|
|
45
|
+
## Page structure
|
|
46
|
+
|
|
47
|
+
`src/app/landing/page.tsx` is a thin **server component** carrying only `metadata`
|
|
48
|
+
(title `TOGA Technology · Cybersecurity Services` + description) and the
|
|
49
|
+
`import "../security.css"`. Everything visible lives in
|
|
50
|
+
`src/flow/screens/SecurityLanding.tsx` (`"use client"`), which — unlike every studio
|
|
51
|
+
screen — **carries its own page shell**: the noise layer, the mote field, the topbar
|
|
52
|
+
lockup, and the header CTA. There is no shared layout wrapper for it.
|
|
53
|
+
|
|
54
|
+
Section order inside the shell:
|
|
55
|
+
|
|
56
|
+
1. **Hero** (`.lp-hero`) — eyebrow, headline whose closing clause is the TOGA gradient
|
|
57
|
+
span, the primary CTA (`#cta`), and a side column: the value tile
|
|
58
|
+
(`.lp-value`, list-price strike-through → free) framed by a peach-hued `Particles`
|
|
59
|
+
field, plus the offer reveal list (`.lp-offer` / `.lp-reveal`).
|
|
60
|
+
2. **Why it matters** (`.lp-why-matters`) — intro line, then two icon-led cards
|
|
61
|
+
(`problem` / `impact`) and a four-tile stat row (`.lp-stats`).
|
|
62
|
+
3. **Footer** (`.lp-footer`) — logo mark, name, one line, copyright.
|
|
63
|
+
|
|
64
|
+
**Zero binary assets.** Every visual is inline SVG or CSS (`LogoSymbol`,
|
|
65
|
+
`AssistantMark`, the `Ico` registry, `Particles`, gradients). The mockup's `agents/` and
|
|
66
|
+
`uploads/` folders are legacy leftovers and are **not referenced** — do not copy them into
|
|
67
|
+
`public/`. This is the opposite of the studio flow, whose agent art is a real asset
|
|
68
|
+
dependency.
|
|
69
|
+
|
|
70
|
+
## All copy lives in `src/content/security.ts`
|
|
71
|
+
|
|
72
|
+
Every string on the page is in one typed const (`SecurityLandingContent`), so the view
|
|
73
|
+
layer holds **no inline copy**. It deliberately follows the `CampaignBundle` conventions
|
|
74
|
+
from `src/content/schema.ts` — serializable data only, **icons referenced by enum key**
|
|
75
|
+
and hydrated through the `Ico` registry — so the shape can be **grafted into the bundle
|
|
76
|
+
schema later** if the landing becomes campaign-driven. It is not part of the bundle today.
|
|
77
|
+
|
|
78
|
+
- The primary CTA href is `content.hero.primaryCtaHref`.
|
|
79
|
+
- Landing copy contains **no em dashes** — the repo's ESLint no-em-dash rule covers it
|
|
80
|
+
like any other in-repo string.
|
|
81
|
+
|
|
82
|
+
## Design tokens are scoped to the landing, NOT global
|
|
83
|
+
|
|
84
|
+
The mockup's tokens **diverge** from the live studio screens, so every override is
|
|
85
|
+
declared on **`.security-shell`**, never `:root`. That scoping is the whole reason the
|
|
86
|
+
parked studio flow keeps its existing look, and it is load-bearing — moving any of these
|
|
87
|
+
to `:root` restyles the funnel.
|
|
88
|
+
|
|
89
|
+
| Token | Studio (`:root`) | Landing (`.security-shell`) |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| `--accent` | `#4571DD` | `#80A4FF` (cobalt-300) |
|
|
92
|
+
| `--radius` | `8px` | `4px` (crisp/architectural; `--r-sm` 2px, `--r-lg` 12px) |
|
|
93
|
+
| `--r-pill` | (studio value) | `999px` — a true pill, used by the header CTA only |
|
|
94
|
+
| `--muted` | (warmer) | `#94A3B8` (cooler grays; `--faint` `#6A72A6`) |
|
|
95
|
+
| gradient | — | new `--grad-1..4` + `--toga-grad` |
|
|
96
|
+
| `--on-peach` | — | `#1A0E07` (white fails contrast on peach) |
|
|
97
|
+
|
|
98
|
+
Two consequences worth knowing before editing `security.css`:
|
|
99
|
+
|
|
100
|
+
- **Accent-derived tokens must be recomputed under the shell.** `--accent-soft` / `-mid` /
|
|
101
|
+
`-glow` / `-ink` are `color-mix()` values; custom properties resolve where they are
|
|
102
|
+
*declared*, so studio.css's `:root` versions still carry the studio accent. They are
|
|
103
|
+
redeclared on `.security-shell`.
|
|
104
|
+
- **Peach is a fixed brand hue, not the accent.** The mockup's peach values were promoted
|
|
105
|
+
to `--peach` / `--peach-hover` / `--peach-soft` so nothing hardcodes them, but they
|
|
106
|
+
**never** track `--accent` (the mockup's own CLAUDE.md rule is "never hardcode the
|
|
107
|
+
accent," which is why the promotion happened at all).
|
|
108
|
+
|
|
109
|
+
`security.css` (215 lines) reuses studio.css's shared chrome (`.shell`, `.topbar`,
|
|
110
|
+
`.screen`, `.wrap`, the `.btn` base, `.particles`, the `mote` / `syn-rotate` keyframes,
|
|
111
|
+
`@property --syn-a`) and carries only the token overrides plus the selectors studio.css
|
|
112
|
+
does not define or defines differently.
|
|
113
|
+
|
|
114
|
+
## Shared components were extended, not forked
|
|
115
|
+
|
|
116
|
+
- **`Ico.tsx`** — added `eyeoff` and `alert` to the icon registry (additive).
|
|
117
|
+
- **`Particles.tsx`** — added `palette` / `bold` / `radiate` props. The **default branch
|
|
118
|
+
was verified byte-identical**, so the 7 existing studio screens do not shift. Any future
|
|
119
|
+
change here must keep that property.
|
|
120
|
+
- **`LogoSymbol.tsx`** / **`AssistantMark.tsx`** — new inline-SVG marks.
|
|
121
|
+
- **`eslint.config.mjs`** — `"AI BDR - Security/**"` added to `globalIgnores` alongside
|
|
122
|
+
`mockup/**`, so the mockup prototype is not linted.
|
|
123
|
+
|
|
124
|
+
## CTA wiring (read this before assuming the page converts)
|
|
125
|
+
|
|
126
|
+
- **"Book your free risk assessment"** is a real `<a class="btn btn-toga btn-lg">` to
|
|
127
|
+
`https://calendly.com/toga-technology/risk-assessment` (`target="_blank"`,
|
|
128
|
+
`rel="noopener noreferrer"`), sourced from `security.ts` `primaryCtaHref`.
|
|
129
|
+
**CAVEAT: that URL is a placeholder carried over from the mockup** (the mockup's own
|
|
130
|
+
comment says "replace with the real TOGA Calendly link") and the slug's liveness has
|
|
131
|
+
**not** been verified. Confirm it before pointing traffic at the page.
|
|
132
|
+
- **"Learn more"** and the header CTA **"Ask Me Anything"** render **inert**. In the
|
|
133
|
+
mockup, "Ask Me Anything" opened a chat drawer; **the drawer was not ported.**
|
|
134
|
+
|
|
135
|
+
## How to work on it
|
|
136
|
+
|
|
137
|
+
- `npx tsc --noEmit`, `npm run lint`, `npm run build` — all clean as of 2026-08-24;
|
|
138
|
+
`/landing` builds as a **prerendered static** route. Local prod smoke test:
|
|
139
|
+
`GET /` → `307` with `Location: /landing`, `GET /landing` → `200`.
|
|
140
|
+
- **Nothing is committed** — as of capture the whole landing lives in the `bdr` working
|
|
141
|
+
tree only. It is not shipped or deployed.
|
|
142
|
+
|
|
143
|
+
## Known gaps / pending work
|
|
144
|
+
|
|
145
|
+
- **Mobile pass is pending.** The mockup has almost no landing-specific mobile CSS: only a
|
|
146
|
+
900px hero-stack and a 760px stats/matters breakpoint. Its big "mobile pass" block
|
|
147
|
+
contains **zero `.lp-*` rules**, so there is no design to port — the responsive
|
|
148
|
+
treatment below ~760px is an open design question, not a porting oversight.
|
|
149
|
+
- **Chat drawer not ported** (the header CTA's mockup behavior).
|
|
150
|
+
- **Calendly URL unverified** (above).
|
|
151
|
+
- No form, no lead capture, no landing-specific analytics.
|
|
152
|
+
|
|
153
|
+
## Gotchas
|
|
154
|
+
|
|
155
|
+
- **`.security-shell` scoping is load-bearing.** The mockup's tokens conflict with the
|
|
156
|
+
studio flow's (different accent, different radii, cooler grays). Promote any of them to
|
|
157
|
+
`:root` and you restyle the parked funnel. Add new landing rules **under the shell
|
|
158
|
+
selector**, always.
|
|
159
|
+
- **Name collisions with studio screens.** The mockup screen is called `Capabilities` but
|
|
160
|
+
`Capabilities.tsx` is a *studio* screen — hence `SecurityLanding.tsx`. Likewise
|
|
161
|
+
`src/flow/screens/Landing.tsx` is a **studio** screen and has nothing to do with the
|
|
162
|
+
`/landing` route. Check which is meant before editing either.
|
|
163
|
+
- **`.btn` does not reset anchor styling.** Every studio `.btn` is a `<button>`, so
|
|
164
|
+
studio.css never needed `text-decoration:none`. The landing's primary CTA is an `<a>`,
|
|
165
|
+
which arrives underlined — a scoped `.security-shell a.btn{text-decoration:none}` rule
|
|
166
|
+
fixes it. Any future anchor-as-button elsewhere hits the same trap.
|
|
167
|
+
- **`Particles` default behavior must stay byte-identical.** The new `palette`/`bold`/
|
|
168
|
+
`radiate` props are additive on purpose; the 7 studio screens depend on the untouched
|
|
169
|
+
default path.
|
|
170
|
+
- **The new mockup's `styles.css` has the same literal-`\n` corruption class as the old
|
|
171
|
+
one** (2 lines, ~379 / ~460), a JS-string generation artifact that breaks real CSS
|
|
172
|
+
parsers. **Both are OUTSIDE the sections the landing uses**, so nothing needed fixing
|
|
173
|
+
this time — but anyone porting *further* sections of that mockup must check for and
|
|
174
|
+
re-apply the fix (same standing gotcha as `mockup/styles.css`, see
|
|
175
|
+
`web-funnel-app.md`).
|
|
176
|
+
- **No `<head>` resource surprises this time**, but the standing rule from the first port
|
|
177
|
+
still applies: a font named in ported CSS is not a loaded font. The landing rides
|
|
178
|
+
`layout.tsx`'s existing Plus Jakarta Sans.
|
|
179
|
+
- **`/landing` is not rate-limited.** `src/proxy.ts`'s matcher covers only `/` and the
|
|
180
|
+
five API routes, so the landing bypasses the limiter entirely. That is correct today
|
|
181
|
+
(the page is static and reads no contact data), but it stops being correct the moment
|
|
182
|
+
the page gains a form or reads a query param.
|
|
183
|
+
|
|
184
|
+
## Change history
|
|
185
|
+
- 2026-08-24 — Initial doc. BUILT the cybersecurity landing page at `/landing`, ported
|
|
186
|
+
pixel-faithfully from the new `BDR/AI BDR - Security/` mockup (its `Capabilities` screen,
|
|
187
|
+
renamed `SecurityLanding` to avoid the studio-screen collision) and made it the site's
|
|
188
|
+
main page via a temporary `/` → `/landing` 307 (see `web-funnel-app.md`). New:
|
|
189
|
+
`src/app/landing/page.tsx` (server shell + metadata), `src/flow/screens/SecurityLanding.tsx`
|
|
190
|
+
(client, carries its own page shell), `src/app/security.css`, `src/content/security.ts`
|
|
191
|
+
(all copy, `CampaignBundle`-shaped for a later graft), `LogoSymbol.tsx`,
|
|
192
|
+
`AssistantMark.tsx`. Extended `Ico.tsx` (`eyeoff`, `alert`) and `Particles.tsx`
|
|
193
|
+
(`palette`/`bold`/`radiate`, default branch verified byte-identical). DECIDED the new
|
|
194
|
+
design tokens are scoped to `.security-shell`, **not** `:root`, so the parked studio flow
|
|
195
|
+
keeps its look; peach promoted to `--peach*` tokens as a fixed brand hue that never
|
|
196
|
+
tracks `--accent`. Zero binary assets needed. Recorded that the primary CTA's Calendly
|
|
197
|
+
URL is an unverified mockup placeholder, that "Learn more" / "Ask Me Anything" are inert
|
|
198
|
+
(chat drawer not ported), and that the mobile pass is pending because the mockup has no
|
|
199
|
+
landing-specific mobile CSS. tsc + lint + build clean, `/landing` prerendered static,
|
|
200
|
+
`GET /` → 307 verified. All work uncommitted in the working tree at capture. (tcox)
|
|
201
|
+
</content>
|
|
202
|
+
</invoke>
|
|
@@ -6,10 +6,11 @@ project: AI-BDR
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
9
|
+
updated: 2026-08-24
|
|
10
10
|
owners: [tcox]
|
|
11
11
|
files:
|
|
12
12
|
- bdr/PLAN.md
|
|
13
|
+
- bdr/next.config.ts
|
|
13
14
|
- bdr/.gitignore
|
|
14
15
|
- bdr/src/server/hubspot.ts
|
|
15
16
|
- bdr/src/server/leadSink.ts
|
|
@@ -65,6 +66,7 @@ related:
|
|
|
65
66
|
- web-funnel-content-model.md
|
|
66
67
|
- bdr-web-funnel-plan.md
|
|
67
68
|
- live-call-status.md
|
|
69
|
+
- security-landing-page.md
|
|
68
70
|
- ../architecture.md
|
|
69
71
|
- ../workflows/safe-call-loop-testing.md
|
|
70
72
|
- ../../worker2/features/vapi-webhook-handler.md
|
|
@@ -76,6 +78,13 @@ related:
|
|
|
76
78
|
|
|
77
79
|
## What this is
|
|
78
80
|
|
|
81
|
+
> **READ FIRST (2026-08-24) — the funnel is currently UNREACHABLE.** `/` now
|
|
82
|
+
> **307-redirects to `/landing`**, the new cybersecurity landing page
|
|
83
|
+
> ([security-landing-page.md](security-landing-page.md)). Everything documented below is
|
|
84
|
+
> still in the repo and still correct, but **nothing in it is reachable in a browser**
|
|
85
|
+
> until the redirect is removed. See "The Agent Studio flow is parked behind a redirect"
|
|
86
|
+
> below before debugging "the funnel doesn't load."
|
|
87
|
+
|
|
79
88
|
The **built** state of the BDR web funnel — the Next.js UI / lead-capture front
|
|
80
89
|
door of the existing AI-BDR product (see `../architecture.md`). The forward-looking
|
|
81
90
|
plan lives in `bdr-web-funnel-plan.md`; the config-driven content contract lives in
|
|
@@ -558,8 +567,30 @@ up — confirm the real owner before assuming.)
|
|
|
558
567
|
follow-ups (lock the Amplify origin to CloudFront; verify `CloudFront-Viewer-Address` inject+strip
|
|
559
568
|
before trusting it).
|
|
560
569
|
|
|
570
|
+
## The Agent Studio flow is parked behind a redirect (2026-08-24)
|
|
571
|
+
|
|
572
|
+
`next.config.ts` gained a `redirects()` entry: **`/` → `/landing`, `permanent: false`**.
|
|
573
|
+
The `307` is temporary **on purpose** — the design decision is not settled, and a `308`
|
|
574
|
+
would be cached by browsers and crawlers and become painful to undo.
|
|
575
|
+
|
|
576
|
+
- **Nothing was deleted.** All 7 screens, `useAgentFlow`, every `/api/*` route handler, and
|
|
577
|
+
the lead priming in `page.tsx` remain in the repo, untouched and passing tests. Design may
|
|
578
|
+
reuse parts of the flow — **do not delete any of it.**
|
|
579
|
+
- **`page.tsx` still exists and still primes leads** — it is simply never reached, so the
|
|
580
|
+
page-prime HubSpot fetch and Toga upsert **never fire** while the redirect stands.
|
|
581
|
+
- **CONSEQUENCE for CRM links.** A campaign link of the form
|
|
582
|
+
`/?hsContactId=…&hsCampaignId=…` now lands on the **static** landing page: no phone
|
|
583
|
+
prefill, no contact lookup, **no page-prime Toga upsert, no campaign attribution**.
|
|
584
|
+
Anyone re-enabling campaign traffic must remove or rework the redirect first. (This also
|
|
585
|
+
means the whole `?hsContactId=` enumeration surface is dormant, not fixed.)
|
|
586
|
+
- **`src/proxy.ts` needed no change.** Its matcher is an exact-path allowlist covering only
|
|
587
|
+
`/` and the five API routes, so `/landing` is neither rate-limited nor rewritten. That is
|
|
588
|
+
fine for a static page — revisit if the landing ever reads a query param or gains a form.
|
|
589
|
+
|
|
561
590
|
## What is parked / not built
|
|
562
591
|
|
|
592
|
+
- **The entire Agent Studio flow (2026-08-24)** — in-repo but unreachable behind the
|
|
593
|
+
`/` → `/landing` redirect; see the section above.
|
|
563
594
|
- **Creator screen + `TweaksPanel` — deliberately NOT ported** (parked per plan
|
|
564
595
|
§9.3 / §9.7).
|
|
565
596
|
- **Content is in-repo, not HubSpot (§9.10 RESOLVED by dissolution, 2026-07-16).** The
|
|
@@ -585,6 +616,10 @@ up — confirm the real owner before assuming.)
|
|
|
585
616
|
|
|
586
617
|
## Gotchas
|
|
587
618
|
|
|
619
|
+
- **"The funnel is gone / a CRM link doesn't prefill" — check the redirect FIRST.** Since
|
|
620
|
+
2026-08-24 `/` 307s to `/landing`, so every symptom that used to mean "missing env" or
|
|
621
|
+
"rate-limit soft-degrade" can now simply mean the request never reached `page.tsx`. Probe
|
|
622
|
+
with `curl -I` on `/`: a `307` to `/landing` is the current expected behavior, not a bug.
|
|
588
623
|
- **HIGH (security + availability) — rotating the platform credentials takes BDR dark unless
|
|
589
624
|
BDR's env is updated in the SAME change.** BDR consumes two credentials that are **committed
|
|
590
625
|
literals** elsewhere in the platform: the SES SMTP settings in `_underscore/Email.php` and the
|
|
@@ -716,6 +751,20 @@ up — confirm the real owner before assuming.)
|
|
|
716
751
|
harness; pull it with `npx toga-ai`.
|
|
717
752
|
|
|
718
753
|
## Change history
|
|
754
|
+
- 2026-08-24 — **DECIDED: `/` 307-redirects to `/landing` and the whole Agent Studio flow is
|
|
755
|
+
parked.** `next.config.ts` gained `redirects()` with `permanent: false` (deliberately
|
|
756
|
+
temporary so browsers/crawlers do not cache it while design settles). The new
|
|
757
|
+
cybersecurity landing page is now the site's main page —
|
|
758
|
+
[security-landing-page.md](security-landing-page.md). Nothing was deleted: the 7 screens,
|
|
759
|
+
`useAgentFlow`, the `/api/*` handlers and `page.tsx` lead priming all remain in the repo
|
|
760
|
+
and untouched, just unreachable, and design may reuse parts of them. DISCOVERED the two
|
|
761
|
+
consequences: (1) CRM links `/?hsContactId=…` now land on the static landing, so there is
|
|
762
|
+
**no prefill, no contact lookup, and no page-prime Toga upsert or campaign attribution**
|
|
763
|
+
while the flow is parked — revisit before campaign traffic resumes; (2) `src/proxy.ts`
|
|
764
|
+
needed **no change** (its exact-path matcher covers only `/` and the five API routes), so
|
|
765
|
+
`/landing` is neither rate-limited nor rewritten. Added the triage gotcha that "the funnel
|
|
766
|
+
is gone / a link doesn't prefill" now most often means the redirect, not missing env. All
|
|
767
|
+
work uncommitted in the working tree at capture. (tcox)
|
|
719
768
|
- 2026-07-29 — Four behavior changes plus a security model. (1) **Anonymous phone entry** — the
|
|
720
769
|
`hasLead` submit-block and the `phone.missingContactNotice` copy key were **removed entirely**,
|
|
721
770
|
reversing the 2026-07-16 "Missing contact reference" behavior; the backend is deliberately
|
package/knowledge/INDEX.md
CHANGED
|
@@ -28,7 +28,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
28
28
|
- **toga2-hub** (TOGa Hub) — 2 doc(s) → [2.0/apps/toga2-hub/INDEX.md](2.0/apps/toga2-hub/INDEX.md)
|
|
29
29
|
- **talos** (TOGa IQ) — 7 doc(s) → [2.0/apps/talos/INDEX.md](2.0/apps/talos/INDEX.md)
|
|
30
30
|
- **voice-to-voice** (TOGa Voice) — 4 doc(s) → [2.0/apps/voice-to-voice/INDEX.md](2.0/apps/voice-to-voice/INDEX.md)
|
|
31
|
-
- **ai-bdr** (AI-BDR) —
|
|
31
|
+
- **ai-bdr** (AI-BDR) — 10 doc(s) → [2.0/apps/ai-bdr/INDEX.md](2.0/apps/ai-bdr/INDEX.md)
|
|
32
32
|
- **toga2-commerce** (TOGa Commerce) — 19 doc(s) → [2.0/apps/toga2-commerce/INDEX.md](2.0/apps/toga2-commerce/INDEX.md)
|
|
33
33
|
- **toga25-supply** (TOGa 2.5 Supply) — 12 doc(s) → [2.0/apps/toga25-supply/INDEX.md](2.0/apps/toga25-supply/INDEX.md)
|
|
34
34
|
- **toga-blox** (TOGa Blox) — 10 doc(s) → [2.0/apps/toga-blox/INDEX.md](2.0/apps/toga-blox/INDEX.md)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: session
|
|
3
|
+
slug: bdr-landing-update
|
|
4
|
+
title: BDR security landing page built at /landing
|
|
5
|
+
author: tcox
|
|
6
|
+
repos: [bdr]
|
|
7
|
+
framework: "2.0"
|
|
8
|
+
client: shared
|
|
9
|
+
status: active
|
|
10
|
+
created: 2026-08-24
|
|
11
|
+
updated: 2026-08-24
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Session: bdr-landing-update
|
|
15
|
+
**Date:** 2026-08-24
|
|
16
|
+
**Project/Repo:** bdr (2.0)
|
|
17
|
+
**Task:** Built the new cybersecurity-services landing page UI for the BDR web funnel (C:\WWW\BDR) from the designer mockup in `BDR/AI BDR - Security/`, served at `/landing` as the site's new main page ("/" redirects to it); Agent Studio flow parked; only the Book CTA is wired (Calendly), everything else inert pending design.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## What WORKED
|
|
22
|
+
- Two-agent porting flow: an Explore agent mapped the mockup (screens, tokens, assets, line ranges) in its own context, then a general-purpose implementer wrote all files. Evidence: `npx tsc --noEmit` clean, `npm run lint` clean (including the em-dash ban), `npm run build` clean with `/landing` prerendered static.
|
|
23
|
+
- Token scoping: all new design tokens (accent `#80A4FF`, `--radius:4px`, `--r-pill:999px`, cooler grays, `--grad-1..4`, `--peach` family) declared on `.security-shell` in `src/app/security.css`, NOT `:root`. The 7 existing studio screens are unaffected; `src/components/Particles.tsx` default branch verified line-by-line byte-identical after adding `palette`/`bold`/`radiate` props.
|
|
24
|
+
- Root redirect via `next.config.ts` `redirects()`: `/` → `/landing`, `permanent:false`. Smoke-tested on a temp prod server (port 3111): `GET /` → 307 with `Location: /landing`; `GET /landing` → 200.
|
|
25
|
+
- The landing needs ZERO binary assets — everything is inline SVG (`LogoSymbol`, `AssistantMark`, `Ico` icons) + CSS. Nothing copied to `public/`.
|
|
26
|
+
- Adding `"AI BDR - Security/**"` to `globalIgnores` in `eslint.config.mjs` (next to the existing `mockup/**`) cleared all 96 lint errors in one move.
|
|
27
|
+
- Book CTA as a real `<a class="btn btn-toga btn-lg">` to the Calendly URL (new tab, `rel="noopener noreferrer"`), with one scoped rule `.security-shell a.btn{text-decoration:none}` because studio's `.btn` never resets anchor defaults (all other .btn elements are `<button>`s).
|
|
28
|
+
- `/capture` already ran: knowledge docs `2.0/apps/ai-bdr/features/security-landing-page.md` (new) and `web-funnel-app.md` (parked-flow banner) pushed as `ef0f2e6`.
|
|
29
|
+
|
|
30
|
+
## What did NOT work — DO NOT RETRY THESE
|
|
31
|
+
- **Glob on `c:\WWW` or even on the BDR repo root times out** (ripgrep 20s timeout, huge tree/node_modules). Use Bash `ls` / `find` with explicit paths for directory listings there instead of Glob with broad patterns.
|
|
32
|
+
- **First Explore (mapping) agent died mid-run**: "API Error: Connection lost mid-response", returned near-zero partial output. A plain re-spawn with the identical prompt succeeded — retry, don't redesign the prompt.
|
|
33
|
+
- **First `npm run lint` reported 96 problems** — every one was inside the un-ignored mockup folder `AI BDR - Security/` (tweaks-panel.jsx etc.), zero in shipped code. Don't chase those errors; the ignore entry is the fix (already in place).
|
|
34
|
+
- **False corruption signal from Grep output**: Grep content mode displayed CSS comment openers as `\*` (e.g. security.css lines 135/139, studio.css 312/768/827), which looks exactly like the mockup's known literal-`\n`/`\"` corruption class. `od -c` proved the actual bytes are a normal `/*`. It's a display artifact of the search tool — do NOT "fix" these lines.
|
|
35
|
+
|
|
36
|
+
## Not tried yet (candidates for next session)
|
|
37
|
+
- **Mobile pass for the landing**: the mockup has no landing-specific mobile CSS (only the 900px hero-stack and 760px stats/matters breakpoints; its big mobile block has zero `.lp-*` rules). `.lp-value` and small-viewport typography need a deliberate pass in `src/app/security.css`.
|
|
38
|
+
- Porting the mockup's chat drawer (`ChatPanel`) — needed only if design decides "Ask Me Anything"/"Learn more" should open it.
|
|
39
|
+
- Verifying the Calendly slug `toga-technology/risk-assessment` is live (mockup comment calls it a placeholder). Outbound request — was not run.
|
|
40
|
+
- Grafting the copy module `src/content/security.ts` into the `CampaignBundle` schema (`src/content/schema.ts`) once the page becomes campaign-driven.
|
|
41
|
+
- Git: nothing committed. Branch creation needs tcox's go-ahead (team rule: ask first; ticket work uses bare ticket-ID branch names).
|
|
42
|
+
|
|
43
|
+
## Current file state
|
|
44
|
+
| File | Status | Notes |
|
|
45
|
+
|------|--------|-------|
|
|
46
|
+
| src/app/landing/page.tsx | created | Server component + metadata; folder renamed from security/; imports ../security.css |
|
|
47
|
+
| src/flow/screens/SecurityLanding.tsx | created | "use client" landing screen with own shell/header/footer; Book = anchor to Calendly; other CTAs inert |
|
|
48
|
+
| src/app/security.css | created | All styles scoped under .security-shell (tokens, btn-toga, lp-* block, 3 media queries, a.btn underline reset) |
|
|
49
|
+
| src/content/security.ts | created | Typed copy module incl. primaryCtaHref (Calendly URL) |
|
|
50
|
+
| src/components/LogoSymbol.tsx | created | Inline TOGA mark SVG, currentColor |
|
|
51
|
+
| src/components/AssistantMark.tsx | created | Talos glyph SVG, per-instance gradient id via useId |
|
|
52
|
+
| src/components/Ico.tsx | modified | Added eyeoff + alert icons (verbatim from mockup) |
|
|
53
|
+
| src/components/Particles.tsx | modified | Added palette/bold/radiate props; default branch byte-identical |
|
|
54
|
+
| eslint.config.mjs | modified | globalIgnores += "AI BDR - Security/**" |
|
|
55
|
+
| next.config.ts | modified | redirects(): / -> /landing, permanent:false (307) |
|
|
56
|
+
| src/proxy.ts | untouched | Verified: matcher covers only / and 5 API routes; /landing unaffected |
|
|
57
|
+
|
|
58
|
+
All changes are **uncommitted, working tree only** — intentional, awaiting review.
|
|
59
|
+
|
|
60
|
+
## Decisions made
|
|
61
|
+
- **Route is `/landing`, root 307-redirects to it** (developer + design). Rationale: landing is the main page but the studio flow code must survive untouched for possible reuse; a temporary 307 avoids permanent browser/crawler caching while design settles. Rejected: replacing `src/app/page.tsx` (would gut the flow entry + lead priming); `permanent:true` (308).
|
|
62
|
+
- **New tokens scoped to `.security-shell`, not global** (developer choice via AskUserQuestion). Rejected: re-tokening the whole app, which would visibly re-skin all 7 shipped studio screens (`--r-pill` 8px→999px alone changes every button).
|
|
63
|
+
- **All CTAs unwired except Book → Calendly placeholder** (design-team direction relayed by developer; earlier Book→"/" wiring was removed when design parked the flow).
|
|
64
|
+
- **Peach promoted to `--peach`/`--peach-hover`/`--peach-soft`** rather than hardcoded hexes; peach is a fixed brand hue, not the accent (mockup CLAUDE.md rule: never hardcode accent colors).
|
|
65
|
+
- **Component named `SecurityLanding`** — the mockup calls the screen `Capabilities`, which collides with the existing studio `Capabilities.tsx`. Internal names keep "security" (describes content); only the route says "landing".
|
|
66
|
+
- **Copy lives in `src/content/security.ts`**, not inline JSX and not yet in CampaignBundle — UI-first, graftable later.
|
|
67
|
+
- **KB placement**: landing doc filed under `2.0/apps/ai-bdr/` following precedent; splitting a `2.0/apps/bdr/` tree is a deliberate future (elevated) decision.
|
|
68
|
+
|
|
69
|
+
## Blockers
|
|
70
|
+
None hard. Pending external inputs: design decisions on "Learn more" / "Ask Me Anything" destinations (chat drawer?), confirmation of the real Calendly link, and the go-ahead to commit/branch.
|
|
71
|
+
|
|
72
|
+
## Exact next step
|
|
73
|
+
> Run `npm run dev` in `C:\WWW\BDR`, open `http://localhost:3000/` (should 307 to `/landing`), and visually review the page at desktop and narrow widths — then do the mobile CSS pass for the `.lp-*` block in `src/app/security.css` (the mockup ships none).
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
_Saved by /session-save on 2026-08-24_
|
package/package.json
CHANGED