Skip to main content

HoopAI AI Chat Widget Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.
Goal: Replace the broken VoiceGlow/ConvoCore widget with a fully custom Claude Haiku 4.5 chat panel backed by a Cloudflare Worker proxy that keeps all API keys off the client. Architecture: A Cloudflare Worker (worker/src/index.js) receives chat requests from the browser, runs an agentic tool loop (web search, support ticket creation), then streams the final Claude response back via SSE. The browser widget (theme/chat-widget.js) is a self-contained IIFE that renders a right-side panel matching Mintlify’s native AI drawer — slides in and pushes page content left. Tech Stack: Cloudflare Workers, Wrangler CLI v3, OpenRouter API (anthropic/claude-haiku-4-5), Vanilla JS (ES5-compatible IIFE), CSS custom properties (--ds-* tokens already in theme/custom.css).

File Map


Task 1: Worker — Project Scaffold

Files:
  • Create: worker/package.json
  • Create: worker/wrangler.toml
  • Create: worker/src/index.js (skeleton only)
  • Step 1.1 — Create worker/package.json
  • Step 1.2 — Create worker/wrangler.toml
  • Step 1.3 — Create skeleton worker/src/index.js
  • Step 1.4 — Install Wrangler and verify scaffold
Expected output: 3.x.x (Wrangler version number)
  • Step 1.5 — Commit scaffold

Task 2: Worker — CORS + Routing + OpenRouter Streaming Proxy

Files:
  • Modify: worker/src/index.js (replace skeleton with full implementation)
  • Step 2.1 — Smoke-test the current skeleton locally
In a second terminal:
Expected: hoopai-chat-api ok Stop the dev server (Ctrl+C).
  • Step 2.2 — Replace worker/src/index.js with full implementation
Write the complete file. This handles CORS, routing, the agentic tool loop, web search, support ticket, and SSE streaming all in one module:
  • Step 2.3 — Start worker dev server and test CORS preflight
In a second terminal, test CORS preflight:
Expected: HTTP/1.1 204 and access-control-allow-origin: http://localhost:3000
  • Step 2.4 — Test blocked origin
Expected: HTTP/1.1 403
  • Step 2.5 — Test basic streaming (requires OPENROUTER_API_KEY as local secret)
Create worker/.dev.vars (gitignored, local only):
Note: .dev.vars is automatically gitignored by Wrangler — it’s the Wrangler equivalent of .env for local dev. Restart the dev server, then:
Expected: a stream of data: {"type":"token","content":"..."} lines ending with data: {"type":"done"}
  • Step 2.6 — Commit worker implementation

Task 3: Deploy Worker and Set Secrets

Files: No code changes — deployment and secret configuration only.
  • Step 3.1 — Deploy to Cloudflare
Expected output (last line):
Copy the worker URL — you will need it in Task 5.
  • Step 3.2 — Set the OpenRouter API key secret
When prompted, paste:
Expected: ✓ Success! Uploaded secret OPENROUTER_API_KEY
  • Step 3.3 — Verify deployed worker responds
Replace <WORKER_URL> with the URL from Step 3.1:
Expected: streaming token events ending with {"type":"done"}
  • Step 3.4 — Commit deployment artifacts
Note: Add worker/.dev.vars to .gitignore if not already covered by .env.* rule: Open .gitignore and add under the secrets section:

Task 4: Widget CSS — Panel Styles

Files:
  • Modify: theme/custom.css (append at end of file)
  • Step 4.1 — Append panel CSS to theme/custom.css
Read the current end of theme/custom.css to find the last line number, then append:
  • Step 4.2 — Commit CSS

Task 5: Widget JS — Complete Rewrite

Files:
  • Rewrite: theme/chat-widget.js
This task replaces the entire VoiceGlow file with the custom widget. All existing Ask AI button injection points are preserved with identical IDs and behaviour — only toggleWidget() is replaced by togglePanel().
  • Step 5.1 — Replace theme/chat-widget.js with the full widget
  • Step 5.2 — Commit widget

Task 6: Wire Worker URL and Verify docs.json

Files:
  • Modify: theme/chat-widget.js (replace placeholder URL)
  • Verify: docs.json (ensure JS path is correct)
  • Step 6.1 — Replace the WORKER_URL placeholder
In theme/chat-widget.js, line 22, replace:
With the actual URL from Task 3 Step 3.1, e.g.:
  • Step 6.2 — Verify docs.json JS reference
Check that docs.json line ~143 references the correct path. Open docs.json and look for the "js" array. It should read:
If any entries are missing the theme/ prefix (e.g. "chat-widget.js"), update them to include theme/:
If the path is already "theme/chat-widget.js", no change needed. If it shows "chat-widget.js", update it in docs.json.
  • Step 6.3 — Commit URL + docs.json fix

Task 7: Integration Smoke Test

No file changes — verification only.
  • Step 7.1 — Kill any stale Node processes and start dev server
Wait for localhost:3000 to be ready.
  • Step 7.2 — Open browser at localhost:3000 and verify Ask AI button appears
Navigate to http://localhost:3000. Confirm:
  • Navbar shows the sparkle “Ask AI” button to the right of the search bar
  • No JavaScript console errors
  • Step 7.3 — Open panel and verify layout
Click “Ask AI”. Confirm:
  • Panel slides in from the right
  • Page content shifts left
  • Empty state shows sparkle icon, title, and 3 suggestion chips
  • Dark/light mode matches site theme (toggle dark mode to verify)
  • Step 7.4 — Send a message and verify streaming
Type “What is HoopAI?” and press Enter. Confirm:
  • User bubble appears immediately
  • Typing indicator shows
  • Response streams in token by token
  • Send button shows stop icon during streaming
  • Input is disabled during streaming
  • After completion: send button resets, input re-enables
  • Step 7.5 — Test expand and clear
Click the expand button — panel widens to 680px, content shifts further left. Click clear — conversation resets to empty state. Press Ctrl+I — panel toggles closed/open.
  • Step 7.6 — Test code block Ask AI button
Navigate to a page with a code block (e.g. /api-reference/introduction). Confirm:
  • Sparkle icon appears in code block toolbar on hover
  • Clicking it opens the panel with the code pre-loaded in input
  • Step 7.7 — Commit final state if all checks pass

Self-Review Checklist

  • CORS security — Worker blocks all origins except help.hoopai.com and localhost:3000
  • API key never in browserOPENROUTER_API_KEY is a Wrangler secret, not in any file
  • Streaming — SSE handled with ReadableStream + TransformStream in Worker, ReadableStream in widget
  • Tool loop — max 4 iterations prevents infinite loops; each tool fires tool_start / tool_end SSE events
  • Web search gracefully disabled — if BRAVE_SEARCH_API_KEY secret absent, returns fallback message (no crash)
  • Support ticket gracefully disabled — if SUPPORT_WEBHOOK_URL absent, returns helpful message
  • Dark mode — all panel CSS uses --ds-* tokens; no hardcoded colours
  • Mobile — panel goes full-width on ≤768px, no content push (avoids broken layout)
  • Existing Ask AI IDs preserved#assistant-entry, #assistant-entry-mobile, data-ask-ai-injected, #page-ask-ai-btn all identical
  • No VoiceGlow CDN callscdn.voiceglow.org script removed entirely
  • Branding — system prompt explicitly blocks GoHighLevel / Marketing Muse / WhoPayI
  • Keyboard shortcut — Ctrl+I / Cmd+I preserved
Last modified on May 19, 2026