Repository navigation
perf: Load the Kapa.ai widget on demand - #20278
coolguyzone wants to merge 1 commit into
Conversation
The widget bundle is ~600 KiB and pulls reCAPTCHA Enterprise in behind it. Together they accounted for roughly 1.3 MB of JavaScript and ~1.08s of script bootup on every page load, even though almost nobody opens Ask AI. It was already strategy="lazyOnload", which only defers it past window load; it still ran on every visit. Replace the eager <Script> with an on-demand loader. Each Ask AI entry point now fetches the widget on first use and pre-warms on hover/focus, so the click still feels instant. This also removes two latent races. The ?askAI=true deep link previously waited a fixed 300ms and silently did nothing if the widget wasn't ready; the search results AI entry was guarded by `if (window.Kapa?.open)` and was a no-op in the same case. Both now await the loader. Verified in headless Chrome: zero kapa/reCAPTCHA requests on load, and all four entry points (header, search bar, search results with query passthrough, and the ?askAI=true deep link) open the modal correctly on desktop and mobile. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
The change loads the Ask AI widget only after a user reaches for it. The plan checks widget script volume against page loads, search query volume, and widget load errors. An issue escalates when widget scripts still run on most page loads or load errors appear. Services: Mention PlanWhat changedAsk AI no longer fetches its widget on every page view. The widget loads on the first hover, focus, or click. The askAI deep link and the search-result Ask AI row wait for that load. sentry-docs and develop-docs must deploy before this change is live. Those sites share the app layout and the Ask AI controls. RiskIf the on-demand loader fails, Ask AI never opens for that visit. The search overlay can close and still fail to open the widget. A broken header control can hide Ask AI on mobile and desktop. The loader waits up to 10 seconds for the widget API. A timeout leaves the click with no modal and reports an error. Intended effectThe widget script should run on far fewer page loads than today. Absent means the widget-script share of page loads stays in the pre-deploy band. A drop to zero can mean nobody opened Ask AI. It can also mean the loader never ran. Use the load-error watch to split those cases. Widget-script volume follows a daily cycle. Compare 24h pooled rates, not a single hour. Client traces sample at 30 percent. The share below is an index against
Regression watchA failed loader, a broken header, or a broken search overlay would show here. Widget-script volume follows a daily cycle. Compare 24h pooled rates, not a single hour.
Not observableNo counter records that the Ask AI modal opened. Plausible Get Slack DMs about this change: cursor.com/automations/rollouts |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 18e8779. Configure here.
| props: {referrer: searchParams.get('referrer') ?? ''}, | ||
| }); | ||
| } | ||
| } |
There was a problem hiding this comment.
Deep link opens Ask AI after navigation
Medium Severity
The ?askAI=true effect fires openKapa with no cancellation, so a still-loading widget can open the modal after the user leaves the page. The previous timeout was cleared on unmount; openKapa can now run for seconds, and a later effect re-run can call it again.
Reviewed by Cursor Bugbot for commit 18e8779. Configure here.


DESCRIBE YOUR PR
The Kapa.ai widget was loading on every page view. The bundle is ~600 KiB and pulls reCAPTCHA Enterprise in behind it — together roughly 1.3 MB of JavaScript and ~1.08s of script bootup on every visit, for a feature almost nobody opens. It was already
strategy="lazyOnload", but that only defers pastwindow.load; it still ran every time.This replaces the eager
<Script>inapp/layout.tsxwith an on-demand loader (src/lib/kapa.ts). The widget is fetched the first time someone reaches for Ask AI, and pre-warmed on hover/focus so the click still feels instant.There are four Ask AI entry points, and all four needed rewiring. The first two previously worked through Kapa's own
data-modal-override-open-class="kapa-ai-class"delegation, which can't fire if the widget was never loaded — so that class is gone and every entry point now callsopenKapa()directly:header.tsx)search/index.tsx)#ai-list-entryrow in the search results, which passes{query, submit: true}(search/index.tsx)?askAI=truedeep link (askAiSearchParams.tsx)This also fixes two latent bugs. The deep link waited a fixed 300ms and then silently did nothing if the widget wasn't ready yet; the search-results entry was wrapped in
if (window.Kapa?.open)and was a no-op in the same situation. Both now await the loader, so neither races a timeout.Verification
Tested in headless Chrome against a local dev server, all four paths confirmed with screenshots:
window.Kapaundefined, 0 console errorswindow.Kapabecomes available<script src*="kapa">in the DOM, so no duplicate injectionMeasured on
masterunder identical local conditions, page load pulled 9 third-party requests / 764 KiB (6 of them reCAPTCHA, 730 KiB). On this branch that is zero until someone opens Ask AI.pnpm lint:ts, ESLint and Prettier are clean, and all 517 tests pass.Notes for reviewers
?askAI=trueand the "Ask Sentry about …" row in search results — those two are the ones a quick smoke test would miss.https://proxy.kapa.ai/returns 404 on localhost. It is not a regression from this change — onmasterit fires on page load, here it only fires after Ask AI opens, and production doesn't 404 at all. It's Kapa's origin whitelist not covering localhost.IS YOUR CHANGE URGENT?
Help us prioritize incoming PRs by letting us know when the change needs to go live.
Select exactly one option. For deadlines, replace
YYYY-MM-DDwith the due date. You can update this information later by editing the PR description.SLA
Thanks in advance for your help!
PRE-MERGE CHECKLIST
Make sure you've checked the following before merging your changes:
EXTRA RESOURCES
🤖 Generated with Claude Code