Skip to content

Commit 7e217e2

Browse files
authored
refactor(studio): split routes/index into per-domain route groups (#355)
* refactor(studio): split routes/index into per-domain route groups Break the ~770-line routes/index.tsx into one feature-gated route module per domain under routes/groups/, leaving index.tsx as a thin composition root that spreads the groups into the workspace route tree. Each group owns its own lazy component definitions and exports a fully gated RouteObject[]. Hoist the lazy-load Suspense boundary to the single wrapper around the workspace Outlet rather than repeating it per route. Signed-off-by: mschwab <mschwab@nvidia.com> * chore: use type-only import for RouteObject across route files RouteObject is only used as a type annotation. Convert all imports to import type to follow TypeScript best practices. Signed-off-by: mschwab <mschwab@nvidia.com> --------- Signed-off-by: mschwab <mschwab@nvidia.com>
1 parent f228dd7 commit 7e217e2

21 files changed

Lines changed: 801 additions & 705 deletions
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { ErrorPanel } from '@studio/components/ErrorPanel';
5+
import { AGENTS_ENABLED } from '@studio/constants/environment';
6+
import { ROUTES } from '@studio/constants/routes';
7+
import { agentsRoutes } from '@studio/routes/utils';
8+
import { lazy } from 'react';
9+
import type { RouteObject } from 'react-router-dom';
10+
11+
const AgentsListRoute =
12+
AGENTS_ENABLED &&
13+
lazy(() =>
14+
import('@studio/routes/agents/AgentsListRoute').then((m) => ({
15+
default: m.AgentsListRoute,
16+
}))
17+
);
18+
const AgentOptimizationsRoute =
19+
AGENTS_ENABLED &&
20+
lazy(() =>
21+
import('@studio/routes/agents/AgentSuggestionsRoute').then((m) => ({
22+
default: m.AgentOptimizationsRoute,
23+
}))
24+
);
25+
const AgentMonitorRoute =
26+
AGENTS_ENABLED &&
27+
lazy(() =>
28+
import('@studio/routes/agents/AgentMonitorRoute').then((m) => ({
29+
default: m.AgentMonitorRoute,
30+
}))
31+
);
32+
const AgentEvaluationsListRoute =
33+
AGENTS_ENABLED &&
34+
lazy(() =>
35+
import('@studio/routes/agents/AgentEvaluationsRoute').then((m) => ({
36+
default: m.AgentEvaluationsListRoute,
37+
}))
38+
);
39+
const AgentEvaluationDetailRoute =
40+
AGENTS_ENABLED &&
41+
lazy(() =>
42+
import('@studio/routes/agents/AgentEvaluationsRoute').then((m) => ({
43+
default: m.AgentEvaluationDetailRoute,
44+
}))
45+
);
46+
47+
export const agentRoutes: RouteObject[] = agentsRoutes([
48+
{
49+
path: ROUTES.workspace.agentsList,
50+
element: AgentsListRoute ? <AgentsListRoute /> : null,
51+
errorElement: <ErrorPanel title="Agents" />,
52+
},
53+
{
54+
path: ROUTES.workspace.agentOptimizations,
55+
element: AgentOptimizationsRoute ? <AgentOptimizationsRoute /> : null,
56+
errorElement: <ErrorPanel title="Optimizations" />,
57+
},
58+
{
59+
path: ROUTES.workspace.agentMonitor,
60+
element: AgentMonitorRoute ? <AgentMonitorRoute /> : null,
61+
errorElement: <ErrorPanel title="Monitor" />,
62+
},
63+
{
64+
path: ROUTES.workspace.agentEvaluationsList,
65+
element: AgentEvaluationsListRoute ? <AgentEvaluationsListRoute /> : null,
66+
errorElement: <ErrorPanel title="Agent Evaluations" />,
67+
},
68+
{
69+
path: ROUTES.workspace.agentEvaluationDetail,
70+
element: AgentEvaluationDetailRoute ? <AgentEvaluationDetailRoute /> : null,
71+
errorElement: <ErrorPanel title="Agent Evaluation" />,
72+
},
73+
{
74+
path: ROUTES.workspace.agentDetail,
75+
element: AgentsListRoute ? <AgentsListRoute /> : null,
76+
errorElement: <ErrorPanel title="Agents" />,
77+
},
78+
]);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { ROUTES } from '@studio/constants/routes';
5+
import { gateBaseModelsRoutes } from '@studio/routes/utils';
6+
import { lazy } from 'react';
7+
import type { RouteObject } from 'react-router-dom';
8+
9+
const WorkspaceBaseModelsRoute = lazy(() =>
10+
import('@studio/routes/WorkspaceBaseModelsRoute').then((module) => ({
11+
default: module.WorkspaceBaseModelsRoute,
12+
}))
13+
);
14+
15+
export const baseModelsRoutes: RouteObject[] = gateBaseModelsRoutes([
16+
{
17+
path: ROUTES.workspace.baseModels,
18+
element: <WorkspaceBaseModelsRoute />,
19+
},
20+
{
21+
path: ROUTES.workspace.baseModelsModel,
22+
element: <WorkspaceBaseModelsRoute />,
23+
},
24+
]);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { ErrorPanel } from '@studio/components/ErrorPanel';
5+
import { ROUTES } from '@studio/constants/routes';
6+
import { gateCustomizationRoutes } from '@studio/routes/utils';
7+
import { lazy } from 'react';
8+
import type { RouteObject } from 'react-router-dom';
9+
10+
const PromptTuningFormRoute = lazy(() =>
11+
import('@studio/routes/PromptTuningFormRoute/index').then((module) => ({
12+
default: module.PromptTuningFormRoute,
13+
}))
14+
);
15+
const CustomizationJobListRoute = lazy(() =>
16+
import('@studio/routes/CustomizationJobListRoute').then((module) => ({
17+
default: module.CustomizationJobListRoute,
18+
}))
19+
);
20+
const CustomizationJobDetailsRoute = lazy(() =>
21+
import('@studio/routes/CustomizationJobDetailsRoute').then((module) => ({
22+
default: module.CustomizationJobDetailsRoute,
23+
}))
24+
);
25+
const NewCustomizationRoute = lazy(() =>
26+
import('@studio/routes/NewCustomizationRoute').then((module) => ({
27+
default: module.NewCustomizationRoute,
28+
}))
29+
);
30+
31+
export const customizationRoutes: RouteObject[] = gateCustomizationRoutes([
32+
{
33+
path: ROUTES.workspace.promptTuningForm,
34+
element: <PromptTuningFormRoute />,
35+
errorElement: <ErrorPanel title="Customizer" />,
36+
},
37+
{
38+
path: ROUTES.workspace.customizationJobList,
39+
element: <CustomizationJobListRoute />,
40+
errorElement: <ErrorPanel title="Customizer" />,
41+
},
42+
{
43+
path: ROUTES.workspace.customizationJobDetails,
44+
element: <CustomizationJobDetailsRoute />,
45+
errorElement: <ErrorPanel title="Customizer" />,
46+
},
47+
{
48+
path: ROUTES.workspace.newCustomizationJob,
49+
element: <NewCustomizationRoute />,
50+
errorElement: <ErrorPanel title="Customizer" />,
51+
},
52+
]);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { ErrorPanel } from '@studio/components/ErrorPanel';
5+
import { CODING_AGENT_STUDIO_ENABLED } from '@studio/constants/environment';
6+
import { ROUTES } from '@studio/constants/routes';
7+
import { gateCodingAgentStudioRoutes, gateDashboardRoutes } from '@studio/routes/utils';
8+
import { lazy } from 'react';
9+
import type { RouteObject } from 'react-router-dom';
10+
11+
const DashboardLandingRoute = lazy(() =>
12+
import('@studio/routes/DashboardLandingRoute').then((module) => ({
13+
default: module.DashboardLandingRoute,
14+
}))
15+
);
16+
const WorkspaceDashboardRoute = lazy(() =>
17+
import('@studio/routes/WorkspaceDashboardRoute').then((module) => ({
18+
default: module.WorkspaceDashboardRoute,
19+
}))
20+
);
21+
const ClaudeCodeChatRoute = lazy(() =>
22+
import('@studio/routes/agents/ClaudeCodeChatRoute').then((m) => ({
23+
default: m.ClaudeCodeChatRoute,
24+
}))
25+
);
26+
27+
export const dashboardRoutes: RouteObject[] = gateDashboardRoutes([
28+
{
29+
path: ROUTES.workspace.dashboard,
30+
element: CODING_AGENT_STUDIO_ENABLED ? <DashboardLandingRoute /> : <WorkspaceDashboardRoute />,
31+
errorElement: <ErrorPanel title="Workspace" />,
32+
},
33+
...gateCodingAgentStudioRoutes([
34+
{
35+
path: ROUTES.workspace.claudeCodeChat,
36+
element: <ClaudeCodeChatRoute />,
37+
errorElement: <ErrorPanel title="Claude Code" />,
38+
},
39+
]),
40+
]);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { ErrorPanel } from '@studio/components/ErrorPanel';
5+
import { DATA_DESIGNER_ENABLED } from '@studio/constants/environment';
6+
import { ROUTES } from '@studio/constants/routes';
7+
import { gateDataDesignerRoutes } from '@studio/routes/utils';
8+
import { lazy } from 'react';
9+
import type { RouteObject } from 'react-router-dom';
10+
11+
const DataDesignerJobListRoute =
12+
DATA_DESIGNER_ENABLED &&
13+
lazy(() =>
14+
import('@studio/routes/DataDesignerJobListRoute').then((m) => ({
15+
default: m.DataDesignerJobListRoute,
16+
}))
17+
);
18+
const DataDesignerJobDetailsRoute =
19+
DATA_DESIGNER_ENABLED &&
20+
lazy(() =>
21+
import('@studio/routes/DataDesignerJobDetailsRoute').then((m) => ({
22+
default: m.DataDesignerJobDetailsRoute,
23+
}))
24+
);
25+
const NewDataDesignerJobRoute =
26+
DATA_DESIGNER_ENABLED &&
27+
lazy(() =>
28+
import('@studio/routes/NewDataDesignerJobRoute').then((m) => ({
29+
default: m.NewDataDesignerJobRoute,
30+
}))
31+
);
32+
33+
export const dataDesignerRoutes: RouteObject[] = gateDataDesignerRoutes([
34+
{
35+
path: ROUTES.workspace.dataDesignerJobList,
36+
element: DataDesignerJobListRoute ? <DataDesignerJobListRoute /> : null,
37+
errorElement: <ErrorPanel title="Data Designer" />,
38+
},
39+
{
40+
path: ROUTES.workspace.dataDesignerJobDetails,
41+
element: DataDesignerJobDetailsRoute ? <DataDesignerJobDetailsRoute /> : null,
42+
errorElement: <ErrorPanel title="Data Designer" />,
43+
},
44+
{
45+
path: ROUTES.workspace.dataDesignerJobNew,
46+
element: NewDataDesignerJobRoute ? <NewDataDesignerJobRoute /> : null,
47+
errorElement: <ErrorPanel title="Data Designer" />,
48+
},
49+
]);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { ErrorPanel } from '@studio/components/ErrorPanel';
5+
import { DEPLOYMENTS_ENABLED } from '@studio/constants/environment';
6+
import { ROUTES } from '@studio/constants/routes';
7+
import { gateDeploymentsRoutes } from '@studio/routes/utils';
8+
import { lazy } from 'react';
9+
import type { RouteObject } from 'react-router-dom';
10+
11+
const DeploymentsListRoute =
12+
DEPLOYMENTS_ENABLED &&
13+
lazy(() =>
14+
import('@studio/routes/DeploymentsListRoute').then((module) => ({
15+
default: module.DeploymentsListRoute,
16+
}))
17+
);
18+
19+
export const deploymentRoutes: RouteObject[] = gateDeploymentsRoutes([
20+
{
21+
path: ROUTES.workspace.deployments,
22+
element: DeploymentsListRoute ? <DeploymentsListRoute /> : null,
23+
errorElement: <ErrorPanel title="Deployments" />,
24+
},
25+
{
26+
path: ROUTES.workspace.deploymentsDeployment,
27+
element: DeploymentsListRoute ? <DeploymentsListRoute /> : null,
28+
errorElement: <ErrorPanel title="Deployments" />,
29+
},
30+
]);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { ErrorPanel } from '@studio/components/ErrorPanel';
5+
import { ROUTES } from '@studio/constants/routes';
6+
import { gateEvaluationBenchmarksRoutes, gateEvaluationRoutes } from '@studio/routes/utils';
7+
import { lazy } from 'react';
8+
import { Navigate, RouteObject } from 'react-router-dom';
9+
10+
const EvaluationLayout = lazy(() =>
11+
import('@studio/routes/evaluation/EvaluationLayout').then((module) => ({
12+
default: module.EvaluationLayout,
13+
}))
14+
);
15+
const EvaluationResultsLayout = lazy(() =>
16+
import('@studio/routes/evaluation/EvaluationResultsLayout').then((module) => ({
17+
default: module.EvaluationResultsLayout,
18+
}))
19+
);
20+
const EvaluationResultsRoute = lazy(() =>
21+
import('@studio/routes/evaluation/EvaluationResultsRoute').then((module) => ({
22+
default: module.EvaluationResultsRoute,
23+
}))
24+
);
25+
const EvaluationResultDetailsRoute = lazy(() =>
26+
import('@studio/routes/evaluation/EvaluationResultDetailsRoute').then((module) => ({
27+
default: module.EvaluationResultDetailsRoute,
28+
}))
29+
);
30+
31+
export const evaluationRoutes: RouteObject[] = gateEvaluationRoutes([
32+
{
33+
path: ROUTES.workspace.evaluation,
34+
element: <EvaluationLayout />,
35+
errorElement: <ErrorPanel title="Evaluator" />,
36+
children: [
37+
{
38+
index: true,
39+
element: <Navigate to="results" replace />,
40+
},
41+
...gateEvaluationBenchmarksRoutes([]),
42+
],
43+
},
44+
{
45+
path: ROUTES.workspace.evaluationResultDetails,
46+
element: <EvaluationResultDetailsRoute />,
47+
errorElement: <ErrorPanel title="Evaluator" />,
48+
},
49+
{
50+
path: ROUTES.workspace.evaluationResults,
51+
element: <EvaluationResultsLayout />,
52+
errorElement: <ErrorPanel title="Evaluator" />,
53+
children: [
54+
{
55+
index: true,
56+
element: <EvaluationResultsRoute />,
57+
},
58+
],
59+
},
60+
]);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { ErrorPanel } from '@studio/components/ErrorPanel';
5+
import { ROUTES } from '@studio/constants/routes';
6+
import { gateExperimentRoutes } from '@studio/routes/utils';
7+
import { lazy } from 'react';
8+
import type { RouteObject } from 'react-router-dom';
9+
10+
const ExperimentRoute = lazy(() =>
11+
import('@studio/routes/ExperimentRoute').then((module) => ({
12+
default: module.ExperimentRoute,
13+
}))
14+
);
15+
const ExperimentGroupDetailRoute = lazy(() =>
16+
import('@studio/routes/ExperimentGroupDetailRoute').then((module) => ({
17+
default: module.ExperimentGroupDetailRoute,
18+
}))
19+
);
20+
const ExperimentDetailRoute = lazy(() =>
21+
import('@studio/routes/ExperimentDetailRoute').then((module) => ({
22+
default: module.ExperimentDetailRoute,
23+
}))
24+
);
25+
26+
export const experimentRoutes: RouteObject[] = gateExperimentRoutes([
27+
{
28+
path: ROUTES.workspace.experiment,
29+
element: <ExperimentRoute />,
30+
errorElement: <ErrorPanel title="Experiment" />,
31+
},
32+
{
33+
path: ROUTES.workspace.experimentGroupDetail,
34+
element: <ExperimentGroupDetailRoute />,
35+
errorElement: <ErrorPanel title="Experiment Group" />,
36+
},
37+
{
38+
path: ROUTES.workspace.experimentDetail,
39+
element: <ExperimentDetailRoute />,
40+
errorElement: <ErrorPanel title="Experiment" />,
41+
},
42+
]);

0 commit comments

Comments
 (0)