Skip to content

perf: Load the Kapa.ai widget on demand - #20278

Open
coolguyzone wants to merge 1 commit into
masterfrom
coolguyzone/perf/defer-kapa
Open

coolguyzone wants to merge 1 commit into
masterfrom
coolguyzone/perf/defer-kapa

Conversation

@coolguyzone

Copy link
Copy Markdown
Contributor

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 past window.load; it still ran every time.

This replaces the eager <Script> in app/layout.tsx with 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 calls openKapa() directly:

  • Header button (header.tsx)
  • Desktop search-bar button (search/index.tsx)
  • #ai-list-entry row in the search results, which passes {query, submit: true} (search/index.tsx)
  • The ?askAI=true deep 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:

  • On page load: 0 Kapa requests, 0 reCAPTCHA requests, window.Kapa undefined, 0 console errors
  • On hover: bundle fetches and window.Kapa becomes available
  • On click: modal opens with branding, disclaimer, and example questions intact; the search path passes the query through and submits it; mobile works at 390px
  • On reopen: exactly one <script src*="kapa"> in the DOM, so no duplicate injection

Measured on master under 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

  • Please exercise all four entry points in the preview, including ?askAI=true and the "Ask Sentry about …" row in search results — those two are the ones a quick smoke test would miss.
  • I can't quote a new Lighthouse score from a dev build. Worth running Lighthouse against the Vercel preview to get the real TBT movement.
  • https://proxy.kapa.ai/ returns 404 on localhost. It is not a regression from this change — on master it 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-DD with the due date. You can update this information later by editing the PR description.

  • Urgent deadline (GA date, etc.): YYYY-MM-DD
  • Other deadline: YYYY-MM-DD
  • No deadline: Not urgent, can wait up to 1 week+

SLA

  • Teamwork makes the dream work, so please add a reviewer to your PRs.
  • Please give the docs team up to 1 week to review your PR unless you've supplied a deadline.

Thanks in advance for your help!

PRE-MERGE CHECKLIST

Make sure you've checked the following before merging your changes:

  • Checked Vercel preview for correctness, including links
  • PR was reviewed and approved by any necessary SMEs (subject matter experts)
  • PR was reviewed and approved by a member of the Sentry docs team

EXTRA RESOURCES

🤖 Generated with Claude Code

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>
@vercel

vercel Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
develop-docs Ready Ready Preview Oct 27, 2026 10:09pm UTC
sentry-docs Ready Ready Preview Oct 27, 2026 10:09pm UTC

Request Review

@github-actions github-actions Bot added the Priority: Normal Docs review has no urgent deadline label Oct 27, 2026
@cursor

cursor Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

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: sentry-docs, develop-docs.

Mention @change-monitor in a comment to update the plan.

Plan

What changed

Ask 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.

Risk

If 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 effect

The 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 docs.page.load, not a user percent.

Signal Baseline Rule Source
widget.kapa.ai spans per docs.page.load on docs 0.49-0.51 Fall below the band Sentry org sentry, project docs. Spans url.full:*widget.kapa.ai* with environment:production. Metric docs.page.load. Windows 2026-10-26T22:03Z to 2026-10-27T22:03Z (9503 / 19526 = 0.49) and 2026-10-25T23:00Z to 2026-10-26T21:00Z (9394 / 18267 = 0.51).
widget.kapa.ai spans per docs.page.load on develop-docs 0.44 Fall below 0.44 Sentry org sentry, project develop-docs. Same span query. Metric docs.page.load. Window 2026-10-26T22:03Z to 2026-10-27T22:03Z (747 / 1707 = 0.44). One 24h window only.

Regression watch

A 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. Failed to fetch (proxy.kapa.ai) on issue DOCS-BGH is chrome-extension noise. Do not treat that issue as this change.

Signal Baseline Rule Source
docs.page.load per 24h on docs 16700-19500 Hold in the band Sentry org sentry, project docs. Metric docs.page.load, environment:production. Last 24h 19526 from 2026-10-26T22:03Z to 2026-10-27T22:03Z. Seven-day total 117129, about 16700 per day.
docs.search.query per docs.page.load on docs 0.08-0.11 Hold in the band Sentry org sentry, project docs. Metrics docs.search.query and docs.page.load. Windows 2026-10-26T22:03Z to 2026-10-27T22:03Z (2153 / 19526 = 0.11) and 2026-10-25T23:00Z to 2026-10-26T21:00Z (1478 / 18267 = 0.08).
Kapa loader errors on docs 0 Hold at 0 Sentry org sentry, project docs. Errors environment:production and message Failed to load the Kapa widget or Kapa widget loaded but never initialized. Window 2026-10-26T22:03Z to 2026-10-27T22:03Z. These messages are new. Zero is the pre-deploy baseline. A rise means the loader failed after a user reached for Ask AI.
p75 INP on docs 48ms Hold near 48ms Sentry org sentry, project docs. Spans has:browser.web_vital.inp.value environment:production, field p75(browser.web_vital.inp.value). Last 24h and last 7d both measured 48ms. A rise would show jank on the header or search click path.
docs.page.load per 24h on develop-docs 1707 Hold near 1707 Sentry org sentry, project develop-docs. Metric docs.page.load, environment:production. Window 2026-10-26T22:03Z to 2026-10-27T22:03Z. One 24h window only.

Not observable

No counter records that the Ask AI modal opened. Plausible Ask AI Referrer events are not in this telemetry. Hover and focus prefetch emit no metric. The prior-day recaptcha resource rate was not sampled. The prior-day develop-docs widget-script rate was not sampled. Search and header stack frames returned no error events. LCP on pageload spans returned null in this project.

Get Slack DMs about this change: cursor.com/automations/rollouts

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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') ?? ''},
});
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 18e8779. Configure here.

This branch was successfully deployed

2 active deployments
Preview – sentry-docs — 18e8779e Deployed Oct 27, 2026 by vercel[bot]
Preview – develop-docs — 18e8779e Deployed Oct 27, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Priority: Normal Docs review has no urgent deadline

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant