From 0186cd2da56f895872312c79d28f93cc177de05d Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 04:10:44 +0000 Subject: [PATCH] feat(nudges): unified registry-driven nudge framework MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace eight one-off engagement-nudge implementations (banners, modals, toasts) with a single registry-driven framework. Each nudge declares its trigger, audience, dismissal behavior, persistence policy, and optional schedule in one place; the framework handles route matching, exclusivity, storage, and analytics uniformly. Migrated: launch-banner-dsv4, dsv4-launch-modal, github-star-modal, reproducibility-nudge, star-nudge, export-nudge, gradient-label-nudge, eval-samples-nudge. Old per-nudge components and storage modules are deleted; cypress tests now reference the new dismissal-storage keys (`inferencex-nudge:`). Key features: - Registry entry per nudge with declarative trigger (mount, mount-delay, event with thresholds and optional DOM selector matching) - Persistence policies: session, forever, cooldown (with timestamp expiry — preserves the 1-week re-show cadence for star/eval-samples) - Optional schedule (showAfter / hideAfter) for time-bound campaigns - Priority-based slot manager so dsv4-modal preempts github-star-modal, and page-scoped eval-samples-nudge preempts always-on toasts on /evaluation - External-dismiss events for state-driven hide (e.g. STARRED_EVENT hides the star nudges without persisting) - Unified analytics: nudge_shown / nudge_dismissed / nudge_action_clicked, each carrying { id, kind } Co-authored-by: functionstackx --- packages/app/cypress/e2e/csv-export.cy.ts | 2 +- .../app/cypress/e2e/custom-user-values.cy.ts | 2 +- .../app/cypress/e2e/drill-down-trend.cy.ts | 2 +- .../app/cypress/e2e/dropdown-switching.cy.ts | 2 +- .../app/cypress/e2e/evaluation-chart.cy.ts | 4 +- packages/app/cypress/e2e/gpu-power.cy.ts | 4 +- packages/app/cypress/e2e/gpu-specs.cy.ts | 10 +- .../app/cypress/e2e/gradient-labels.cy.ts | 8 +- .../app/cypress/e2e/historical-trends.cy.ts | 4 +- .../app/cypress/e2e/inference-chart.cy.ts | 2 +- packages/app/cypress/e2e/line-labels.cy.ts | 4 +- .../app/cypress/e2e/model-architecture.cy.ts | 2 +- packages/app/cypress/e2e/navigation.cy.ts | 8 +- .../app/cypress/e2e/reliability-chart.cy.ts | 4 +- packages/app/cypress/e2e/sanity.cy.ts | 4 +- packages/app/cypress/e2e/speed-overlay.cy.ts | 10 +- .../cypress/e2e/throughput-calculator.cy.ts | 6 +- .../app/cypress/e2e/ttft-x-axis-toggle.cy.ts | 2 +- packages/app/cypress/e2e/url-params.cy.ts | 2 +- .../cypress/e2e/yaxis-metrics-render.cy.ts | 2 +- .../src/app/(dashboard)/evaluation/page.tsx | 2 - packages/app/src/app/layout.tsx | 10 +- .../app/src/components/dashboard-shell.tsx | 26 +- .../app/src/components/dsv4-launch-modal.tsx | 92 ------- .../app/src/components/eval-samples-nudge.tsx | 81 ------ .../app/src/components/export-nudge.test.ts | 97 ------- packages/app/src/components/export-nudge.tsx | 72 ------ .../app/src/components/github-star-modal.tsx | 137 ---------- .../components/gradient-label-nudge.test.ts | 97 ------- .../src/components/gradient-label-nudge.tsx | 75 ------ .../components/inference/ui/ScatterGraph.tsx | 3 +- .../src/components/landing/landing-page.tsx | 8 +- .../src/components/landing/launch-banner.tsx | 96 ------- packages/app/src/components/nudges/Nudge.tsx | 148 +++++++++++ .../app/src/components/nudges/NudgeBanner.tsx | 101 ++++++++ .../src/components/nudges/NudgeBannerSlot.tsx | 20 ++ .../app/src/components/nudges/NudgeModal.tsx | 91 +++++++ .../src/components/nudges/NudgeProvider.tsx | 105 ++++++++ .../app/src/components/nudges/NudgeRoot.tsx | 20 ++ .../app/src/components/nudges/NudgeToast.tsx | 59 +++++ packages/app/src/components/nudges/index.ts | 4 + .../src/components/nudges/registry.test.ts | 157 +++++++++++ .../app/src/components/nudges/registry.ts | 244 ++++++++++++++++++ .../components/nudges/use-nudge-trigger.ts | 98 +++++++ .../src/components/reproducibility-nudge.tsx | 64 ----- .../app/src/components/star-nudge.test.ts | 105 -------- packages/app/src/components/star-nudge.tsx | 104 -------- packages/app/src/lib/dsv4-launch-storage.ts | 17 -- packages/app/src/lib/nudges/index.ts | 19 ++ .../app/src/lib/nudges/persistence.test.ts | 142 ++++++++++ packages/app/src/lib/nudges/persistence.ts | 79 ++++++ .../app/src/lib/nudges/scheduling.test.ts | 47 ++++ packages/app/src/lib/nudges/scheduling.ts | 22 ++ .../app/src/lib/nudges/should-show.test.ts | 84 ++++++ packages/app/src/lib/nudges/should-show.ts | 25 ++ packages/app/src/lib/nudges/types.ts | 134 ++++++++++ packages/app/src/lib/star-storage.ts | 16 +- 57 files changed, 1665 insertions(+), 1120 deletions(-) delete mode 100644 packages/app/src/components/dsv4-launch-modal.tsx delete mode 100644 packages/app/src/components/eval-samples-nudge.tsx delete mode 100644 packages/app/src/components/export-nudge.test.ts delete mode 100644 packages/app/src/components/export-nudge.tsx delete mode 100644 packages/app/src/components/github-star-modal.tsx delete mode 100644 packages/app/src/components/gradient-label-nudge.test.ts delete mode 100644 packages/app/src/components/gradient-label-nudge.tsx delete mode 100644 packages/app/src/components/landing/launch-banner.tsx create mode 100644 packages/app/src/components/nudges/Nudge.tsx create mode 100644 packages/app/src/components/nudges/NudgeBanner.tsx create mode 100644 packages/app/src/components/nudges/NudgeBannerSlot.tsx create mode 100644 packages/app/src/components/nudges/NudgeModal.tsx create mode 100644 packages/app/src/components/nudges/NudgeProvider.tsx create mode 100644 packages/app/src/components/nudges/NudgeRoot.tsx create mode 100644 packages/app/src/components/nudges/NudgeToast.tsx create mode 100644 packages/app/src/components/nudges/index.ts create mode 100644 packages/app/src/components/nudges/registry.test.ts create mode 100644 packages/app/src/components/nudges/registry.ts create mode 100644 packages/app/src/components/nudges/use-nudge-trigger.ts delete mode 100644 packages/app/src/components/reproducibility-nudge.tsx delete mode 100644 packages/app/src/components/star-nudge.test.ts delete mode 100644 packages/app/src/components/star-nudge.tsx delete mode 100644 packages/app/src/lib/dsv4-launch-storage.ts create mode 100644 packages/app/src/lib/nudges/index.ts create mode 100644 packages/app/src/lib/nudges/persistence.test.ts create mode 100644 packages/app/src/lib/nudges/persistence.ts create mode 100644 packages/app/src/lib/nudges/scheduling.test.ts create mode 100644 packages/app/src/lib/nudges/scheduling.ts create mode 100644 packages/app/src/lib/nudges/should-show.test.ts create mode 100644 packages/app/src/lib/nudges/should-show.ts create mode 100644 packages/app/src/lib/nudges/types.ts diff --git a/packages/app/cypress/e2e/csv-export.cy.ts b/packages/app/cypress/e2e/csv-export.cy.ts index 026d3121..f37cfd9e 100644 --- a/packages/app/cypress/e2e/csv-export.cy.ts +++ b/packages/app/cypress/e2e/csv-export.cy.ts @@ -1,7 +1,7 @@ describe('CSV Export', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/inference'); cy.get('[data-testid="chart-figure"]').should('exist'); diff --git a/packages/app/cypress/e2e/custom-user-values.cy.ts b/packages/app/cypress/e2e/custom-user-values.cy.ts index 1456033a..7d3545ed 100644 --- a/packages/app/cypress/e2e/custom-user-values.cy.ts +++ b/packages/app/cypress/e2e/custom-user-values.cy.ts @@ -15,7 +15,7 @@ const selectCustomPowerMetric = () => { describe('Custom User Values', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/inference'); cy.get('[data-testid="model-selector"]').should('be.visible'); diff --git a/packages/app/cypress/e2e/drill-down-trend.cy.ts b/packages/app/cypress/e2e/drill-down-trend.cy.ts index bd06ec77..45d3a873 100644 --- a/packages/app/cypress/e2e/drill-down-trend.cy.ts +++ b/packages/app/cypress/e2e/drill-down-trend.cy.ts @@ -6,7 +6,7 @@ describe('Drill-Down Trend Chart Modal', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/inference'); // Wait for scatter graph to render with data points diff --git a/packages/app/cypress/e2e/dropdown-switching.cy.ts b/packages/app/cypress/e2e/dropdown-switching.cy.ts index b45cb51c..3f1d9197 100644 --- a/packages/app/cypress/e2e/dropdown-switching.cy.ts +++ b/packages/app/cypress/e2e/dropdown-switching.cy.ts @@ -6,7 +6,7 @@ describe('Dropdown one-click switching', () => { beforeEach(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/inference'); cy.get('[data-testid="inference-chart-display"]').should('exist'); diff --git a/packages/app/cypress/e2e/evaluation-chart.cy.ts b/packages/app/cypress/e2e/evaluation-chart.cy.ts index 020f9a1f..75a103db 100644 --- a/packages/app/cypress/e2e/evaluation-chart.cy.ts +++ b/packages/app/cypress/e2e/evaluation-chart.cy.ts @@ -1,7 +1,7 @@ describe('Evaluation Chart', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/evaluation'); cy.get('[data-testid="evaluation-chart-display"]').should('exist'); @@ -43,7 +43,7 @@ describe('Evaluation Chart', () => { describe('Evaluation Chart — Content & Interactions', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/evaluation'); cy.get('[data-testid="evaluation-chart-display"]').should('be.visible'); diff --git a/packages/app/cypress/e2e/gpu-power.cy.ts b/packages/app/cypress/e2e/gpu-power.cy.ts index 9991e5f8..d250786b 100644 --- a/packages/app/cypress/e2e/gpu-power.cy.ts +++ b/packages/app/cypress/e2e/gpu-power.cy.ts @@ -7,7 +7,7 @@ describe('PowerX', () => { beforeEach(() => { cy.visit('/inference', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); }); @@ -34,7 +34,7 @@ describe('PowerX', () => { beforeEach(() => { cy.visit('/inference', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); win.localStorage.setItem('inferencex-feature-gate', '1'); }, }); diff --git a/packages/app/cypress/e2e/gpu-specs.cy.ts b/packages/app/cypress/e2e/gpu-specs.cy.ts index c569d7ae..2801f31e 100644 --- a/packages/app/cypress/e2e/gpu-specs.cy.ts +++ b/packages/app/cypress/e2e/gpu-specs.cy.ts @@ -1,7 +1,7 @@ describe('GPU Specs Tab', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/gpu-specs'); // Wait for GPU Specs tab content to be present in the DOM @@ -210,7 +210,7 @@ describe('GPU Specs Tab', () => { describe('GPU Specs Bar Chart View', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/gpu-specs'); cy.get('h2').contains('GPU Specifications').should('exist'); @@ -284,7 +284,7 @@ describe('GPU Specs Bar Chart View', () => { describe('GPU Specs Radar Chart View', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/gpu-specs'); cy.get('h2').contains('GPU Specifications').should('exist'); @@ -381,7 +381,7 @@ describe('GPU Specs Radar Chart View', () => { describe('GPU Specs Navigation', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/inference'); cy.get('[data-testid="chart-section-tabs"]').should('be.visible'); @@ -397,7 +397,7 @@ describe('GPU Specs Navigation', () => { describe('Topology Dialog Navigation', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/gpu-specs'); cy.get('h2').contains('GPU Specifications').should('exist'); diff --git a/packages/app/cypress/e2e/gradient-labels.cy.ts b/packages/app/cypress/e2e/gradient-labels.cy.ts index 333baa6d..5c4b2601 100644 --- a/packages/app/cypress/e2e/gradient-labels.cy.ts +++ b/packages/app/cypress/e2e/gradient-labels.cy.ts @@ -2,7 +2,7 @@ describe('Gradient Labels Toggle', () => { before(() => { cy.visit('/inference', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); // Wait for chart to load @@ -80,7 +80,7 @@ describe('Gradient Labels Toggle', () => { it('URL param i_gradlabel=1 enables gradient labels on load', () => { cy.visit('/inference?i_gradlabel=1', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); cy.get('[data-testid="scatter-graph"]').should('be.visible'); @@ -90,7 +90,7 @@ describe('Gradient Labels Toggle', () => { it('URL param i_advlabel=1 enables parallelism labels on load', () => { cy.visit('/inference?i_advlabel=1', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); cy.get('[data-testid="scatter-graph"]').should('be.visible'); @@ -119,7 +119,7 @@ describe('Gradient Labels with non-default Y-axis metrics', () => { before(() => { cy.visit('/inference', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); cy.get('[data-testid="scatter-graph"]').should('be.visible'); diff --git a/packages/app/cypress/e2e/historical-trends.cy.ts b/packages/app/cypress/e2e/historical-trends.cy.ts index 1e59b72a..27c8aa6c 100644 --- a/packages/app/cypress/e2e/historical-trends.cy.ts +++ b/packages/app/cypress/e2e/historical-trends.cy.ts @@ -5,7 +5,7 @@ describe('Historical Trends Tab', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/historical'); cy.get('[data-testid="historical-trends-display"]').should('be.visible'); @@ -37,7 +37,7 @@ describe('Historical Trends Tab', () => { describe('Historical Trends — Content & Interactions', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/historical'); cy.get('[data-testid="historical-trends-display"]').should('be.visible'); diff --git a/packages/app/cypress/e2e/inference-chart.cy.ts b/packages/app/cypress/e2e/inference-chart.cy.ts index 93350d69..7230b814 100644 --- a/packages/app/cypress/e2e/inference-chart.cy.ts +++ b/packages/app/cypress/e2e/inference-chart.cy.ts @@ -1,7 +1,7 @@ describe('Inference Chart', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/inference'); }); diff --git a/packages/app/cypress/e2e/line-labels.cy.ts b/packages/app/cypress/e2e/line-labels.cy.ts index 011bbda3..1ef3583a 100644 --- a/packages/app/cypress/e2e/line-labels.cy.ts +++ b/packages/app/cypress/e2e/line-labels.cy.ts @@ -2,7 +2,7 @@ describe('Line Labels Toggle', () => { before(() => { cy.visit('/inference', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); // Wait for chart to load @@ -69,7 +69,7 @@ describe('Line Labels Toggle', () => { it('URL param i_linelabel=1 enables line labels on load', () => { cy.visit('/inference?i_linelabel=1', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); cy.get('[data-testid="scatter-graph"]').should('be.visible'); diff --git a/packages/app/cypress/e2e/model-architecture.cy.ts b/packages/app/cypress/e2e/model-architecture.cy.ts index f0646c4e..1df8ed14 100644 --- a/packages/app/cypress/e2e/model-architecture.cy.ts +++ b/packages/app/cypress/e2e/model-architecture.cy.ts @@ -4,7 +4,7 @@ describe('Model Architecture Diagram', () => { cy.viewport(1280, 800); cy.visit('/inference', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); // Wait for the page to load diff --git a/packages/app/cypress/e2e/navigation.cy.ts b/packages/app/cypress/e2e/navigation.cy.ts index c15e49b5..8fa96593 100644 --- a/packages/app/cypress/e2e/navigation.cy.ts +++ b/packages/app/cypress/e2e/navigation.cy.ts @@ -4,7 +4,7 @@ describe('Chart Section Tabs — E2E', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/inference'); }); @@ -46,15 +46,15 @@ describe('First-load navigation', () => { cy.visit('/', { onBeforeLoad(win) { win.localStorage.removeItem('inferencex-starred'); - win.localStorage.removeItem('inferencex-star-modal-dismissed'); - win.localStorage.removeItem('inferencex-dsv4-modal-dismissed'); + win.localStorage.removeItem('inferencex-nudge:github-star-modal'); + win.localStorage.removeItem('inferencex-nudge:dsv4-launch-modal'); }, }); // dsv4 launch modal takes precedence over the GitHub star modal on first // load — only one modal shows at a time. Either is fine for this test, we // just need *a* first-load modal up to verify it doesn't block navigation. - cy.get('[data-testid="dsv4-launch-modal"]').should('be.visible'); + cy.get('[data-testid="nudge-dsv4-launch-modal"]').should('be.visible'); cy.get('body').should('not.have.attr', 'data-scroll-locked'); }); diff --git a/packages/app/cypress/e2e/reliability-chart.cy.ts b/packages/app/cypress/e2e/reliability-chart.cy.ts index ae9d7f8b..17a12e50 100644 --- a/packages/app/cypress/e2e/reliability-chart.cy.ts +++ b/packages/app/cypress/e2e/reliability-chart.cy.ts @@ -1,7 +1,7 @@ describe('Reliability Chart', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/reliability'); cy.get('[data-testid="reliability-chart-display"]').should('exist'); @@ -49,7 +49,7 @@ describe('Reliability Chart', () => { describe('Reliability Chart — Content & Interactions', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/reliability'); cy.get('[data-testid="reliability-chart-display"]').should('be.visible'); diff --git a/packages/app/cypress/e2e/sanity.cy.ts b/packages/app/cypress/e2e/sanity.cy.ts index a18e11cc..c44ed128 100644 --- a/packages/app/cypress/e2e/sanity.cy.ts +++ b/packages/app/cypress/e2e/sanity.cy.ts @@ -38,7 +38,7 @@ describe('Page Load & Navigation', () => { it('navigates from the footer to the land acknowledgement page', () => { cy.visit('/', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); @@ -66,7 +66,7 @@ describe('Page Load & Navigation', () => { describe('Theme Toggle', () => { it('theme persists across page reload (localStorage)', () => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); win.localStorage.setItem('theme', 'light'); }); cy.visit('/'); diff --git a/packages/app/cypress/e2e/speed-overlay.cy.ts b/packages/app/cypress/e2e/speed-overlay.cy.ts index dfa64243..9c7a9b89 100644 --- a/packages/app/cypress/e2e/speed-overlay.cy.ts +++ b/packages/app/cypress/e2e/speed-overlay.cy.ts @@ -2,7 +2,7 @@ describe('Bus / Race Car Speed Overlay', () => { before(() => { cy.visit('/inference', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); cy.get('[data-testid="scatter-graph"]').should('be.visible'); @@ -55,7 +55,7 @@ describe('Bus / Race Car Speed Overlay', () => { it('URL param i_speed=1 enables the overlay on first load', () => { cy.visit('/inference?i_speed=1', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); cy.get('[data-testid="scatter-graph"]').should('be.visible'); @@ -69,7 +69,7 @@ describe('Donkey / Elytra Minecraft Overlay', () => { before(() => { cy.visit('/inference', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); cy.get('[data-testid="scatter-graph"]').should('be.visible'); @@ -129,7 +129,7 @@ describe('Donkey / Elytra Minecraft Overlay', () => { it('URL param i_mc=1 enables the minecraft overlay on first load', () => { cy.visit('/inference?i_mc=1', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); cy.get('[data-testid="scatter-graph"]').should('be.visible'); @@ -146,7 +146,7 @@ describe('Y-Axis Metric Search', () => { before(() => { cy.visit('/inference', { onBeforeLoad(win) { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }, }); cy.get('[data-testid="scatter-graph"]').should('be.visible'); diff --git a/packages/app/cypress/e2e/throughput-calculator.cy.ts b/packages/app/cypress/e2e/throughput-calculator.cy.ts index 28df2034..aa4f6f0c 100644 --- a/packages/app/cypress/e2e/throughput-calculator.cy.ts +++ b/packages/app/cypress/e2e/throughput-calculator.cy.ts @@ -6,7 +6,7 @@ describe('TCO Calculator', () => { describe('tab navigation', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/inference'); }); @@ -37,7 +37,7 @@ describe('TCO Calculator', () => { describe('controls, interactions, and features', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/calculator'); cy.get('[data-testid="calculator-bar-chart"] svg .bar').should('have.length.greaterThan', 0); @@ -514,7 +514,7 @@ describe('TCO Calculator', () => { describe('direct URL navigation', () => { it('navigating to /calculator directly loads the calculator tab with data', () => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/calculator'); cy.url().should('include', '/calculator'); diff --git a/packages/app/cypress/e2e/ttft-x-axis-toggle.cy.ts b/packages/app/cypress/e2e/ttft-x-axis-toggle.cy.ts index e17a4aff..ac9d9ccb 100644 --- a/packages/app/cypress/e2e/ttft-x-axis-toggle.cy.ts +++ b/packages/app/cypress/e2e/ttft-x-axis-toggle.cy.ts @@ -1,7 +1,7 @@ describe('TTFT X-Axis Toggle (E2E chart)', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/inference'); cy.get('[data-testid="chart-figure"]').should('have.length.at.least', 2); diff --git a/packages/app/cypress/e2e/url-params.cy.ts b/packages/app/cypress/e2e/url-params.cy.ts index d260f01d..f70e92d1 100644 --- a/packages/app/cypress/e2e/url-params.cy.ts +++ b/packages/app/cypress/e2e/url-params.cy.ts @@ -6,7 +6,7 @@ describe('URL Parameter Persistence', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); }); diff --git a/packages/app/cypress/e2e/yaxis-metrics-render.cy.ts b/packages/app/cypress/e2e/yaxis-metrics-render.cy.ts index 351061eb..77a79694 100644 --- a/packages/app/cypress/e2e/yaxis-metrics-render.cy.ts +++ b/packages/app/cypress/e2e/yaxis-metrics-render.cy.ts @@ -30,7 +30,7 @@ describe('Y-Axis Metrics All Render Data', () => { before(() => { cy.window().then((win) => { - win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now())); + win.localStorage.setItem('inferencex-nudge:github-star-modal', String(Date.now())); }); cy.visit('/inference'); cy.get('[data-testid="scatter-graph"]') diff --git a/packages/app/src/app/(dashboard)/evaluation/page.tsx b/packages/app/src/app/(dashboard)/evaluation/page.tsx index 57411388..f1be9b0d 100644 --- a/packages/app/src/app/(dashboard)/evaluation/page.tsx +++ b/packages/app/src/app/(dashboard)/evaluation/page.tsx @@ -1,6 +1,5 @@ import type { Metadata } from 'next'; -import { EvalSamplesNudge } from '@/components/eval-samples-nudge'; import { EvaluationProvider } from '@/components/evaluation/EvaluationContext'; import EvaluationChartDisplay from '@/components/evaluation/ui/ChartDisplay'; import { tabMetadata } from '@/lib/tab-meta'; @@ -11,7 +10,6 @@ export default function EvaluationPage() { return ( - ); } diff --git a/packages/app/src/app/layout.tsx b/packages/app/src/app/layout.tsx index 93088655..976218da 100644 --- a/packages/app/src/app/layout.tsx +++ b/packages/app/src/app/layout.tsx @@ -12,6 +12,7 @@ import { Header } from '@/components/header/header'; import { CircuitBackground } from '@/components/circuit-background'; import { MinecraftBackgroundLazy } from '@/components/minecraft/minecraft-background-lazy'; import { MinecraftDecorations } from '@/components/minecraft/minecraft-decorations'; +import { NudgeProvider, NudgeRoot } from '@/components/nudges'; import { ThemeProvider } from '@/components/ui/theme-provider'; import { AUTHOR_HANDLE, @@ -191,9 +192,12 @@ export default async function RootLayout({ disableTransitionOnChange > -
-
{children}
-