feat: hackathon client configurator - #1930
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: Panels collapse on every re-render
- Panel now omits the open prop unless defaultOpen is true, so details stays uncontrolled across form re-renders.
- ✅ Fixed: Capture rule IDs collide after restore
- decodeStateFromUrl now advances the rule id counter past restored ids via rememberCaptureRuleIds before new rules are created.
Or push these changes by commenting:
@cursor push 8d2d26826e
Preview (8d2d26826e)
diff --git a/test-server/configurator/autocapture-options.js b/test-server/configurator/autocapture-options.js
--- a/test-server/configurator/autocapture-options.js
+++ b/test-server/configurator/autocapture-options.js
@@ -104,6 +104,17 @@
};
}
+// Shared links restore rules with their original ids, so bump the counter past anything already in
+// use before the next createCaptureRule() call.
+export function rememberCaptureRuleIds(rules = []) {
+ for (const rule of rules) {
+ const match = /^rule-(\d+)$/.exec(rule?.id);
+ if (match) {
+ nextRuleId = Math.max(nextRuleId, Number(match[1]));
+ }
+ }
+}
+
const pageUrlAllowlist = {
key: 'pageUrlAllowlist',
label: 'Page URL allowlist',
diff --git a/test-server/configurator/components.jsx b/test-server/configurator/components.jsx
--- a/test-server/configurator/components.jsx
+++ b/test-server/configurator/components.jsx
@@ -193,10 +193,11 @@
}
// Left uncontrolled so the browser owns the open/closed state; the panel re-renders on every
-// keystroke elsewhere on the page and a controlled `open` would fight that.
+// keystroke elsewhere on the page and a controlled `open` would fight that. Only pass `open` when
+// the panel should start open — `open={false}` is still controlled and would slam shut on re-render.
export function Panel({ title, description, badge, defaultOpen = false, children }) {
return (
- <details style={styles.panel} open={defaultOpen}>
+ <details style={styles.panel} {...(defaultOpen ? { open: true } : {})}>
<summary style={styles.panelSummary}>
{title}
{badge ? <span style={styles.panelBadge}>{badge}</span> : null}
diff --git a/test-server/configurator/share-link.js b/test-server/configurator/share-link.js
--- a/test-server/configurator/share-link.js
+++ b/test-server/configurator/share-link.js
@@ -1,3 +1,5 @@
+import { rememberCaptureRuleIds } from './autocapture-options.js';
+
// The form state round-trips through a single query parameter, so a bookmarked URL reopens the same
// configuration.
//
@@ -90,7 +92,9 @@
return defaults;
}
try {
- return mergeOverDefaults(defaults, JSON.parse(await inflate(fromBase64Url(saved))));
+ const state = mergeOverDefaults(defaults, JSON.parse(await inflate(fromBase64Url(saved))));
+ rememberCaptureRuleIds(state.autocaptureSubOptions?.networkTracking?.captureRules);
+ return state;
} catch (error) {
// A truncated or hand-edited link shouldn't leave the page blank.
console.warn(`Ignoring unreadable ?${STATE_PARAM} parameter`, error);You can send follow-ups to the cloud agent here.
Reviewed by Cursor Bugbot for commit 98106e9. Configure here.
| {children} | ||
| </div> | ||
| </details> | ||
| ); |
There was a problem hiding this comment.
Panels collapse on every re-render
High Severity
Panel passes open={defaultOpen} into <details>. With the default false, React treats open as controlled and resets it on every parent re-render, so opened sections slam shut as soon as any form field updates—despite the comment saying the panel should stay uncontrolled.
Reviewed by Cursor Bugbot for commit 98106e9. Configure here.
| requestBody: { allowlist: '', excludelist: '' }, | ||
| responseBody: { allowlist: '', excludelist: '' }, | ||
| }; | ||
| } |
There was a problem hiding this comment.
Capture rule IDs collide after restore
Medium Severity
createCaptureRule always increments a module-level counter from zero. Shared links restore rules with their original ids, so adding a rule after load can reuse an existing id and produce duplicate React keys, breaking updates and removes in the capture-rules editor.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 98106e9. Configure here.
size-limit report 📦
|



Summary
Checklist
Note
Low Risk
Adds a self-contained developer tool under
test-server/plus a scoped Vite React plugin andprismjsdependency. No production SDK packages or runtime behavior are changed.Overview
Adds an Amplitude Browser Client Configurator under
test-server/configurator/— a form UI for composing analytics, autocapture, session replay, and Guides & Surveys options, then generating init code.Generated output supports three formats: ESM, browser snippet, and Unified SDK. Only options that differ from SDK defaults are emitted. Configurations can be copied as compressed share links and opened on a sibling run page that initializes the local workspace SDK and logs captured events in a sandbox.
Also wires Vite’s React plugin for
configurator/only and addsprismjsfor syntax-highlighted code output.Reviewed by Cursor Bugbot for commit 98106e9. Bugbot is set up for automated code reviews on this repo. Configure here.