import { lazy, Suspense, useEffect, useState } from 'react'; import Clarity from '@microsoft/clarity'; import { Routes, Route, useLocation } from 'react-router-dom'; import { Toaster } from 'sonner'; import Header from '@/components/layout/Header'; import Footer from '@/components/layout/Footer'; import ErrorBoundary from '@/components/shared/ErrorBoundary'; import ToolLandingPage from '@/components/seo/ToolLandingPage'; import { useDirection } from '@/hooks/useDirection'; import { initAnalytics, trackPageView } from '@/services/analytics'; import { useAuthStore } from '@/stores/authStore'; import { TOOL_MANIFEST } from '@/config/toolManifest'; let clarityInitialized = false; // Pages const HomePage = lazy(() => import('@/pages/HomePage')); const AboutPage = lazy(() => import('@/pages/AboutPage')); const PrivacyPage = lazy(() => import('@/pages/PrivacyPage')); const NotFoundPage = lazy(() => import('@/pages/NotFoundPage')); const TermsPage = lazy(() => import('@/pages/TermsPage')); const ContactPage = lazy(() => import('@/pages/ContactPage')); const AccountPage = lazy(() => import('@/pages/AccountPage')); const ForgotPasswordPage = lazy(() => import('@/pages/ForgotPasswordPage')); const ResetPasswordPage = lazy(() => import('@/pages/ResetPasswordPage')); const PricingPage = lazy(() => import('@/pages/PricingPage')); const PricingTransparencyPage = lazy(() => import('@/pages/PricingTransparencyPage')); const BlogPage = lazy(() => import('@/pages/BlogPage')); const BlogPostPage = lazy(() => import('@/pages/BlogPostPage')); const DevelopersPage = lazy(() => import('@/pages/DevelopersPage')); const AllToolsPage = lazy(() => import('@/pages/AllToolsPage')); const InternalAdminPage = lazy(() => import('@/pages/InternalAdminPage')); const SeoRoutePage = lazy(() => import('@/pages/SeoRoutePage')); const ComparisonPage = lazy(() => import('@/pages/ComparisonPage')); const CookieConsent = lazy(() => import('@/components/layout/CookieConsent')); const SiteAssistant = lazy(() => import('@/components/layout/SiteAssistant')); // Tool components — derived from manifest using React.lazy const ToolComponents = Object.fromEntries( TOOL_MANIFEST.map((tool) => [tool.slug, lazy(tool.component)]) ) as Record>; function LoadingFallback() { return (
); } function IdleLoad({ children }: { children: React.ReactNode }) { const [ready, setReady] = useState(false); useEffect(() => { if ('requestIdleCallback' in window) { const id = requestIdleCallback(() => setReady(true)); return () => cancelIdleCallback(id); } const id = setTimeout(() => setReady(true), 2000); return () => clearTimeout(id); }, []); return ready ? <>{children} : null; } export default function App() { useDirection(); const location = useLocation(); const refreshUser = useAuthStore((state) => state.refreshUser); const isRTL = document.documentElement.getAttribute('dir') === 'rtl'; const isMarketingLayout = location.pathname === '/' || ['/about', '/contact', '/pricing', '/tools', '/developers', '/pricing-transparency'].includes(location.pathname) || location.pathname.startsWith('/compare/'); useEffect(() => { initAnalytics(); void refreshUser(); }, [refreshUser]); // Microsoft Clarity: Run only in production and browser useEffect(() => { if (!import.meta.env.PROD || typeof window === 'undefined') return; const projectId = (import.meta.env.VITE_CLARITY_PROJECT_ID || '').trim(); if (!projectId) return; const tryInitClarity = () => { if (clarityInitialized) return; try { const rawConsent = localStorage.getItem('cookie_consent'); const parsed = rawConsent ? JSON.parse(rawConsent) : null; const hasConsent = parsed?.state === 'accepted'; if (hasConsent) { Clarity.init(projectId); clarityInitialized = true; } } catch { // Ignore malformed consent payloads. } }; tryInitClarity(); const onConsent = (event: Event) => { const customEvent = event as CustomEvent<{ accepted: boolean }>; if (customEvent.detail?.accepted && !clarityInitialized) { Clarity.init(projectId); clarityInitialized = true; } }; window.addEventListener('cookie-consent', onConsent as EventListener); return () => window.removeEventListener('cookie-consent', onConsent as EventListener); }, []); useEffect(() => { trackPageView(`${location.pathname}${location.search}`); }, [location.pathname, location.search]); return (
}> {/* Pages */} } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> {/* Tool Routes — driven by the unified manifest */} {TOOL_MANIFEST.map((tool) => { const Component = ToolComponents[tool.slug]; return ( } /> ); })} {/* 404 */} } />
); }