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.
@@ -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) | The **built** state of the BDR web funnel — the Next.js UI / lead-capture front door of the existing AI-BDR product (see `../architecture.md`). | bdr/PLAN.md, 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
+ | [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-07-29
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
@@ -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) — 9 doc(s) → [2.0/apps/ai-bdr/INDEX.md](2.0/apps/ai-bdr/INDEX.md)
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.635",
3
+ "version": "1.0.637",
4
4
  "description": "TOGA Technology Team Claude Knowledge System — shared AI coding harness with skills, knowledge base CLI, and project installer for Claude Code.",
5
5
  "keywords": [
6
6
  "claude",