import { Toaster } from "@/components/ui/toaster";
import { Toaster as Sonner } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Routes, Route, useLocation } from "react-router-dom";
import { useEffect } from "react";
// Layouts
import PublicLayout from "@/components/layouts/PublicLayout";
import ProtectedLayout from "@/components/layouts/ProtectedLayout";
import MarketingLayout from "@/components/layouts/MarketingLayout";
// Marketing pages
import HomePage from "@/pages/marketing/HomePage";
import FeaturesPage from "@/pages/marketing/FeaturesPage";
import PricingPage from "@/pages/marketing/PricingPage";
import SecurityPage from "@/pages/marketing/SecurityPage";
import SSHCertificatesPage from "@/pages/marketing/SSHCertificatesPage";
import ZeroTierPage from "@/pages/marketing/ZeroTierPage";
import DemoPage from "@/pages/marketing/DemoPage";
// Public pages
import LoginPage from "@/pages/auth/LoginPage";
import RegisterPage from "@/pages/auth/RegisterPage";
import VerifyEmailPage from "@/pages/auth/VerifyEmailPage";
import ForgotPasswordPage from "@/pages/auth/ForgotPasswordPage";
import ResetPasswordPage from "@/pages/auth/ResetPasswordPage";
import InviteAcceptPage from "@/pages/auth/InviteAcceptPage";
import OIDCConsentPage from "@/pages/auth/OIDCConsentPage";
import OIDCErrorPage from "@/pages/auth/OIDCErrorPage";
import OIDCLoginPage from "@/pages/auth/OIDCLoginPage";
import OAuthCallbackPage from "@/pages/auth/OAuthCallbackPage";
import ActivatePage from "@/pages/auth/ActivatePage";
// User pages
import ProfilePage from "@/pages/user/ProfilePage";
import UserSecurityPage from "@/pages/user/SecurityPage";
import LinkedAccountsPage from "@/pages/user/LinkedAccountsPage";
import ActivityPage from "@/pages/user/ActivityPage";
import SSHKeysPage from "@/pages/user/SSHKeysPage";
import CLIGuidePage from "@/pages/user/CLIGuidePage";
// Organization pages
import OrgOverviewPage from "@/pages/org/OrgOverviewPage";
import MembersPage from "@/pages/org/MembersPage";
import UserManagementPage from "@/pages/admin/UserManagementPage";
import PoliciesPage from "@/pages/org/PoliciesPage";
import CompliancePage from "@/pages/org/CompliancePage";
import OrgAuditPage from "@/pages/org/OrgAuditPage";
import OIDCClientsPage from "@/pages/org/OIDCClientsPage";
import CAsPage from "@/pages/org/CAsPage";
import DepartmentsPage from "@/pages/org/DepartmentsPage";
import PrincipalsPage from "@/pages/org/PrincipalsPage";
import MyMembershipsPage from "@/pages/org/MyMembershipsPage";
import NetworksPage from "@/pages/org/NetworksPage";
import NetworkManagementPage from "@/pages/org/NetworkManagementPage";
import DevicesPage from "@/pages/org/DevicesPage";
import AccessPage from "@/pages/org/AccessPage";
import ZeroTierConfigPage from "@/pages/org/ZeroTierConfigPage";
import SystemAuditPage from "@/pages/admin/SystemAuditPage";
import OAuthProvidersPage from "@/pages/admin/OAuthProvidersPage";
import OrgSetupPage from "@/pages/auth/OrgSetupPage";
import SessionTimeoutModal from "@/components/auth/SessionTimeoutModal";
import NotFound from "@/pages/NotFound";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: (failureCount, error) => {
// Don't retry on 403 authorization errors
if (error && typeof error === 'object' && 'code' in error && error.code === 403) {
return false;
}
// Default retry behavior for other errors (max 3 retries)
return failureCount < 3;
},
},
},
});
const App = () => (
);
// Scroll to top on navigation
function ScrollToTop() {
const location = useLocation();
useEffect(() => {
window.scrollTo({ top: 0, left: 0, behavior: 'instant' });
}, [location.pathname]);
return null;
}
// Separate component so AuthProvider can use useNavigate
import { AuthProvider, useAuth } from "@/contexts/AuthContext";
import { OrgProvider } from "@/contexts/OrgContext";
import { Navigate } from "react-router-dom";
/** Redirects already-authenticated users away from guest-only pages (e.g. /login). */
function GuestRoute({ children }: { children: React.ReactNode }) {
const { isAuthenticated, isOrgMember, isLoading } = useAuth();
// Allow authenticated users through to /login when it's a CLI auth request or
// an OIDC session — LoginPage will immediately forward the existing token.
const params = new URLSearchParams(window.location.search);
const isCli = params.has('cli_token') || params.has('cli_redirect');
const isOidcBridge = params.has('oidc_session_id');
if (isLoading) return null; // wait for auth state to resolve
if (isAuthenticated && !isCli && !isOidcBridge) {
// If the user hasn't set up an org yet, send them there first
return ;
}
return <>{children}>;
}
/** Blocks access to /admin/* for non-admin users. */
function RequireAdmin({ children }: { children: React.ReactNode }) {
const { isOrgAdmin, isLoading, isAuthenticated } = useAuth();
if (isLoading) return null;
if (!isAuthenticated) return ;
if (!isOrgAdmin) return ;
return <>{children}>;
}
/** Blocks access to /org/* for users who don't belong to any organisation. */
function RequireOrgMember({ children }: { children: React.ReactNode }) {
const { isOrgMember, isLoading, isAuthenticated } = useAuth();
if (isLoading) return null;
if (!isAuthenticated) return ;
if (!isOrgMember) return ;
return <>{children}>;
}
/**
* Used for /org-setup which lives inside PublicLayout */
function RequireAuth({ children }: { children: React.ReactNode }) {
const { isAuthenticated, isLoading } = useAuth();
if (isLoading) return null;
if (!isAuthenticated) return ;
return <>{children}>;
}
function AppRoutes() {
return (
{/* Marketing pages */}
}>
} />
} />
} />
} />
} />
} />
} />
{/* Public routes */}
}>
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
{/* Org-setup uses the same full-screen centred layout as auth pages,
but requires a valid session token (RequireAuth guard below). */}
} />
{/* Protected routes - handles auth and MFA enforcement */}
}>
{/* User routes */}
} />
} />
} />
} />
} />
} />
{/* Organization routes — org members: overview + own memberships only */}
} />
} />
} />
{/* Organization management routes — org admins/owners only */}
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
{/* Admin routes — org admin/owner only */}
} />
} />
} />
{/* Catch-all */}
} />
);
}
export default App;