{title}
+{description}
+ {actionHref && actionText && ( +diff --git a/src/App.tsx b/src/App.tsx
index 8079d24..3918f07 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,69 +1,86 @@
-import { useEffect } from "react";
+import { useEffect, lazy, useRef } from "react";
import { Navigate, createBrowserRouter, useParams } from "react-router";
import { RouterProvider } from "react-router/dom";
import { getSavedThemeId, getThemeById, applyTheme, defaultThemeId } from "@/lib/theme";
+import { pushFaroMeasurement } from "@/faro";
+
+// Eager imports — app shell (always needed)
import RootLayout from "@/app/root-layout";
-
-import AuthLayout from "@/page/auth/layout";
-import LoginPage from "@/page/auth/login";
-import RegisterPage from "@/page/auth/register";
-import ForgotPasswordPage from "@/page/auth/forgot-password";
-import ResetPasswordPage from "@/page/auth/reset-password";
import { PersonalShell, WorkspaceShell, SettingsShell } from "@/components/shell/navshell";
-import WorkspaceRepositoriesPage from "@/page/workspace/repositories";
-import WorkspaceIssuesPage from "@/page/workspace/issues";
-import IssueDetailPage from "@/page/workspace/issues/detail";
-import RepoLayout, { RepoIndexRedirect } from "@/page/workspace/repo/layout";
-import CodeTab from "@/page/workspace/repo/code";
-import CommitsTab from "@/page/workspace/repo/commits";
-import BranchesTab from "@/page/workspace/repo/branches";
-import TagsTab from "@/page/workspace/repo/tags";
-import PullsTab from "@/page/workspace/repo/pulls";
-import ContributorsTab from "@/page/workspace/repo/contributors";
-import WebhooksTab from "@/page/workspace/repo/webhooks";
-import RepoSettingsTab from "@/page/workspace/repo/settings";
-import ReadmePage from "@/page/workspace/repo/readme-page";
-import CommitDetailPage from "@/page/workspace/repo/commit-detail";
-import PullCreatePage from "@/page/workspace/repo/pull-create";
-import PullDetailPage from "@/page/workspace/repo/pull-detail";
-import WorkspaceSettingsPage from "@/page/workspace/settings";
-import ChannelPage from "@/page/workspace/channel";
-import WorkplanChatList from "@/page/workspace/workplan/chat-list";
-import WorkplanChatConversation from "@/page/workspace/workplan/chat-conversation";
-import MeOverviewPage from "@/page/me/overview";
-import MeReposPage from "@/page/me/repos";
-import MeChatListPage from "@/page/me/chat-list.tsx";
-import MeChatConversationPage from "@/page/me/chat-conversation.tsx";
-import MeNotificationsPage from "@/page/me/notifications";
-import MeStarsPage from "@/page/me/stars";
-import MeFollowingPage from "@/page/me/following";
-import SettingsProfilePage from "@/page/settings/profile";
-import SettingsAppearancePage from "@/page/settings/appearance";
-import SettingsNotificationsPage from "@/page/settings/notifications";
-import SettingsPrivacyPage from "@/page/settings/privacy";
-import SettingsAccessibilityPage from "@/page/settings/accessibility";
-import SettingsSecurityPage from "@/page/settings/security";
-import SettingsTokensPage from "@/page/settings/tokens";
-import SettingsSshKeysPage from "@/page/settings/ssh-keys";
-import LandingLayout from "@/page/landing/layout";
-import LandingHome from "@/page/landing/home";
-import FeaturesPage from "@/page/landing/features";
-import WorkflowPage from "@/page/landing/workflow";
-import PricingPage from "@/page/landing/pricing";
+// Lazy-loaded pages — code-split by route
+const AuthLayout = lazy(() => import("@/page/auth/layout"));
+const LoginPage = lazy(() => import("@/page/auth/login"));
+const RegisterPage = lazy(() => import("@/page/auth/register"));
+const ForgotPasswordPage = lazy(() => import("@/page/auth/forgot-password"));
+const ResetPasswordPage = lazy(() => import("@/page/auth/reset-password"));
+const WorkspaceRepositoriesPage = lazy(() => import("@/page/workspace/repositories"));
+const WorkspaceIssuesPage = lazy(() => import("@/page/workspace/issues"));
+const IssueDetailPage = lazy(() => import("@/page/workspace/issues/detail"));
+const RepoLayout = lazy(() => import("@/page/workspace/repo/layout"));
+const RepoIndexRedirect = lazy(() =>
+ import("@/page/workspace/repo/layout").then((m) => ({ default: m.RepoIndexRedirect })),
+);
+const CodeTab = lazy(() => import("@/page/workspace/repo/code"));
+const CommitsTab = lazy(() => import("@/page/workspace/repo/commits"));
+const BranchesTab = lazy(() => import("@/page/workspace/repo/branches"));
+const TagsTab = lazy(() => import("@/page/workspace/repo/tags"));
+const PullsTab = lazy(() => import("@/page/workspace/repo/pulls"));
+const ContributorsTab = lazy(() => import("@/page/workspace/repo/contributors"));
+const WebhooksTab = lazy(() => import("@/page/workspace/repo/webhooks"));
+const RepoSettingsTab = lazy(() => import("@/page/workspace/repo/settings"));
+const ReadmePage = lazy(() => import("@/page/workspace/repo/readme-page"));
+const CommitDetailPage = lazy(() => import("@/page/workspace/repo/commit-detail"));
+const PullCreatePage = lazy(() => import("@/page/workspace/repo/pull-create"));
+const PullDetailPage = lazy(() => import("@/page/workspace/repo/pull-detail"));
+const WorkspaceSettingsPage = lazy(() => import("@/page/workspace/settings"));
+const ChannelPage = lazy(() => import("@/page/workspace/channel"));
+const WorkplanChatList = lazy(() => import("@/page/workspace/workplan/chat-list"));
+const WorkplanChatConversation = lazy(() => import("@/page/workspace/workplan/chat-conversation"));
+const MeOverviewPage = lazy(() => import("@/page/me/overview"));
+const MeReposPage = lazy(() => import("@/page/me/repos"));
+const MeChatListPage = lazy(() => import("@/page/me/chat-list"));
+const MeChatConversationPage = lazy(() => import("@/page/me/chat-conversation"));
+const MeNotificationsPage = lazy(() => import("@/page/me/notifications"));
+const MeStarsPage = lazy(() => import("@/page/me/stars"));
+const MeFollowingPage = lazy(() => import("@/page/me/following"));
+const SettingsProfilePage = lazy(() => import("@/page/settings/profile"));
+const SettingsAppearancePage = lazy(() => import("@/page/settings/appearance"));
+const SettingsNotificationsPage = lazy(() => import("@/page/settings/notifications"));
+const SettingsPrivacyPage = lazy(() => import("@/page/settings/privacy"));
+const SettingsAccessibilityPage = lazy(() => import("@/page/settings/accessibility"));
+const SettingsSecurityPage = lazy(() => import("@/page/settings/security"));
+const SettingsTokensPage = lazy(() => import("@/page/settings/tokens"));
+const SettingsSshKeysPage = lazy(() => import("@/page/settings/ssh-keys"));
+const LandingLayout = lazy(() => import("@/page/landing/layout"));
+const LandingHome = lazy(() => import("@/page/landing/home"));
+const FeaturesPage = lazy(() => import("@/page/landing/features"));
+const WorkflowPage = lazy(() => import("@/page/landing/workflow"));
+const PricingPage = lazy(() => import("@/page/landing/pricing"));
+const JoinInvitePage = lazy(() => import("@/page/join-invite"));
+const WorkspaceJoinApplyPage = lazy(() => import("@/page/workspace/join-apply"));
+
+/** Moved to module level — avoids re-creating on every App render. */
function WorkspaceCompatRedirect() {
const { projectName = "" } = useParams();
-
return
{error}
+ {workspaceId && ( +{description}
+{description}
+ {actionHref && actionText && ( +Accept this invitation to continue.
+{user.display_name ?? user.username}
diff --git a/src/page/me/overview/activity.tsx b/src/page/me/overview/activity.tsx index e12c885..e4fbb64 100644 --- a/src/page/me/overview/activity.tsx +++ b/src/page/me/overview/activity.tsx @@ -28,7 +28,7 @@ export function WorkspaceList({ workspaces }: { workspaces: { name: string; avat - {ws.avatar_url ?Method: {status.method ?? "TOTP"} {status.has_backup_codes ? " — Backup codes available" : " — No backup codes"}
+ {verifiedBackupCodes.length > 0 && ( ++ Backup codes — save these now. They won't be shown again. +
+{code}
+ ))} ++
Invalid code. Please try again.
+ )} +{apply.message}
)} + {apply.question && ( ++ Q: {apply.question} + {apply.answer && · A: {apply.answer}} +
+ )}