Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions packages/app/cypress/component/header.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('Header', () => {

it('shows Dashboard nav link', () => {
cy.get('[data-testid="nav-link-dashboard"]').should('be.visible');
cy.get('[data-testid="nav-link-dashboard"]').should('have.attr', 'href', '/');
cy.get('[data-testid="nav-link-dashboard"]').should('have.attr', 'href', '/inference');
});

it('shows Media nav link', () => {
Expand All @@ -52,11 +52,12 @@ describe('Header', () => {
cy.get('[data-testid="theme-toggle"]').should('be.visible');
});

it('shows mobile nav links on small viewports', () => {
it('shows mobile hamburger menu on small viewports', () => {
cy.viewport(375, 812);
cy.get('[data-testid="mobile-nav"]').should('be.visible');
cy.get('[data-testid="mobile-nav"]').contains('Dashboard').should('be.visible');
cy.get('[data-testid="mobile-nav"]').contains('Media').should('be.visible');
cy.get('[data-testid="mobile-nav"]').contains('Supporters').should('be.visible');
cy.get('[data-testid="mobile-menu-toggle"]').should('be.visible');
cy.get('[data-testid="mobile-menu-toggle"]').click();
cy.contains('Dashboard').should('be.visible');
cy.contains('Media').should('be.visible');
cy.contains('Supporters').should('be.visible');
});
});
2 changes: 1 addition & 1 deletion packages/app/cypress/e2e/csv-export.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('CSV Export', () => {
cy.window().then((win) => {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
});
cy.visit('/');
cy.visit('/inference');
cy.get('[data-testid="chart-figure"]').should('exist');
});

Expand Down
2 changes: 1 addition & 1 deletion packages/app/cypress/e2e/custom-user-values.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('Custom User Values', () => {
cy.window().then((win) => {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
});
cy.visit('/');
cy.visit('/inference');
cy.get('[data-testid="model-selector"]').should('be.visible');
});

Expand Down
2 changes: 1 addition & 1 deletion packages/app/cypress/e2e/drill-down-trend.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('Drill-Down Trend Chart Modal', () => {
cy.window().then((win) => {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
});
cy.visit('/');
cy.visit('/inference');
// Wait for scatter graph to render with data points
cy.get('[data-testid="scatter-graph"]')
.first()
Expand Down
6 changes: 3 additions & 3 deletions packages/app/cypress/e2e/favorite-presets.cy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
describe('Favorite Presets', () => {
before(() => {
cy.visit('/', {
cy.visit('/inference', {
onBeforeLoad(win) {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
},
Expand All @@ -18,8 +18,8 @@ describe('Favorite Presets', () => {
cy.get('[data-testid="favorites-panel"]').should('be.visible');
});

it('shows all 6 preset cards', () => {
cy.get('[data-testid^="favorite-preset-"]').should('have.length', 6);
it('shows all 9 preset cards', () => {
cy.get('[data-testid^="favorite-preset-"]').should('have.length', 9);
});

it('each preset card has a title and description', () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/app/cypress/e2e/gpu-power.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ function unlockPowerX() {

describe('PowerX', () => {
beforeEach(() => {
cy.visit('/', {
cy.visit('/inference', {
onBeforeLoad(win) {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
},
Expand All @@ -32,7 +32,7 @@ describe('PowerX', () => {

describe('(unlocked)', () => {
beforeEach(() => {
cy.visit('/', {
cy.visit('/inference', {
onBeforeLoad(win) {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
win.localStorage.setItem('inferencex-powerx-unlocked', '1');
Expand Down
2 changes: 1 addition & 1 deletion packages/app/cypress/e2e/gpu-specs.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ describe('GPU Specs Radar Chart View', () => {

describe('GPU Specs Navigation', () => {
it('tab switcher activates GPU Specs', () => {
cy.visit('/');
cy.visit('/inference');
// Wait for tabs to be rendered and page to be interactive
cy.get('[role="tablist"]').should('be.visible');
// Use force:true to handle potential pointer-events:none from modals/overlays
Expand Down
4 changes: 2 additions & 2 deletions packages/app/cypress/e2e/gradient-labels.cy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
describe('Gradient Labels Toggle', () => {
before(() => {
cy.visit('/', {
cy.visit('/inference', {
onBeforeLoad(win) {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
},
Expand Down Expand Up @@ -117,7 +117,7 @@ describe('Gradient Labels with non-default Y-axis metrics', () => {
};

before(() => {
cy.visit('/', {
cy.visit('/inference', {
onBeforeLoad(win) {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
},
Expand Down
2 changes: 1 addition & 1 deletion packages/app/cypress/e2e/high-contrast.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('High Contrast Mode', () => {
cy.window().then((win) => {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
});
cy.visit('/');
cy.visit('/inference');
cy.get('[data-testid="scatter-graph"]').should('exist');
});

Expand Down
2 changes: 1 addition & 1 deletion packages/app/cypress/e2e/inference-chart.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('Inference Chart', () => {
cy.window().then((win) => {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
});
cy.visit('/');
cy.visit('/inference');
});

it('renders the inference chart display wrapper', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/app/cypress/e2e/model-architecture.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ describe('Model Architecture Diagram', () => {
before(() => {
// Use desktop viewport to ensure all UI elements are visible
cy.viewport(1280, 800);
cy.visit('/', {
cy.visit('/inference', {
onBeforeLoad(win) {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
},
Expand Down
4 changes: 2 additions & 2 deletions packages/app/cypress/e2e/performance.cy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
describe('Performance', () => {
it('page loads quickly', () => {
const startTime = Date.now();
cy.visit('/');
cy.visit('/inference');
cy.document().then(() => {
const loadTime = Date.now() - startTime;
const threshold = 5_000;
Expand All @@ -18,7 +18,7 @@ describe('Performance', () => {
});

it('no excessive layout shift issues', () => {
cy.visit('/');
cy.visit('/inference');
cy.wait(5000);

// Measure CLS using PerformanceObserver
Expand Down
12 changes: 6 additions & 6 deletions packages/app/cypress/e2e/sanity.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

describe('Page Load & Navigation', () => {
before(() => {
cy.visit('/');
cy.visit('/inference');
});

it('page loads with correct title', () => {
Expand All @@ -23,16 +23,16 @@ describe('Page Load & Navigation', () => {
});

// Re-visit to capture errors from a fresh load
cy.visit('/');
cy.visit('/inference');
cy.get('[data-testid="scatter-graph"]').should('exist');
cy.wrap(errors).should('have.length', 0);
});

it('page loads without 404 errors', () => {
cy.visit('/');
cy.visit('/inference');
cy.get('[data-testid="scatter-graph"]').should('exist');
cy.get('h1').should('not.contain.text', '404');
cy.get('h1').should('not.contain.text', 'Not Found');
cy.contains('404').should('not.exist');
cy.contains('Not Found').should('not.exist');
});
});

Expand All @@ -45,7 +45,7 @@ describe('Theme Toggle', () => {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
win.localStorage.setItem('theme', 'light');
});
cy.visit('/');
cy.visit('/inference');
cy.get('[data-testid="theme-toggle"]').click();
cy.get('html').should('have.class', 'dark');
cy.reload();
Expand Down
4 changes: 2 additions & 2 deletions packages/app/cypress/e2e/tabs.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('Chart Section Tabs — E2E', () => {
cy.window().then((win) => {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
});
cy.visit('/');
cy.visit('/inference');
});

it('updates the URL path when switching tabs', () => {
Expand All @@ -28,7 +28,7 @@ describe('Chart Section Tabs — E2E', () => {

it('shows mobile chart select dropdown on small viewport', () => {
cy.viewport(375, 812);
cy.visit('/');
cy.visit('/inference');
cy.get('[data-testid="mobile-chart-select"]').should('be.visible');
});
});
2 changes: 1 addition & 1 deletion packages/app/cypress/e2e/throughput-calculator.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('TCO Calculator', () => {
cy.window().then((win) => {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
});
cy.visit('/');
cy.visit('/inference');
});

it('shows the TCO Calculator tab trigger', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/app/cypress/e2e/ttft-x-axis-toggle.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('TTFT X-Axis Toggle (E2E chart)', () => {
cy.window().then((win) => {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
});
cy.visit('/');
cy.visit('/inference');
cy.get('[data-testid="chart-figure"]').should('have.length.at.least', 2);
});

Expand Down
8 changes: 4 additions & 4 deletions packages/app/cypress/e2e/url-params.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('URL Parameter Persistence', () => {
});

it('page loads without error with unknown params', () => {
cy.visit('/?unknown_param=test');
cy.visit('/inference?unknown_param=test');
cy.get('[data-testid="inference-chart-display"]').should('exist');
});

Expand Down Expand Up @@ -39,7 +39,7 @@ describe('URL Parameter Persistence', () => {
});

it('changing Y-axis metric via dropdown updates SVG axis label', () => {
cy.visit('/');
cy.visit('/inference');

cy.get('[data-testid="scatter-graph"]')
.first()
Expand All @@ -59,7 +59,7 @@ describe('URL Parameter Persistence', () => {
});

it('selecting a Y-axis metric updates the displayed value', () => {
cy.visit('/');
cy.visit('/inference');
cy.get('[data-testid="yaxis-metric-selector"]').click();
cy.get('[role="option"]')
.eq(1)
Expand All @@ -73,7 +73,7 @@ describe('URL Parameter Persistence', () => {
});

it('switching to energy metric updates SVG axis label to joules', () => {
cy.visit('/');
cy.visit('/inference');
cy.get('[data-testid="scatter-graph"]').first().should('be.visible');

cy.get('[data-testid="yaxis-metric-selector"]').click();
Expand Down
2 changes: 1 addition & 1 deletion packages/app/cypress/e2e/yaxis-metrics-render.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('Y-Axis Metrics All Render Data', () => {
cy.window().then((win) => {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
});
cy.visit('/');
cy.visit('/inference');
cy.get('[data-testid="scatter-graph"]')
.first()
.find('svg .dot-group')
Expand Down
59 changes: 52 additions & 7 deletions packages/app/src/app/[[...tab]]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { notFound, redirect } from 'next/navigation';

import { LandingPage } from '@/components/landing/landing-page';
import { PageContent } from '@/components/page-content';
import { TAB_META, VALID_TABS } from '@/lib/tab-meta';
import { LANDING_META, TAB_META, VALID_TABS } from '@/lib/tab-meta';
import { SITE_URL } from '@semianalysisai/inferencex-constants';

export const dynamicParams = true;
Expand All @@ -17,11 +18,30 @@ export async function generateMetadata({
params: Promise<{ tab?: string[] }>;
}): Promise<Metadata> {
const { tab } = await params;
const activeTab = tab?.[0] ?? 'inference';

// Landing page metadata
if (!tab || tab.length === 0) {
return {
title: LANDING_META.title,
description: LANDING_META.description,
alternates: { canonical: SITE_URL },
openGraph: {
title: LANDING_META.title,
description: LANDING_META.description,
url: SITE_URL,
},
twitter: {
title: LANDING_META.title,
description: LANDING_META.description,
},
};
}

const activeTab = tab[0];
const meta = TAB_META[activeTab as keyof typeof TAB_META];
if (!meta) return {};

const url = activeTab === 'inference' ? SITE_URL : `${SITE_URL}/${activeTab}`;
const url = `${SITE_URL}/${activeTab}`;

return {
title: meta.title,
Expand All @@ -39,11 +59,36 @@ export async function generateMetadata({
};
}

export default async function Page({ params }: { params: Promise<{ tab?: string[] }> }) {
export default async function Page({
params,
searchParams,
}: {
params: Promise<{ tab?: string[] }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}) {
const { tab } = await params;
const activeTab = tab?.[0] ?? 'inference';

if (!VALID_TABS.includes(activeTab as (typeof VALID_TABS)[number]) || (tab && tab.length > 1)) {
// Landing page at /
if (!tab || tab.length === 0) {
// Backward compat: if / has chart query params, redirect to /inference with them
const search = await searchParams;
const hasChartParams = Object.keys(search).some(
(k) => k.startsWith('g_') || k.startsWith('i_') || k.startsWith('e_') || k.startsWith('r_'),
);
if (hasChartParams) {
const qs = new URLSearchParams(
Object.entries(search).flatMap(([k, v]) =>
Array.isArray(v) ? v.map((val) => [k, val]) : v != null ? [[k, v]] : [],
),
).toString();
redirect(`/inference?${qs}`);
}
return <LandingPage />;
}

const activeTab = tab[0];

if (!VALID_TABS.includes(activeTab as (typeof VALID_TABS)[number]) || tab.length > 1) {
notFound();
}

Expand Down
15 changes: 15 additions & 0 deletions packages/app/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -353,3 +353,18 @@
.star-button-glow {
animation: star-glow 2s ease-in-out infinite;
}

/* CTA button glow animation - brand colored */
@keyframes cta-glow {
0%,
100% {
box-shadow: none;
}
50% {
box-shadow: 0 0 20px 6px oklch(65% 0.18 250 / 60%);
}
}

.cta-button-glow {
animation: cta-glow 2s ease-in-out infinite;
}
Loading
Loading