toga-ai 1.0.330 → 1.0.331
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,7 +6,7 @@ project: "AI-BDR"
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: draft
|
|
9
|
-
updated: 2026-07-
|
|
9
|
+
updated: 2026-07-14
|
|
10
10
|
owners: [tcox]
|
|
11
11
|
files:
|
|
12
12
|
- bdr/PLAN.md
|
|
@@ -16,8 +16,15 @@ files:
|
|
|
16
16
|
related:
|
|
17
17
|
- architecture.md
|
|
18
18
|
- web-funnel-content-model.md
|
|
19
|
+
- web-funnel-app.md
|
|
19
20
|
---
|
|
20
21
|
|
|
22
|
+
> **Execution status (2026-07-14):** PLAN **Phases 0–5 are BUILT and QA'd** — the web
|
|
23
|
+
> app engine, full mockup port, and real backend are done. Remaining work is
|
|
24
|
+
> decision-gated, not code (§9.10 HubSpot mechanism, leadership copy, Phase 7 polish,
|
|
25
|
+
> Phase 8 deploy). The built codebase is documented in `web-funnel-app.md`; this doc
|
|
26
|
+
> stays a plan mirror. This body still mirrors `BDR/PLAN.md`.
|
|
27
|
+
|
|
21
28
|
# BDR: Multi-Campaign "AI BDR / Agent Studio" Web App — Implementation Plan
|
|
22
29
|
|
|
23
30
|
> **Status:** Draft 2 (needs one more review). Open items tracked in §9; final campaign direction /
|
|
@@ -194,7 +201,7 @@ the bundle carries the UUID so a slug maps to the right campaign for logging.
|
|
|
194
201
|
## 4. Decisions locked at kickoff
|
|
195
202
|
| Decision | Choice | Consequence |
|
|
196
203
|
|---|---|---|
|
|
197
|
-
| Repo name | **`bdr`** |
|
|
204
|
+
| Repo name | **`bdr`** | Greenfield repo, registered in the TOGA registry (`agilantsolutions/BDR`). |
|
|
198
205
|
| Framework | **Next.js (App Router) + TypeScript** | Chosen because the site is highly public: SSR + SEO, and a built-in server for the secret-bearing HubSpot/Toga/content calls. Matches `info`, so its patterns port directly. |
|
|
199
206
|
| UI source | **The mockup** | Rebuild its Agent Studio flow faithfully (pixel-perfect). The mockup is React, so components port cleanly into Next.js client components. |
|
|
200
207
|
| Backend source | **`info`** | Reuse HubSpot/Toga/callback logic directly (same framework). |
|
|
@@ -551,5 +558,11 @@ so fidelity should be near-exact.
|
|
|
551
558
|
- [ ] Pixel-perfect parity pass against the mockup screens + screenshots.
|
|
552
559
|
|
|
553
560
|
## Change history
|
|
561
|
+
- 2026-07-14 — Phases 0–5 executed and QA'd (engine + full mockup port + real backend);
|
|
562
|
+
built codebase now documented in `web-funnel-app.md`. `BDR/PLAN.md` itself corrected:
|
|
563
|
+
absolute local paths genericized, and the stale "not yet in TOGA registry" note fixed
|
|
564
|
+
(bdr IS registered). Repo now lives at `agilantsolutions/BDR` (branch `BDR-Development`);
|
|
565
|
+
the local `.claude/` harness is gitignored (devs pull it via `npx toga-ai`). Body still
|
|
566
|
+
mirrors PLAN.md. (tcox)
|
|
554
567
|
- 2026-07-13 — Draft 2 resync: re-mirrored the body from the current `BDR/PLAN.md`. Framework locked to Next.js App Router (earlier React/Vite SPA idea dropped); content store decided HubSpot over Contentful (rationale in §4/§5.2); no-hardcoding (HubSpot-owned, fetched by slug from the start); same-product framing confirmed (front door of the existing AI-BDR backend, "backend relationship" open question resolved); meeting-specific dates/cadence removed. Still a draft. (tcox)
|
|
555
568
|
- 2026-07-08 — Captured the full BDR web-funnel implementation plan verbatim into the knowledge repo as a companion to the distilled `web-funnel-content-model.md` feature doc (redundancy intentional). (tcox)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Web Funnel — Built Next.js App (structure, stack, how to run)
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: ai-bdr
|
|
5
|
+
project: AI-BDR
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-07-14
|
|
10
|
+
owners: [tcox]
|
|
11
|
+
files:
|
|
12
|
+
- bdr/PLAN.md
|
|
13
|
+
- bdr/.gitignore
|
|
14
|
+
- bdr/eslint.config.mjs
|
|
15
|
+
- bdr/amplify.yml
|
|
16
|
+
- bdr/src/app
|
|
17
|
+
- bdr/src/lib/resolveCampaignId.ts
|
|
18
|
+
- bdr/src/content
|
|
19
|
+
- bdr/src/components
|
|
20
|
+
- bdr/src/flow
|
|
21
|
+
- bdr/src/server
|
|
22
|
+
- bdr/src/app/api
|
|
23
|
+
- bdr/test
|
|
24
|
+
- bdr/public
|
|
25
|
+
- bdr/mockup/styles.css
|
|
26
|
+
related:
|
|
27
|
+
- web-funnel-content-model.md
|
|
28
|
+
- bdr-web-funnel-plan.md
|
|
29
|
+
- ../architecture.md
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## What this is
|
|
33
|
+
|
|
34
|
+
The **built** state of the BDR web funnel — the Next.js UI / lead-capture front
|
|
35
|
+
door of the existing AI-BDR product (see `../architecture.md`). The forward-looking
|
|
36
|
+
plan lives in `bdr-web-funnel-plan.md`; the config-driven content contract lives in
|
|
37
|
+
`web-funnel-content-model.md`. **This doc covers the actual shipped codebase: the
|
|
38
|
+
stack, the directory map, what was ported vs. parked, the test suite, and the
|
|
39
|
+
decisions that are load-bearing for anyone touching the repo.**
|
|
40
|
+
|
|
41
|
+
As of this writing **PLAN Phases 0–5 are BUILT and QA'd** — the web app engine and
|
|
42
|
+
full mockup port are complete, all screens/modals render config-driven from a
|
|
43
|
+
bundle, and the real backend is wired behind adapters. Developer QA verdict: the UI
|
|
44
|
+
is "very close, minimal adjustments to be near exact" vs. the mockup. Remaining work
|
|
45
|
+
is **decision-gated, not code** (see "What is parked / not built").
|
|
46
|
+
|
|
47
|
+
- **Repo:** `agilantsolutions/BDR` on GitHub, working branch `BDR-Development`. The
|
|
48
|
+
machine-local `.claude/` harness is **gitignored** — committing it would snapshot
|
|
49
|
+
the whole KB stale; devs get the harness via `npx toga-ai`, not from this repo.
|
|
50
|
+
|
|
51
|
+
## Stack
|
|
52
|
+
|
|
53
|
+
- **Next.js 16.2.3, App Router + TypeScript**, mirroring the `info` repo's config.
|
|
54
|
+
- **No Tailwind (deliberate).** Tailwind 4's preflight reset would fight the mockup's
|
|
55
|
+
hand-authored CSS (ported verbatim as `src/app/studio.css`) and threaten pixel
|
|
56
|
+
parity. Do **not** add Tailwind to this repo — the styling is intentionally the
|
|
57
|
+
mockup's own CSS-variable system. See the styles.css escape-sequence gotcha below.
|
|
58
|
+
- **ESLint flat config** carries a **no-em-dash rule** on shipped strings
|
|
59
|
+
(`Literal` / `TemplateElement` / `JSXText` selectors) — enforces the mockup copy
|
|
60
|
+
rule on in-repo strings (`eslint.config.mjs`).
|
|
61
|
+
- **Vitest** test suite: **67 tests across 7 files, all green.** Every phase was
|
|
62
|
+
verified with `tsc` + lint + build + a live SSR `curl` before commit.
|
|
63
|
+
- **Deploy target:** AWS Amplify (SSR), `amplify.yml` present (Phase 8 not done).
|
|
64
|
+
|
|
65
|
+
## Directory map (what got built)
|
|
66
|
+
|
|
67
|
+
- `src/app/*` — App Router shell + pages; `page.tsx` is a server component that
|
|
68
|
+
resolves the campaign and primes the lead server-side (from `?hsContactId`) and
|
|
69
|
+
**never fails rendering**. `src/app/studio.css` is the mockup CSS ported verbatim.
|
|
70
|
+
- `src/lib/resolveCampaignId.ts` — campaign entry resolution: `?campaign=<slug>` →
|
|
71
|
+
`?hsCampaignId=` mapped → `DEFAULT`. Slug regex `^[a-z0-9][a-z0-9-]{0,63}$`.
|
|
72
|
+
- `src/content/*` — the content layer (schema/provider/default/hook). See
|
|
73
|
+
`web-funnel-content-model.md` for the contract; the schema is now THE contract.
|
|
74
|
+
- `src/components/*` — full mockup component library port: `Ico` (27-icon registry
|
|
75
|
+
hydrating bundle icon keys), `SwapFade`, `TalkingPreview`, `VoiceDial`, etc., with
|
|
76
|
+
the mockup's motion hardening ported **verbatim** (do not "simplify" the settle
|
|
77
|
+
guards / effect-owned timers away).
|
|
78
|
+
- `src/flow/*` — `useAgentFlow` state machine (the `go()` / `back` map, modal gates)
|
|
79
|
+
plus the screens. Persists to `localStorage` (`aibdr.v2`) where **only voice
|
|
80
|
+
survives a refresh**; the flow restarts at Welcome.
|
|
81
|
+
- `src/server/*` — the real backend, ported from `info`'s `toga.ts` / `hubspot.ts`
|
|
82
|
+
behind `LeadSink` + `CallbackService` adapters (detail in
|
|
83
|
+
`web-funnel-content-model.md`).
|
|
84
|
+
- `src/app/api/*` — route handlers `call-now`, `call-later`, `contact`.
|
|
85
|
+
- `public/*` — assets pruned to the **default campaign only** (~6.2 MB).
|
|
86
|
+
- `test/*` — the 67-test Vitest suite.
|
|
87
|
+
|
|
88
|
+
## How the built app behaves (key runtime facts)
|
|
89
|
+
|
|
90
|
+
- **Agent identity is campaign config.** AutoBuild lands on the campaign's
|
|
91
|
+
`bundle.agent`, **not** a hardcoded "Alex" — the presented agent (art, accent,
|
|
92
|
+
voice, name) comes from the resolved bundle. The manual Creator is parked, so the
|
|
93
|
+
user does not pick the agent in the default flow.
|
|
94
|
+
- **Template tokens** `<agent>` / `<date>` / `<tz>` / `<time>` / `<detail>` in bundle
|
|
95
|
+
strings are substituted at render by an `agentize()` helper.
|
|
96
|
+
- **Funnel always renders.** `resolveCampaign` never throws — an unknown slug or a
|
|
97
|
+
provider failure returns the `DEFAULT` bundle. The server page primes the lead but
|
|
98
|
+
never fails rendering on a bad/absent contact.
|
|
99
|
+
- **Boundary validation on every route handler.** 16 KB body cap; phone / UUID / ISO
|
|
100
|
+
checks; all handlers return the `{isSuccess, status, error, messages, data}`
|
|
101
|
+
envelope (same contract as `info`/Toga).
|
|
102
|
+
|
|
103
|
+
## What is parked / not built
|
|
104
|
+
|
|
105
|
+
- **Creator screen + `TweaksPanel` — deliberately NOT ported** (parked per plan
|
|
106
|
+
§9.3 / §9.7).
|
|
107
|
+
- **`hubspotProvider` is a throwing stub**, gated on the §9.10 HubSpot content-
|
|
108
|
+
modeling decision. Until HubSpot is seeded, `DEFAULT_BUNDLE` carries the mockup's
|
|
109
|
+
copy verbatim as documented **interim dev content**; it slims to a bare
|
|
110
|
+
engineering fallback once HubSpot is seeded.
|
|
111
|
+
- **`info`'s dead 501 `visit` route was dropped** on purpose (attack surface, no
|
|
112
|
+
caller).
|
|
113
|
+
- **Remaining work is decision-gated, not code:** §9.10 HubSpot content mechanism
|
|
114
|
+
(HubDB likely — gates the provider + campaign seeding, Phase 6); leadership's
|
|
115
|
+
first-campaign copy; Phase 7 pixel/GA4/accessibility polish; Phase 8 Amplify SSR +
|
|
116
|
+
`togatech` integration.
|
|
117
|
+
|
|
118
|
+
## Gotchas
|
|
119
|
+
|
|
120
|
+
- **The mockup's `mockup/styles.css` contains literal `\n` and `\"` escape sequences**
|
|
121
|
+
(JS-string generation artifacts, around lines ~759 / ~840) that break real CSS
|
|
122
|
+
parsers. This was **fixed in the ported `src/app/studio.css`**, but
|
|
123
|
+
`mockup/styles.css` was intentionally left pristine — so **anyone re-porting the
|
|
124
|
+
mockup CSS must re-apply this fix.**
|
|
125
|
+
- **No PII in logs.** All of `info`'s PII-logging was stripped on port (identifier-
|
|
126
|
+
only logs); the Toga error paths **strip query strings** because the contact
|
|
127
|
+
lookup carries the email in the query. Do not reintroduce value logging.
|
|
128
|
+
- **No Tailwind** — see Stack. The mockup CSS is the styling system; adding Tailwind
|
|
129
|
+
risks pixel parity.
|
|
130
|
+
- **`.claude/` is gitignored** in the BDR repo on purpose — do not commit the
|
|
131
|
+
harness; pull it with `npx toga-ai`.
|
|
132
|
+
|
|
133
|
+
## Change history
|
|
134
|
+
- 2026-07-14 — Initial doc: recorded the BUILT state of the BDR web funnel (PLAN
|
|
135
|
+
Phases 0–5 executed + QA'd). Next.js 16.2.3 App Router/TS, deliberate no-Tailwind,
|
|
136
|
+
ESLint no-em-dash rule, `resolveCampaignId`, full mockup component/flow port
|
|
137
|
+
(`useAgentFlow`, Ico registry, motion hardening verbatim), agent identity as
|
|
138
|
+
campaign config, real backend behind LeadSink/CallbackService with PII logging
|
|
139
|
+
stripped and boundary-validated route handlers, 67 green Vitest tests. Recorded the
|
|
140
|
+
parked items (Creator/TweaksPanel, throwing hubspotProvider, dropped `visit` route)
|
|
141
|
+
and the `mockup/styles.css` escape-sequence re-port gotcha. (tcox)
|
|
142
|
+
</content>
|
|
143
|
+
</invoke>
|
|
@@ -6,22 +6,31 @@ project: AI-BDR
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: draft
|
|
9
|
-
updated: 2026-07-
|
|
9
|
+
updated: 2026-07-14
|
|
10
10
|
owners: [tcox]
|
|
11
11
|
files:
|
|
12
12
|
- bdr/src/content/schema.ts
|
|
13
13
|
- bdr/src/content/hubspotProvider.ts
|
|
14
14
|
- bdr/src/content/useCampaign.ts
|
|
15
15
|
- bdr/src/content/default.ts
|
|
16
|
+
- bdr/src/lib/resolveCampaignId.ts
|
|
16
17
|
- bdr/src/server/leadSink.ts
|
|
17
18
|
- bdr/src/server/callbackService.ts
|
|
18
19
|
- bdr/src/app/api/call-now/route.ts
|
|
19
20
|
- bdr/src/app/api/call-later/route.ts
|
|
21
|
+
- bdr/src/app/api/contact/route.ts
|
|
20
22
|
related:
|
|
21
23
|
- ../architecture.md
|
|
22
24
|
- call-orchestration.md
|
|
25
|
+
- web-funnel-app.md
|
|
23
26
|
---
|
|
24
27
|
|
|
28
|
+
> **Status note:** the content **contract** below (schema, provider seam, adapters)
|
|
29
|
+
> is now BUILT and QA'd (PLAN Phases 0–5). The built codebase — structure, stack,
|
|
30
|
+
> how to run — is documented in `web-funnel-app.md`. The one part still **not** built
|
|
31
|
+
> is the HubSpot content *sourcing* (`hubspotProvider` is a throwing stub gated on the
|
|
32
|
+
> §9.10 mechanism decision), which is why this doc stays `draft`.
|
|
33
|
+
|
|
25
34
|
## What this is
|
|
26
35
|
|
|
27
36
|
The **public-facing web funnel** is the new UI / lead-capture front door of the **same
|
|
@@ -100,6 +109,24 @@ optional `build` (AutoBuild beats), `analytics`, and `features[]` capability fla
|
|
|
100
109
|
`RichLine` supports the accent-inked span the mockup uses (e.g. `"<agent> is ready to
|
|
101
110
|
work."`). The mapping layer is the seam between HubSpot storage and this contract.
|
|
102
111
|
|
|
112
|
+
**Schema calibrated by building (the §6 plan sketch was a sketch; `src/content/schema.ts`
|
|
113
|
+
is now THE contract).** Additions made while building the real screens: `chrome`
|
|
114
|
+
(wordmark / rail labels); capabilities `eyebrows` + qbank strings + `howLink`;
|
|
115
|
+
`connectNote` split to `{label, value}`; `earlyAccess` / `phone` / `recap` groups;
|
|
116
|
+
`build` made **required**. Bundle template tokens `<agent>` / `<date>` / `<tz>` /
|
|
117
|
+
`<time>` / `<detail>` are substituted **at render** by an `agentize()` helper (they are
|
|
118
|
+
plain strings in the bundle, so HubSpot only ever stores strings).
|
|
119
|
+
|
|
120
|
+
**`resolveCampaign` never throws** (built): an unknown slug or a provider failure
|
|
121
|
+
returns the `DEFAULT` bundle, so the funnel always renders. Entry resolution lives in
|
|
122
|
+
`src/lib/resolveCampaignId.ts` (`?campaign=<slug>` → mapped `?hsCampaignId=` →
|
|
123
|
+
`DEFAULT`; slug regex `^[a-z0-9][a-z0-9-]{0,63}$`).
|
|
124
|
+
|
|
125
|
+
**`hubspotProvider` is a throwing stub** explicitly gated on the §9.10 HubSpot-modeling
|
|
126
|
+
decision — it is not wired yet. Until HubSpot is seeded, **`DEFAULT_BUNDLE` carries the
|
|
127
|
+
mockup's copy verbatim as documented interim dev content**; once HubSpot is seeded it
|
|
128
|
+
slims to a bare engineering safety-net fallback (not authored marketing copy).
|
|
129
|
+
|
|
103
130
|
## Backend reuse (from the `info` repo; existing AI-BDR calls)
|
|
104
131
|
|
|
105
132
|
The funnel's Call Now / Schedule screens submit to a real backend **ported from the
|
|
@@ -118,6 +145,16 @@ so only the impl changes later:
|
|
|
118
145
|
- `CallbackService.requestCall(ref, whenOrNow, phone)` → Toga `requestCall`, immediate vs.
|
|
119
146
|
scheduled mapped to `CONTACT_CALL_TYPE_UUID`.
|
|
120
147
|
|
|
148
|
+
**Built (PLAN Phase 5):** `info`'s `toga.ts` / `hubspot.ts` are ported into `src/server/`
|
|
149
|
+
behind those adapters with **all of `info`'s PII logging stripped** (identifier-only
|
|
150
|
+
logs; the Toga error paths **strip query strings** because the contact lookup carries
|
|
151
|
+
the email in the query). Route handlers `/api/call-now`, `/api/call-later`, `/api/contact`
|
|
152
|
+
**validate at the boundary** (16 KB body cap; phone / uuid / ISO checks) and always
|
|
153
|
+
return the `{isSuccess, status, error, messages, data}` envelope. The page primes the
|
|
154
|
+
lead server-side from `?hsContactId` and never fails rendering. `info`'s dead 501
|
|
155
|
+
`visit` route was deliberately dropped (attack surface, no caller). Verified by 67 green
|
|
156
|
+
Vitest tests. See `web-funnel-app.md` for the full built structure.
|
|
157
|
+
|
|
121
158
|
Note on "campaign": `info` uses HubSpot **only to fetch the contact**; the URL's
|
|
122
159
|
`hsCampaignId` is passed to Toga as the attribution campaign UUID
|
|
123
160
|
(`addContactToCampaign`) — attribution-only in `info`. **Fetching marketing content by
|
|
@@ -158,6 +195,16 @@ right campaign for logging.
|
|
|
158
195
|
`var(--accent)` (+ derived `--accent-fill`); never hardcode an accent value.
|
|
159
196
|
|
|
160
197
|
## Change history
|
|
198
|
+
- 2026-07-14 — Content contract BUILT + QA'd (PLAN Phases 0–5): schema calibrated by
|
|
199
|
+
building the real screens (`src/content/schema.ts` is now THE contract — chrome,
|
|
200
|
+
capabilities eyebrows/qbank/howLink, `connectNote` {label,value}, earlyAccess/phone/
|
|
201
|
+
recap groups, `build` required, `agentize()` token substitution); `resolveCampaign`
|
|
202
|
+
never throws (unknown slug/provider failure → DEFAULT); `hubspotProvider` is a throwing
|
|
203
|
+
stub gated on §9.10; `DEFAULT_BUNDLE` carries the mockup copy as interim dev content.
|
|
204
|
+
Backend ported from `info` behind LeadSink/CallbackService with PII logging stripped,
|
|
205
|
+
boundary-validated route handlers, dead `visit` route dropped; 67 green Vitest tests.
|
|
206
|
+
Built structure split out to `web-funnel-app.md`. Kept `draft` because HubSpot content
|
|
207
|
+
sourcing (§9.10) is still open. (tcox)
|
|
161
208
|
- 2026-07-13 — Draft 2 resync to the current plan: framework locked to Next.js App Router
|
|
162
209
|
(earlier React/Vite SPA idea dropped); recorded the **HubSpot-over-Contentful** content-store
|
|
163
210
|
decision + rationale (marketing already in HubSpot, campaign model already exists, trivial
|
package/package.json
CHANGED