diff --git a/ui/litellm-dashboard/src/app/(dashboard)/access-groups/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/access-groups/page.tsx
new file mode 100644
index 00000000000..b73785dd12c
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/access-groups/page.tsx
@@ -0,0 +1,7 @@
+"use client";
+
+import { AccessGroupsPage } from "@/components/AccessGroups/AccessGroupsPage";
+
+export default function AccessGroupsRoute() {
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/budgets/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/budgets/page.tsx
new file mode 100644
index 00000000000..ab85af82de3
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/budgets/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import BudgetPanel from "@/components/budgets/budget_panel";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function BudgetsRoute() {
+ const { accessToken } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/caching/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/caching/page.tsx
new file mode 100644
index 00000000000..59749571d1a
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/caching/page.tsx
@@ -0,0 +1,17 @@
+"use client";
+
+import CacheDashboard from "@/components/cache_dashboard";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function CachingRoute() {
+ const { accessToken, userId, userRole, token, premiumUser } = useAuthorized();
+ return (
+
+ );
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/page.tsx
new file mode 100644
index 00000000000..0879fafa142
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-tracking/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import { CostTrackingSettings } from "@/components/CostTrackingSettings";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function CostTrackingRoute() {
+ const { accessToken, userId, userRole } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/page.tsx
new file mode 100644
index 00000000000..ad8446d13fa
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import GuardrailsMonitorView from "@/components/GuardrailsMonitor/GuardrailsMonitorView";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function GuardrailsMonitorRoute() {
+ const { accessToken } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/page.tsx
new file mode 100644
index 00000000000..96da8b5f234
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import GuardrailsPanel from "@/components/guardrails";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function GuardrailsRoute() {
+ const { accessToken, userRole } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/logs/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/logs/page.tsx
new file mode 100644
index 00000000000..6a91df11344
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/logs/page.tsx
@@ -0,0 +1,17 @@
+"use client";
+
+import SpendLogsTable from "@/components/view_logs";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function LogsRoute() {
+ const { accessToken, userId, userRole, token, premiumUser } = useAuthorized();
+ return (
+
+ );
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/page.tsx
new file mode 100644
index 00000000000..f3267ccea7f
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import { MCPServers } from "@/components/mcp_tools";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function McpServersRoute() {
+ const { accessToken, userId, userRole } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/memory/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/memory/page.tsx
new file mode 100644
index 00000000000..9830799db58
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/memory/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import { MemoryView } from "@/components/MemoryView";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function MemoryRoute() {
+ const { accessToken, userId, userRole } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/policies/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/policies/page.tsx
new file mode 100644
index 00000000000..c989655542c
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/policies/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import PoliciesPanel from "@/components/policies";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function PoliciesRoute() {
+ const { accessToken, userRole } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/projects/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/projects/page.tsx
new file mode 100644
index 00000000000..272e1961522
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/projects/page.tsx
@@ -0,0 +1,7 @@
+"use client";
+
+import { ProjectsPage } from "@/components/Projects/ProjectsPage";
+
+export default function ProjectsRoute() {
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/prompts/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/prompts/page.tsx
new file mode 100644
index 00000000000..d59255f11dc
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/prompts/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import PromptsPanel from "@/components/prompts";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function PromptsRoute() {
+ const { accessToken, userRole } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/search-tools/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/search-tools/page.tsx
new file mode 100644
index 00000000000..9d0f97cd78a
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/search-tools/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import { SearchTools } from "@/components/SearchTools";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function SearchToolsRoute() {
+ const { accessToken, userId, userRole } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/skills/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/skills/page.tsx
new file mode 100644
index 00000000000..4d8a6247a2c
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/skills/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import ClaudeCodePluginsPanel from "@/components/claude_code_plugins";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function SkillsRoute() {
+ const { accessToken, userRole } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/tag-management/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/tag-management/page.tsx
new file mode 100644
index 00000000000..63234d18a03
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/tag-management/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import TagManagement from "@/components/tag_management";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function TagManagementRoute() {
+ const { accessToken, userId, userRole } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/tool-policies/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/tool-policies/page.tsx
new file mode 100644
index 00000000000..2b4f99d507d
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/tool-policies/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import ToolPoliciesView from "@/components/ToolPoliciesView";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function ToolPoliciesRoute() {
+ const { accessToken, userRole } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/transform-request/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/transform-request/page.tsx
new file mode 100644
index 00000000000..3d380491788
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/transform-request/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import TransformRequestPanel from "@/components/transform_request";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function TransformRequestRoute() {
+ const { accessToken } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/ui-theme/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/ui-theme/page.tsx
new file mode 100644
index 00000000000..c848c3b7225
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/ui-theme/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import UIThemeSettings from "@/components/ui_theme_settings";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function UiThemeRoute() {
+ const { accessToken, userId, userRole } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/page.tsx
new file mode 100644
index 00000000000..5a273dc8154
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import VectorStoreManagement from "@/components/vector_store_management";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function VectorStoresRoute() {
+ const { accessToken, userId, userRole } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/workflows/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/workflows/page.tsx
new file mode 100644
index 00000000000..c7a89d608ee
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/workflows/page.tsx
@@ -0,0 +1,9 @@
+"use client";
+
+import WorkflowRuns from "@/components/workflow_runs";
+import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
+
+export default function WorkflowsRoute() {
+ const { accessToken } = useAuthorized();
+ return ;
+}
diff --git a/ui/litellm-dashboard/src/app/page.tsx b/ui/litellm-dashboard/src/app/page.tsx
index 12dd39a1c21..40792453c5d 100644
--- a/ui/litellm-dashboard/src/app/page.tsx
+++ b/ui/litellm-dashboard/src/app/page.tsx
@@ -5,18 +5,10 @@ import OldModelDashboard from "@/app/(dashboard)/models-and-endpoints/ModelsAndE
import PlaygroundPage from "@/app/(dashboard)/playground/page";
import AdminPanel from "@/components/AdminPanel";
import AgentsPanel from "@/components/agents";
-import BudgetPanel from "@/components/budgets/budget_panel";
-import CacheDashboard from "@/components/cache_dashboard";
-import ClaudeCodePluginsPanel from "@/components/claude_code_plugins";
import { teamListCall as v2TeamListCall } from "@/app/(dashboard)/hooks/teams/useTeams";
import LoadingScreen from "@/components/common_components/LoadingScreen";
-import { CostTrackingSettings } from "@/components/CostTrackingSettings";
import GeneralSettings from "@/components/general_settings";
-import GuardrailsMonitorView from "@/components/GuardrailsMonitor/GuardrailsMonitorView";
-import GuardrailsPanel from "@/components/guardrails";
-import PoliciesPanel from "@/components/policies";
import { Team } from "@/components/key_team_helpers/key_list";
-import { MCPServers } from "@/components/mcp_tools";
import ModelHubTable from "@/components/AIHub/ModelHubTable";
import Navbar from "@/components/navbar";
import { Organization, proxyBaseUrl, getInProductNudgesCall } from "@/components/networking";
@@ -25,23 +17,11 @@ import OldTeams from "@/components/OldTeams";
import { fetchUserModels, CreateKeyPrefillData } from "@/components/organisms/create_key_button";
import Organizations, { fetchOrganizations } from "@/components/organizations";
import PassThroughSettings from "@/components/pass_through_settings";
-import PromptsPanel from "@/components/prompts";
import PublicModelHub from "@/components/public_model_hub";
-import { SearchTools } from "@/components/SearchTools";
import Settings from "@/components/settings";
import { SurveyPrompt, SurveyModal, ClaudeCodePrompt, ClaudeCodeModal } from "@/components/survey";
-import TagManagement from "@/components/tag_management";
-import TransformRequestPanel from "@/components/transform_request";
-import UIThemeSettings from "@/components/ui_theme_settings";
import Usage from "@/components/usage";
import UserDashboard from "@/components/user_dashboard";
-import { AccessGroupsPage } from "@/components/AccessGroups/AccessGroupsPage";
-import { ProjectsPage } from "@/components/Projects/ProjectsPage";
-import VectorStoreManagement from "@/components/vector_store_management";
-import ToolPoliciesView from "@/components/ToolPoliciesView";
-import { MemoryView } from "@/components/MemoryView";
-import WorkflowRuns from "@/components/workflow_runs";
-import SpendLogsTable from "@/components/view_logs";
import ViewUserDashboard from "@/components/view_users";
import { ThemeProvider } from "@/contexts/ThemeContext";
import { useAuth } from "@/contexts/AuthContext";
@@ -442,18 +422,8 @@ function CreateKeyPageContent() {
) : page == "logging-and-alerts" ? (
- ) : page == "budgets" ? (
-
- ) : page == "guardrails" ? (
-
- ) : page == "policies" ? (
-
) : page == "agents" ? (
- ) : page == "prompts" ? (
-
- ) : page == "transform-request" ? (
-
) : page == "router-settings" ? (
- ) : page == "ui-theme" ? (
-
- ) : page == "cost-tracking" ? (
-
) : page == "model-hub-table" ? (
isAdminRole(userRole) ? (
)
- ) : page == "caching" ? (
-
) : page == "pass-through-settings" ? (
- ) : page == "logs" ? (
-
- ) : page == "mcp-servers" ? (
-
- ) : page == "search-tools" ? (
-
- ) : page == "tag-management" ? (
-
- ) : page == "skills" || page == "claude-code-plugins" ? (
-
- ) : page == "access-groups" ? (
-
- ) : page == "projects" ? (
-
- ) : page == "vector-stores" ? (
-
- ) : page == "tool-policies" ? (
-
- ) : page == "workflows" ? (
-
- ) : page == "memory" ? (
-
- ) : page == "guardrails-monitor" ? (
-
) : page == "new_usage" ? (
{
expect(legacyKeyForPathname("/ui/api-reference")).toBeNull();
});
});
+
+describe("MIGRATED_PAGES leaf cutover", () => {
+ beforeEach(() => {
+ vi.resetModules();
+ });
+
+ it("routes every migrated leaf page to its segment and back to a sidebar key", async () => {
+ vi.doMock("@/components/networking", () => ({ serverRootPath: "/" }));
+ const { MIGRATED_PAGES, legacyKeyForPathname } = await import("./migratedPages");
+
+ const cases: [string, string][] = [
+ ["budgets", "budgets"],
+ ["caching", "caching"],
+ ["cost-tracking", "cost-tracking"],
+ ["guardrails", "guardrails"],
+ ["guardrails-monitor", "guardrails-monitor"],
+ ["logs", "logs"],
+ ["mcp-servers", "mcp-servers"],
+ ["memory", "memory"],
+ ["policies", "policies"],
+ ["projects", "projects"],
+ ["prompts", "prompts"],
+ ["search-tools", "search-tools"],
+ ["skills", "skills"],
+ ["claude-code-plugins", "skills"],
+ ["tag-management", "tag-management"],
+ ["tool-policies", "tool-policies"],
+ ["transform-request", "transform-request"],
+ ["ui-theme", "ui-theme"],
+ ["vector-stores", "vector-stores"],
+ ["workflows", "workflows"],
+ ["access-groups", "access-groups"],
+ ];
+ for (const [key, seg] of cases) {
+ expect(MIGRATED_PAGES[key]).toBe(seg);
+ expect(legacyKeyForPathname(`/ui/${seg}`)).not.toBeNull();
+ expect(legacyKeyForPathname(`/ui/${seg}/`)).not.toBeNull();
+ }
+
+ // The skills alias resolves to the "skills" sidebar key, not "claude-code-plugins".
+ expect(legacyKeyForPathname("/ui/skills")).toBe("skills");
+ expect(legacyKeyForPathname("/ui/budgets")).toBe("budgets");
+ });
+});
diff --git a/ui/litellm-dashboard/src/utils/migratedPages.ts b/ui/litellm-dashboard/src/utils/migratedPages.ts
index 2c27e4fee64..e1be807037b 100644
--- a/ui/litellm-dashboard/src/utils/migratedPages.ts
+++ b/ui/litellm-dashboard/src/utils/migratedPages.ts
@@ -12,6 +12,27 @@ export const MIGRATED_PAGES: Record = {
api_ref: "api-reference",
// Legacy alias: older bookmarks used the hyphenated ?page=api-reference form.
"api-reference": "api-reference",
+ budgets: "budgets",
+ caching: "caching",
+ "cost-tracking": "cost-tracking",
+ guardrails: "guardrails",
+ "guardrails-monitor": "guardrails-monitor",
+ logs: "logs",
+ "mcp-servers": "mcp-servers",
+ memory: "memory",
+ policies: "policies",
+ projects: "projects",
+ prompts: "prompts",
+ "search-tools": "search-tools",
+ skills: "skills",
+ "claude-code-plugins": "skills",
+ "tag-management": "tag-management",
+ "tool-policies": "tool-policies",
+ "transform-request": "transform-request",
+ "ui-theme": "ui-theme",
+ "vector-stores": "vector-stores",
+ workflows: "workflows",
+ "access-groups": "access-groups",
};
function uiBase(): string {