import React, { useState, useEffect } from 'react'; import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; import { Box, CircularProgress, Typography } from '@mui/material'; import { ClerkProvider, useAuth } from '@clerk/clerk-react'; import Wizard from './components/OnboardingWizard/Wizard'; import MainDashboard from './components/MainDashboard/MainDashboard'; import SEODashboard from './components/SEODashboard/SEODashboard'; import ContentPlanningDashboard from './components/ContentPlanningDashboard/ContentPlanningDashboard'; import FacebookWriter from './components/FacebookWriter/FacebookWriter'; import LinkedInWriter from './components/LinkedInWriter/LinkedInWriter'; import BlogWriter from './components/BlogWriter/BlogWriter'; import StoryWriter from './components/StoryWriter/StoryWriter'; import { StoryProjectList } from './components/StoryWriter/StoryProjectList'; import YouTubeCreator from './components/YouTubeCreator/YouTubeCreator'; import { CreateStudio, EditStudio, UpscaleStudio, ControlStudio, SocialOptimizer, AssetLibrary, ImageStudioDashboard, FaceSwapStudio, CompressionStudio, ImageProcessingStudio } from './components/ImageStudio'; import { VideoStudioDashboard, CreateVideo, AvatarVideo, EnhanceVideo, ExtendVideo, EditVideo, TransformVideo, SocialVideo, FaceSwap, VideoTranslate, VideoBackgroundRemover, AddAudioToVideo, LibraryVideo, } from './components/VideoStudio'; import { ProductMarketingDashboard, ProductPhotoshootStudio, ProductAnimationStudio, ProductVideoStudio, ProductAvatarStudio, } from './components/ProductMarketing'; import PodcastDashboard from './components/PodcastMaker/PodcastDashboard'; import PricingPage from './components/Pricing/PricingPage'; import WixTestPage from './components/WixTestPage/WixTestPage'; import WixCallbackPage from './components/WixCallbackPage/WixCallbackPage'; import WordPressCallbackPage from './components/WordPressCallbackPage/WordPressCallbackPage'; import BingCallbackPage from './components/BingCallbackPage/BingCallbackPage'; import BingAnalyticsStorage from './components/BingAnalyticsStorage/BingAnalyticsStorage'; import ResearchDashboard from './pages/ResearchDashboard'; import IntentResearchTest from './pages/IntentResearchTest'; import SchedulerDashboard from './pages/SchedulerDashboard'; import BillingPage from './pages/BillingPage'; import ApprovalsPage from './pages/ApprovalsPage'; import TeamActivityPage from './pages/TeamActivityPage'; import StripeDisputesDashboard from './pages/StripeDisputesDashboard'; import ProtectedRoute from './components/shared/ProtectedRoute'; import GSCAuthCallback from './components/SEODashboard/components/GSCAuthCallback'; import Landing from './components/Landing/Landing'; import ErrorBoundary from './components/shared/ErrorBoundary'; import ErrorBoundaryTest from './components/shared/ErrorBoundaryTest'; import { OnboardingProvider } from './contexts/OnboardingContext'; import { SubscriptionProvider } from './contexts/SubscriptionContext'; import InitialRouteHandler from './components/App/InitialRouteHandler'; import TokenInstaller from './components/App/TokenInstaller'; import { ConditionalCopilotKit, AuthenticatedCopilotWrapper } from './components/App/CopilotWrappers'; // interface OnboardingStatus { // onboarding_required: boolean; // onboarding_complete: boolean; // current_step?: number; // total_steps?: number; // completion_percentage?: number; // } // Root route that chooses Landing (signed out) or InitialRouteHandler (signed in) const RootRoute: React.FC = () => { const { isSignedIn } = useAuth(); if (isSignedIn) { return ; } return ; }; const App: React.FC = () => { // React Hooks MUST be at the top before any conditionals const [loading, setLoading] = useState(true); // Get CopilotKit key from localStorage or .env const [copilotApiKey, setCopilotApiKey] = useState(() => { const savedKey = localStorage.getItem('copilotkit_api_key'); const envKey = process.env.REACT_APP_COPILOTKIT_API_KEY || ''; const key = (savedKey || envKey).trim(); // Validate key format if present if (key && !key.startsWith('ck_pub_')) { console.warn('CopilotKit API key format invalid - must start with ck_pub_'); } return key; }); // Initialize app - loading state will be managed by InitialRouteHandler useEffect(() => { // Remove manual health check - connection errors are handled by ErrorBoundary setLoading(false); }, []); // Listen for CopilotKit key updates useEffect(() => { const handleKeyUpdate = (event: CustomEvent) => { const newKey = event.detail?.apiKey; if (newKey) { console.log('App: CopilotKit key updated, reloading...'); setCopilotApiKey(newKey); setTimeout(() => window.location.reload(), 500); } }; window.addEventListener('copilotkit-key-updated', handleKeyUpdate as EventListener); return () => window.removeEventListener('copilotkit-key-updated', handleKeyUpdate as EventListener); }, []); // Token installer must be inside ClerkProvider; see TokenInstaller below if (loading) { return ( Connecting to ALwrity... ); } // Get environment variables with fallbacks const clerkPublishableKey = process.env.REACT_APP_CLERK_PUBLISHABLE_KEY || ''; const clerkJSUrl = process.env.REACT_APP_CLERK_JS_URL; // Show error if required keys are missing if (!clerkPublishableKey) { return ( Missing Clerk Publishable Key Please add REACT_APP_CLERK_PUBLISHABLE_KEY to your .env file ); } // Render app with or without CopilotKit based on whether we have a key const renderApp = () => { return ( } /> } /> {/* Error Boundary Testing - Development Only */} {process.env.NODE_ENV === 'development' && ( } /> )} } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> ); }; return ( { // Custom error handler - send to analytics/monitoring console.error('Global error caught:', { error, errorInfo }); // TODO: Send to error tracking service (Sentry, LogRocket, etc.) }} > {renderApp()} ); }; export default App;