@gymmymac/bob-widget 3.1.10 β†’ 3.1.20

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.
@@ -1,6 +1,6 @@
1
1
  # Bob Widget - Complete Documentation
2
2
 
3
- > **Version:** 3.1.10 | **Last Updated:** January 2025
3
+ > **Version:** 3.1.19 | **Last Updated:** February 2026
4
4
 
5
5
  AI-powered automotive parts assistant widget for seamless integration into partner websites.
6
6
 
@@ -26,11 +26,12 @@ AI-powered automotive parts assistant widget for seamless integration into partn
26
26
 
27
27
  Bob is a friendly Kiwi auto parts expert that helps customers find the right parts for their vehicles through natural conversation. The widget is designed as a **"black box"** that auto-configures from the databaseβ€”partners only need to provide a partner code.
28
28
 
29
- ### Key Features (v3.1.10)
29
+ ### Key Features (v3.1.19)
30
30
 
31
31
  | Feature | Description |
32
32
  |---------|-------------|
33
33
  | **CLI Installer** | 3-stage installation via `npx @gymmymac/bob-widget carfix stage-a\|b\|c` |
34
+ | **`--with-layout` Flag** | Stage B can generate CARFIX Header (72px) and BottomNav (72px) components |
34
35
  | **BobStandalone** | Auto-configures from database - 4 lines to integrate |
35
36
  | **No Hardcoded Blur** | Background uses CSS variable `--bob-blur-intensity` (default: 0) |
36
37
  | **Partner Config System** | All settings stored in `bob_partners` table |
@@ -733,6 +734,35 @@ Before proceeding to Stage B, confirm:
733
734
 
734
735
  Create the blank page that will host Bob. **Do NOT import Bob yet** - that happens in Stage C.
735
736
 
737
+ #### CARFIX Layout Components (Required)
738
+
739
+ Before creating the Bob container, ensure your CARFIX application has:
740
+
741
+ 1. **Fixed Header (72px)** - Fixed to top of viewport
742
+ 2. **Fixed Bottom Navigation (72px)** - Fixed to bottom of viewport
743
+
744
+ **If these elements do NOT exist**, you must create them first. The 144px height offset
745
+ in the container formula ASSUMES both elements are present.
746
+
747
+ ##### Option A: Use Existing Layout
748
+
749
+ If your CARFIX app already has a header and bottom nav, confirm their heights:
750
+ - Header: Must be exactly 72px
751
+ - Bottom Nav: Must be exactly 72px (plus safe-area-inset-bottom on mobile)
752
+
753
+ ##### Option B: Generate Layout Components
754
+
755
+ Run Stage B with the `--with-layout` flag to generate placeholder components:
756
+
757
+ ```bash
758
+ npx @gymmymac/bob-widget carfix stage-b --target next-pages --with-layout
759
+ ```
760
+
761
+ This generates:
762
+ - `components/CarfixHeader.tsx` (72px header)
763
+ - `components/CarfixBottomNav.tsx` (72px bottom nav)
764
+ - `pages/ask-bob.tsx` (complete page with layout)
765
+
736
766
  #### Requirements
737
767
 
738
768
  1. Page must use the standard CARFIX layout (Header + Bottom Navigation)
package/CHANGELOG.md CHANGED
@@ -5,6 +5,114 @@ All notable changes to the `@gymmymac/bob-widget` package will be documented in
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.1.20] - 2026-02-13
9
+
10
+ ### Added
11
+ - πŸ“¦ **CARFIX Installation Brief**: README.md now serves as the comprehensive installation document with full container preparation requirements, anti-patterns table, pre-mount checklist, and layout diagram
12
+ - πŸ§ͺ **Quality Baseline Tests**: 36 unit tests locked in across rear brake filter, bundle discount pricing, and callback stability
13
+ - πŸ’° **Bundle Discount Display**: Was/Now pricing with savings badges for service package tiers when `savingsAmount > 0`
14
+ - πŸ›’ **Bundle Cart Metadata**: Cart items from service packages now include `is_bundle_item`, `bundle_discount_percentage`, `service_package_name`, and `quality_tier`
15
+
16
+ ### Changed
17
+ - πŸ“– **README Overhaul**: Full installation brief is now front-and-center β€” visible on npm, GitHub, and in `node_modules`
18
+ - πŸ“ **Container Anti-Patterns**: Documented all prohibited CSS properties (`overflow: hidden`, `transform`, etc.) that break Bob's layering
19
+
20
+ ---
21
+
22
+ ## [3.1.19] - 2026-02-04
23
+
24
+ ### Added
25
+ - πŸš— **Vehicle Variant Deduplication**: Smart filtering removes duplicate vehicle variants based on parts-relevant specs (fuel type, engine capacity, power output) rather than superficial trim differences
26
+ - πŸ—£οΈ **REGO Terminology Alignment**: Bob now treats "registration", "rego", "plate", and "number plate" identically
27
+
28
+ ### Fixed
29
+ - πŸ”’ **Speech Count Alignment**: Bob's spoken variant count now matches the deduplicated UI cards shown on screen
30
+ - 🎴 **Variant Card Display**: Cards now show specs-first format without characterization text
31
+
32
+ ### Documentation
33
+ - πŸ“ **bottomOffset Clarification**: `bottomOffset` prop only applies to fixed-position variants. Contained/embedded variants position relative to their container (which should already be sized to fit between header/footer).
34
+
35
+ ---
36
+
37
+ ## [3.1.18] - 2026-01-28
38
+
39
+ ### Changed
40
+ - πŸ—£οΈ **Language Consistency**: Replaced all "CFX" references with "CARFIX" in:
41
+ - Database prompts (sales_flow)
42
+ - Edge function tool descriptions
43
+ - Service package descriptions in carfix-tokens.ts
44
+ - πŸ’¬ **Bob's Recommendations**: Bob now verbally recommends "CARFIX Value" tier (was "Standard")
45
+ - 🎨 **Button Styling**:
46
+ - CARFIX Value tier: Solid green (#22C55E) button with white text
47
+ - Other tiers: Light background with green text
48
+ - Removed cart icons from all Add buttons
49
+ - 🏷️ **Badge Update**: "RECOMMENDED" pill renamed to "CARFIX VALUE"
50
+
51
+ ---
52
+
53
+ ## [3.1.17] - 2026-01-28
54
+
55
+ ### Changed
56
+ - 🏷️ **Shelf Header**: Replaced "Bob's Shelf" with vehicle make/model (e.g., "Toyota RAV4")
57
+ - πŸ—‘οΈ **Service Packs Label**: Removed "CFX SERVICE PACKS" row to reclaim vertical space
58
+ - 🎨 **Recommended Badge**: Changed green "Recommended" pill to blue "Carfix Value"
59
+ - πŸ›’ **Add Buttons**: Removed cart icons, centered button text
60
+ - πŸ”˜ **Chevron Handle**: Larger handle button (32px) positioned higher (-24px) to prevent clipping
61
+ - πŸ“ **Chat Height**: Increased collapsed drawer from 90px to 110px for PTT button visibility
62
+
63
+ ---
64
+
65
+ ## [3.1.16] - 2026-01-28
66
+
67
+ ## [3.1.15] - 2026-01-28
68
+
69
+ ### Fixed
70
+ - πŸ—£οΈ **State Terminology**: Default animation states updated to match V2 Bob:
71
+ - "talking" (was "talk")
72
+ - "researching" (was "research")
73
+ - "listening" (was "talk_pause")
74
+ - "idle" for complete state (was "complete")
75
+ - πŸ“ **Chat Drawer Position**: Chat drawer now positioned at `bottom: 0` to sit below the counter overlay visually
76
+ - πŸ–ΌοΈ **Counter Stretching**: Counter overlay now uses `object-fit: fill` to stretch to configured height
77
+ - πŸ“ **Chat Height**: Increased collapsed chat drawer height from 70px to 90px
78
+
79
+ ---
80
+
81
+ ## [3.1.14] - 2026-01-28
82
+
83
+ ### Fixed
84
+ - πŸ“ **ContainedChatDrawer Positioning**: Removed incorrect `bottomOffset` addition - container already accounts for host UI
85
+ - 🎨 **Chat Drawer Height**: Chat drawer now correctly positions at `counterHeightPercent%` from container bottom
86
+ - πŸ“ **Counter Overlay**: Single counter display verified (backdrop + overlay are separate layers)
87
+
88
+ ---
89
+
90
+ ## [3.1.13] - 2026-01-28
91
+
92
+ ### Fixed
93
+ - πŸ“ **Chat Drawer Positioning**: Chat drawer now positions above counter overlay using `counterHeightPercent`
94
+ - 🎨 **Visual Alignment**: Chat input and PTT button no longer overlap with counter graphic
95
+
96
+ ---
97
+
98
+ ## [3.1.12] - 2026-01-28
99
+
100
+ ### Fixed
101
+ - 🎨 **Chat Drawer Z-Index**: Raised chat drawer z-index above counter overlay (z-80) to ensure visibility
102
+ - 🎀 **PTT Button Layering**: Elevated PTT button and handle button z-index for proper layer hierarchy
103
+
104
+ ---
105
+
106
+ ## [3.1.11] - 2026-01-28
107
+
108
+ ### Added
109
+ - πŸ“ **Stage B `--with-layout` Flag**: New CLI option generates CARFIX Header (72px) and Bottom Navigation (72px) components
110
+ - πŸ“– **CARFIX Layout Components Section**: Documentation now explicitly provides Header and BottomNav code templates
111
+ - πŸ§ͺ **Demo Route `/ask-bob`**: Added test route to demo repo with mock CARFIX layout for accurate local testing
112
+
113
+ ### Fixed
114
+ - πŸ“– **Stage B Instructions**: Now include explicit layout component requirements instead of assuming they exist
115
+
8
116
  ## [3.1.10] - 2026-01-28
9
117
 
10
118
  ### Added
package/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  # @gymmymac/bob-widget
2
2
 
3
- AI-powered automotive parts assistant widget for integration into partner websites.
3
+ AI-powered automotive parts assistant widget for partner websites.
4
4
 
5
- **Current Version:** 3.1.10
5
+ **Current Version:** 3.1.20 | **36 unit tests** | **8+ E2E scenarios** | Production-ready
6
6
 
7
7
  ---
8
8
 
9
- ## 🚨 STOP - RUN THE INSTALLER FIRST
9
+ ## 🚨 STOP β€” RUN THE INSTALLER FIRST
10
10
 
11
- Bob v3.1.10 includes an **executable 3-stage installer**. Do NOT skip this step.
11
+ Bob v3.1.19 includes an **executable 3-stage installer**. Do NOT skip this step.
12
12
 
13
13
  ```bash
14
14
  # Stage A: Forensic Scan & Purge (removes old Bob code)
@@ -21,62 +21,460 @@ npx @gymmymac/bob-widget carfix stage-b --target next-pages --output pages/ask-b
21
21
  npx @gymmymac/bob-widget carfix stage-c --partner CARFIX
22
22
  ```
23
23
 
24
- ### πŸ“– Required Reading
24
+ ---
25
25
 
26
- | Document | Description |
27
- |----------|-------------|
28
- | **[BOB-DOCUMENTATION.md](./BOB-DOCUMENTATION.md)** | **Complete integration guide** - Contains CARFIX-specific installation steps, container height calculations, and verification tests. **START HERE.** |
29
- | **[CHANGELOG.md](./CHANGELOG.md)** | Version history and release notes |
30
- | **[install/carfix/](./install/carfix/)** | Installer scripts and templates |
26
+ ## 1. Peer Dependencies
31
27
 
32
- ### ⚠️ Critical Installation Notes
28
+ ```json
29
+ {
30
+ "peerDependencies": {
31
+ "react": "^18.0.0",
32
+ "react-dom": "^18.0.0"
33
+ }
34
+ }
35
+ ```
33
36
 
34
- 1. **3-Stage Installation Process**: Bob v3.1.10 requires a strict 3-stage installation via CLI. See the commands above.
35
- 2. **Container Height**: Bob requires `height: calc(100dvh - 144px - env(safe-area-inset-bottom, 0px))` for CARFIX header/footer
36
- 3. **HTTPS Required**: Push-to-Talk (PTT) requires HTTPS - will be disabled on HTTP connections
37
- 4. **No Background Blur**: v3.1.10 removes hardcoded blur - background is crisp by default
37
+ > `@supabase/supabase-js` and `@tanstack/react-query` are bundled β€” no action needed.
38
+ > If CARFIX already uses `@tanstack/react-query`, ensure v5+ compatibility.
38
39
 
39
40
  ---
40
41
 
41
- ## Quick Start
42
-
43
- After completing the 3-stage installation:
42
+ ## 2. Minimal Integration (4 Lines)
44
43
 
45
44
  ```tsx
46
45
  import { BobStandalone } from '@gymmymac/bob-widget';
47
46
 
48
- <BobStandalone
49
- partner="CARFIX"
50
- sessionToken={sessionToken}
51
- onAddToCart={(item) => addToCart(item)}
52
- onNavigate={(url) => router.push(url)}
53
- onCheckout={(url) => window.location.href = url}
54
- />
47
+ function AskBobPage() {
48
+ const router = useRouter();
49
+ const sessionToken = router.query.session as string;
50
+
51
+ return (
52
+ <div style={{
53
+ height: 'calc(100dvh - 144px - env(safe-area-inset-bottom, 0px))',
54
+ position: 'relative',
55
+ /* DO NOT use overflow: hidden β€” clips PTT button and chat drawer */
56
+ }}>
57
+ <BobStandalone
58
+ partner="CARFIX"
59
+ sessionToken={sessionToken}
60
+ bottomOffset={0}
61
+ zIndexBase={100}
62
+ onAddToCart={async (item) => await carfixCart.add(item)}
63
+ onNavigate={(url) => router.push(url)}
64
+ onCheckout={(checkoutUrl) => window.location.href = checkoutUrl}
65
+ onError={(error) => console.error('[Bob Error]', error)}
66
+ />
67
+ </div>
68
+ );
69
+ }
70
+ ```
71
+
72
+ > **Auto-configuration:** `partner="CARFIX"` loads all API URLs, credentials, layout defaults, and feature flags from the `bob_partners` database table. No manual config needed.
73
+
74
+ ---
75
+
76
+ ## 3. CARFIX API Configuration (Already in Database)
77
+
78
+ ```json
79
+ {
80
+ "baseUrl": "https://flpzjbasdsfwoeruyxgp.supabase.co/functions/v1",
81
+ "apiKey": "(anon key β€” auto-loaded)",
82
+ "partnerCode": "CARFIX"
83
+ }
84
+ ```
85
+
86
+ ### Available Endpoints
87
+
88
+ | Endpoint | Purpose |
89
+ |---|---|
90
+ | `partner-api` | Session creation, cart, user context, orders |
91
+ | `calculate-service-bundles` | Service packs with `preparedTiers[]` (incl. bundle discounts) |
92
+ | `retrieve-vehicle-info` | NZ rego lookup |
93
+ | `retrieve-parts` | Vehicle parts by category |
94
+
95
+ ---
96
+
97
+ ## 4. Host Container Preparation (MANDATORY)
98
+
99
+ > ⚠️ **Bob will not render correctly if the host container is misconfigured.** Complete ALL items below before mounting `<BobStandalone>`.
100
+
101
+ ### 4.1 Container Requirements
102
+
103
+ The CARFIX page that hosts Bob **must** provide a container element with these exact properties:
104
+
105
+ ```css
106
+ /* The Bob container β€” EVERY property is required */
107
+ .bob-container {
108
+ height: calc(100dvh - 144px - env(safe-area-inset-bottom, 0px));
109
+ position: relative;
110
+ width: 100%;
111
+
112
+ /* ❌ PROHIBITED β€” these WILL break Bob */
113
+ /* overflow: hidden; ← Clips PTT button, chat drawer, and expand handle */
114
+ /* overflow: clip; ← Same issue on WebKit */
115
+ /* overflow: auto; ← Creates nested scroll context, breaks shelf scrolling */
116
+ /* overflow: scroll; ← Same as above */
117
+ /* transform: ...; ← Creates new stacking context, breaks z-index layering */
118
+ }
119
+ ```
120
+
121
+ ```tsx
122
+ // βœ… Correct JSX
123
+ <div style={{
124
+ height: 'calc(100dvh - 144px - env(safe-area-inset-bottom, 0px))',
125
+ position: 'relative',
126
+ width: '100%',
127
+ }}>
128
+ <BobStandalone partner="CARFIX" ... />
129
+ </div>
130
+
131
+ // ❌ WRONG β€” overflow hidden clips Bob's interactive elements
132
+ <div style={{ height: '100%', overflow: 'hidden' }}>
133
+ <BobStandalone partner="CARFIX" ... />
134
+ </div>
135
+ ```
136
+
137
+ ### 4.2 Height Calculation Breakdown
138
+
139
+ | Component | Height | Notes |
140
+ |---|---|---|
141
+ | CARFIX Header | 72px | `position: fixed; top: 0; z-index: 40` |
142
+ | CARFIX Bottom Nav | 72px | `position: fixed; bottom: 0; z-index: 30` |
143
+ | **Total chrome** | **144px** | Subtracted from viewport |
144
+ | Safe area inset | Variable | For notched devices (iPhone, etc.) |
145
+ | **Bob container** | `100dvh - 144px - safe-area` | Everything between header and nav |
146
+
147
+ ### 4.3 Header & Bottom Nav Requirements
148
+
149
+ Bob's UI layers (chat drawer at z-130, PTT at z-145) must sit **above** CARFIX navigation:
150
+
151
+ ```css
152
+ /* CARFIX Header */
153
+ .carfix-header {
154
+ position: fixed;
155
+ top: 0;
156
+ left: 0;
157
+ right: 0;
158
+ height: 72px;
159
+ z-index: 40; /* Bob uses zIndexBase=100, so Bob layers above this */
160
+ }
161
+
162
+ /* CARFIX Bottom Nav */
163
+ .carfix-bottom-nav {
164
+ position: fixed;
165
+ bottom: 0;
166
+ left: 0;
167
+ right: 0;
168
+ height: 72px;
169
+ z-index: 30; /* Must be BELOW Bob's z-base of 100 */
170
+ }
171
+ ```
172
+
173
+ > **If your header or nav use `z-index: 50` or higher**, increase Bob's `zIndexBase` prop accordingly (e.g., `zIndexBase={150}`).
174
+
175
+ ### 4.4 Container Anti-Patterns (WILL CAUSE BUGS)
176
+
177
+ | ❌ Don't Do This | Why It Breaks |
178
+ |---|---|
179
+ | `overflow: hidden` on container | Clips PTT button, chat drawer, and expand handle |
180
+ | `overflow: auto/scroll` on container | Creates nested scroll context β€” product shelf scroll breaks |
181
+ | `transform` on container or ancestors | Creates new stacking context β€” z-index layering fails |
182
+ | `isolation: isolate` on container | Same stacking context issue (Bob manages its own isolation) |
183
+ | Container height as `%` without parent height | Bob collapses to 0px |
184
+ | Missing `position: relative` | Absolutely-positioned Bob layers escape the container |
185
+ | Wrapping Bob in a scrollable parent | Bob has its own scroll management β€” nesting causes conflicts |
186
+
187
+ ### 4.5 Pre-Mount Checklist
188
+
189
+ Before writing any integration code, verify:
190
+
191
+ ```
192
+ β–‘ Header is position: fixed, 72px tall, z-index ≀ 49
193
+ β–‘ Bottom nav is position: fixed, 72px tall, z-index ≀ 49
194
+ β–‘ Bob container uses calc(100dvh - 144px - env(safe-area-inset-bottom, 0px))
195
+ β–‘ Bob container has position: relative
196
+ β–‘ Bob container has NO overflow property set
197
+ β–‘ Bob container has NO transform property set
198
+ β–‘ No ancestor element between <body> and Bob container has overflow: hidden
199
+ β–‘ No ancestor element has a transform that creates a stacking context
200
+ β–‘ Container renders at correct height (inspect element in DevTools)
201
+ β–‘ HTTPS is enabled (required for Push-to-Talk microphone access)
202
+ ```
203
+
204
+ ---
205
+
206
+ ### 4.6 Layout Diagram
207
+
208
+ ```
209
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
210
+ β”‚ CARFIX Header (72px, z-40) β”‚ ← position: fixed; top: 0
211
+ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
212
+ β”‚ β”‚
213
+ β”‚ Bob Container β”‚ ← position: relative
214
+ β”‚ height: calc(100dvh - 144px β”‚ NO overflow property
215
+ β”‚ - safe-area-inset) β”‚ NO transform property
216
+ β”‚ β”‚
217
+ β”‚ β”Œβ”€ Bob Internal Layers ───┐ β”‚
218
+ β”‚ β”‚ PTT Button z-145 β”‚ β”‚
219
+ β”‚ β”‚ Chat Drawer z-130 β”‚ β”‚
220
+ β”‚ β”‚ Counter Overlay z-70 β”‚ β”‚
221
+ β”‚ β”‚ Bob Character z-60 β”‚ β”‚
222
+ β”‚ β”‚ Product Shelf z-55 β”‚ β”‚
223
+ β”‚ β”‚ Backdrop z-10 β”‚ β”‚
224
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
225
+ β”‚ β”‚
226
+ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
227
+ β”‚ Bottom Nav (72px, z-30) β”‚ ← position: fixed; bottom: 0
228
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
229
+ ```
230
+
231
+ **Bob's internal z-index stack (relative to `zIndexBase={100}`):**
232
+
233
+ | Layer | z-index |
234
+ |---|---|
235
+ | Chat PTT Button | 145 |
236
+ | Chat Drawer | 130 |
237
+ | Counter Overlay | 70 |
238
+ | Bob Character | 60 |
239
+ | Product Shelf | 55 |
240
+ | Backdrop | 10 |
241
+
242
+ ---
243
+
244
+ ## 5. Callback Signatures
245
+
246
+ ### onAddToCart
247
+
248
+ ```typescript
249
+ onAddToCart: (item: {
250
+ product_id: string;
251
+ product_name: string;
252
+ quantity: number;
253
+ unit_price: number; // Final price (discount already applied for bundle items)
254
+ sku?: string;
255
+ brand?: string;
256
+ image_url?: string;
257
+ vehicle_id?: string;
258
+ // Bundle metadata (present when item is part of a service package)
259
+ is_bundle_item?: boolean;
260
+ bundle_discount_percentage?: number;
261
+ service_package_name?: string;
262
+ service_package_id?: string;
263
+ quality_tier?: string; // "Economy" | "Standard" | "Premium" | "Performance"
264
+ }) => Promise<void> | void;
265
+ ```
266
+
267
+ ### onNavigate
268
+
269
+ ```typescript
270
+ onNavigate: (url: string) => void;
271
+ // Example urls: "/product/SKU123", "/checkout"
272
+ ```
273
+
274
+ ### onCheckout
275
+
276
+ ```typescript
277
+ onCheckout: (checkoutUrl: string) => void;
278
+ // checkoutUrl is a full Stripe payment URL
279
+ ```
280
+
281
+ ### onError
282
+
283
+ ```typescript
284
+ onError: (error: Error) => void;
285
+ // Bob shows toast by default β€” this is for host-side logging
286
+ ```
287
+
288
+ ---
289
+
290
+ ## 6. Bundle Discount Fields (NEW)
291
+
292
+ The `calculate-service-bundles` API returns these fields per `PreparedTier`:
293
+
294
+ ```typescript
295
+ interface PreparedTier {
296
+ tierName: string; // "Economy" | "Standard" | "Premium" | "Performance"
297
+ displayName: string;
298
+ description: string;
299
+ isRecommended: boolean; // true = CARFIX Value tier
300
+ isHidden: boolean; // true = filter out (duplicate price)
301
+
302
+ // Pricing (pre-calculated by API β€” never recompute)
303
+ totalPrice: number; // Discounted bundle price
304
+ originalTotalPrice?: number; // Full price before discount
305
+ savingsAmount?: number; // Dollar savings
306
+ bundleDiscountPercentage?: number; // Discount % (0–50)
307
+
308
+ productCount: number;
309
+ dominantBrand: string | null;
310
+ brands: PreparedTierBrand[];
311
+ products: PreparedTierProduct[];
312
+ }
313
+
314
+ interface PreparedTierProduct {
315
+ partslotId: number;
316
+ partslotName: string; // "BRAKE PADS FRONT"
317
+ sku: string;
318
+ name: string;
319
+ brand: string;
320
+ brandFullName: string;
321
+ brandImageUrl: string; // Full URL β€” use directly in <img>
322
+ productImageUrl: string; // Full URL β€” use directly in <img>
323
+ price: number; // Legacy unit price
324
+ unitPrice: number; // Per-unit price
325
+ displayPrice: number; // Total (unitPrice Γ— perCarQty) β€” USE THIS
326
+ isRotor: boolean; // Show "[Pair]" badge
327
+ isMultiQty: boolean; // Show quantity breakdown (e.g. spark plugs)
328
+ perCarQty: number;
329
+ partNumber: string | null;
330
+ webDescription: string | null;
331
+ viscosity: string | null;
332
+ volume: number | null;
333
+ }
334
+
335
+ interface PreparedTierBrand {
336
+ name: string;
337
+ fullName: string;
338
+ imageUrl: string; // Full URL
339
+ }
340
+ ```
341
+
342
+ ### Rendering Rules
343
+
344
+ 1. **Filter hidden tiers:** `preparedTiers.filter(t => !t.isHidden)`
345
+ 2. **When `savingsAmount > 0`:** Show ~~$originalTotalPrice~~ β†’ **$totalPrice** + "SAVE $XX β€” X% Bundle Deal"
346
+ 3. **When `savingsAmount === 0`:** Show `totalPrice` normally, no discount UI
347
+ 4. **Use `displayPrice`** for individual products (already includes quantity)
348
+ 5. **Never calculate prices client-side** β€” all values arrive pre-calculated
349
+
350
+ ---
351
+
352
+ ## 7. Session Handoff (Pre-authenticated Users)
353
+
354
+ ```
355
+ 1. CARFIX calls partner-api: { action: "create_session", vehicle_id: 42899 }
356
+ β†’ vehicle_id MUST be a NUMBER (not string)
357
+ β†’ Returns: { session_token: "abc123..." }
358
+
359
+ 2. Redirect to: /ask-bob?session=abc123...
360
+
361
+ 3. BobStandalone reads sessionToken β†’ resolves vehicle + customer context
362
+ ```
363
+
364
+ > **Critical:** `vehicle_id` must be numeric throughout the pipeline. String values cause silent API failures.
365
+
366
+ ---
367
+
368
+ ## 8. Design Tokens
369
+
370
+ Exported from the package for use on CARFIX pages that mirror Bob's styling:
371
+
372
+ ```typescript
373
+ import {
374
+ CARFIX_COLORS,
375
+ QUALITY_TIER_CONFIG,
376
+ IMAGE_URLS,
377
+ BADGE_CONFIG,
378
+ TYPOGRAPHY,
379
+ isRotorProduct,
380
+ getDisplayPrice,
381
+ formatNZD,
382
+ } from '@gymmymac/bob-widget';
55
383
  ```
56
384
 
57
- **That's it!** Bob auto-configures from the database.
385
+ ### Key Colors
386
+
387
+ | Token | Value | Usage |
388
+ |---|---|---|
389
+ | `primary` | `#0052CC` | Standard tier, CTAs, CARFIX Value |
390
+ | `secondary` | `#38BDF8` | Accents, links |
391
+ | `accent` | `#FF8C00` | Premium tier |
392
+ | `success` | `#22C55E` | "Fits Vehicle" badges, Add to Cart |
393
+ | `destructive` | `#EF4444` | Performance tier |
394
+
395
+ ### Tier Visual Config
396
+
397
+ | Tier | Color | Background | Badge |
398
+ |---|---|---|---|
399
+ | Economy | `#475569` | `#F1F5F9` | πŸ’° |
400
+ | Standard | `#0052CC` | `rgba(0,82,204,0.1)` | ⭐ CARFIX Value |
401
+ | Premium | `#D97706` | `#FEF3C7` | πŸ† |
402
+ | Performance | `#DC2626` | `#FEE2E2` | ⚑ |
58
403
 
59
404
  ---
60
405
 
61
- ## What's New in v3.1.10
406
+ ## 9. Exported Types (Full List)
407
+
408
+ ```typescript
409
+ // Components
410
+ export { BobStandalone } from '@gymmymac/bob-widget';
411
+ export type { StandaloneWidgetProps } from '@gymmymac/bob-widget';
62
412
 
63
- - πŸ› οΈ **Executable CLI Installer**: Run `npx @gymmymac/bob-widget carfix stage-a|b|c`
64
- - 🎨 **Fixed Visual Issues**: Removed hardcoded blur, fixed Bob positioning/scale
65
- - πŸ“¦ **Full Package Distribution**: CLI, install scripts, and docs shipped in npm
66
- - πŸ”§ **Embedded Mode Default**: BobStandalone now uses `inline` variant (container-respecting)
67
- - πŸ”’ **Auth Isolation**: Unique storage keys prevent host-site auth collisions
413
+ // Types
414
+ export type {
415
+ HostContext, HostUserContext, HostVehicleContext, HostCartContext,
416
+ BobConfig, HostApiConfig, BobCallbacks, BobProviderConfig, BobLayoutConfig,
417
+ Product, CartItem, ServicePackage, PreparedTier, PreparedTierProduct, PreparedTierBrand,
418
+ Partslot, QualityTiers, Part,
419
+ PartnerConfig, PartnerFeatureFlags, EssentialCallbacks,
420
+ Vehicle, Message, HighlightedProduct,
421
+ BobAnalyticsEvent, BobGA4Config,
422
+ } from '@gymmymac/bob-widget';
423
+ ```
68
424
 
69
- ## Dependencies
425
+ ---
70
426
 
71
- Only requires:
72
- - `react` ^18.0.0
73
- - `react-dom` ^18.0.0
427
+ ## 10. Post-Install Verification Checklist
428
+
429
+ ```
430
+ β–‘ npm install completes without peer dependency warnings
431
+ β–‘ BobStandalone renders loading spinner, then Bob appears
432
+ β–‘ Bob character sits between header (72px) and bottom nav (72px)
433
+ β–‘ Chat drawer opens above bottom navigation (z-index check)
434
+ β–‘ PTT button is visible and not clipped
435
+ β–‘ Vehicle lookup works (try rego: HZP550)
436
+ β–‘ Service packages appear with tier cards
437
+ β–‘ Bundle discount shows Was/Now pricing where applicable
438
+ β–‘ "Add to Cart" callback fires with correct item shape
439
+ β–‘ Session handoff works (pass ?session=TOKEN)
440
+ β–‘ No console errors (filter for [Bob)
441
+ β–‘ Mobile: safe-area-inset respected on notched devices
442
+ ```
74
443
 
75
- All other dependencies are bundled.
444
+ ---
445
+
446
+ ## 11. Test Baseline
447
+
448
+ Bob ships with **36 unit tests** and **8+ E2E scenarios** covering:
449
+
450
+ - Callback mapping and stability
451
+ - Tier validation and empty states
452
+ - Rear Brake Disc/Drum filter logic
453
+ - Bundle discount display and cart pricing
454
+ - Vehicle lookup flow
455
+ - Service package rendering
456
+
457
+ Run locally: `cd packages/bob-widget && npx vitest run`
458
+
459
+ ---
460
+
461
+ ## πŸ“– Additional Documentation
462
+
463
+ | Document | Description |
464
+ |----------|-------------|
465
+ | **[BOB-DOCUMENTATION.md](./BOB-DOCUMENTATION.md)** | Complete integration guide with troubleshooting |
466
+ | **[CHANGELOG.md](./CHANGELOG.md)** | Version history and release notes |
467
+ | **[install/carfix/](./install/carfix/)** | Installer scripts, templates, and verification checklists |
468
+
469
+ ---
76
470
 
77
471
  ## Support
78
472
 
79
- For integration issues, check the troubleshooting section in [BOB-DOCUMENTATION.md](./BOB-DOCUMENTATION.md#9-troubleshooting).
473
+ For integration issues, the Bob team needs:
474
+ 1. Browser console output (filter for `[Bob`)
475
+ 2. Network tab showing failed API calls
476
+ 3. Screenshot of layout issue
477
+ 4. Device / browser / viewport info
80
478
 
81
479
  ## License
82
480