diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 46579c85..eb597f7c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4,6 +4,7 @@ import { Box, CircularProgress, Typography } from '@mui/material'; import { CopilotKit } from "@copilotkit/react-core"; import { ClerkProvider, useAuth } from '@clerk/clerk-react'; import "@copilotkit/react-ui/styles.css"; +import { shouldSkipOnboarding } from './utils/demoMode'; import Wizard from './components/OnboardingWizard/Wizard'; import MainDashboard from './components/MainDashboard/MainDashboard'; import SEODashboard from './components/SEODashboard/SEODashboard'; @@ -406,6 +407,11 @@ const InitialRouteHandler: React.FC = () => { // 4. Has active subscription, check onboarding status if (!isOnboardingComplete) { + // In demo mode, skip onboarding and go directly to podcast-maker + if (shouldSkipOnboarding()) { + console.log('InitialRouteHandler: Demo mode - skipping onboarding → Podcast Maker'); + return ; + } console.log('InitialRouteHandler: Subscription active but onboarding incomplete → Onboarding'); return ; } diff --git a/frontend/src/contexts/OnboardingContext.tsx b/frontend/src/contexts/OnboardingContext.tsx index 206a508d..46f30b66 100644 --- a/frontend/src/contexts/OnboardingContext.tsx +++ b/frontend/src/contexts/OnboardingContext.tsx @@ -1,6 +1,7 @@ import React, { createContext, useContext, useState, useEffect, useCallback, ReactNode } from 'react'; import { useAuth } from '@clerk/clerk-react'; import { apiClient } from '../api/client'; +import { shouldSkipOnboarding } from '../utils/demoMode'; /** * Onboarding Context @@ -102,6 +103,13 @@ export const OnboardingProvider: React.FC = ({ children setLoading(true); setError(null); + // Skip onboarding fetch in demo mode - onboarding is disabled + if (shouldSkipOnboarding()) { + console.log('OnboardingContext: Skipping onboarding fetch in demo mode'); + setLoading(false); + return; + } + console.log('OnboardingContext: Fetching onboarding data for authenticated user...'); // Call batch init endpoint @@ -159,6 +167,12 @@ export const OnboardingProvider: React.FC = ({ children // Separate effect to fetch data when explicitly requested const initializeOnboarding = useCallback(() => { if (isSignedIn && clerkLoaded) { + // Skip onboarding initialization in demo mode + if (shouldSkipOnboarding()) { + console.log('OnboardingContext: Skipping onboarding init in demo mode'); + setLoading(false); + return; + } console.log('OnboardingContext: Initializing onboarding data...'); fetchOnboardingData(); } diff --git a/frontend/src/utils/demoMode.ts b/frontend/src/utils/demoMode.ts new file mode 100644 index 00000000..3cb6a0c9 --- /dev/null +++ b/frontend/src/utils/demoMode.ts @@ -0,0 +1,47 @@ +/** + * Demo mode detection utilities for podcast-only demo mode. + */ + +const DEMO_MODE_STORAGE_KEYS = [ + 'app_mode', + 'demo_mode', + 'podcast_only_demo_mode', +]; + +const DEMO_MODE_ENV_KEYS = [ + 'REACT_APP_APP_MODE', + 'REACT_APP_DEMO_MODE', + 'REACT_APP_PODCAST_ONLY_DEMO_MODE', +]; + +/** + * Check if podcast-only demo mode is enabled. + * Checks localStorage first, then environment variables. + */ +export function isPodcastOnlyDemoMode(): boolean { + // Check localStorage + for (const key of DEMO_MODE_STORAGE_KEYS) { + const value = (localStorage.getItem(key) || '').toLowerCase(); + if (value === 'true' || value === 'podcast-only' || value === 'podcast_only') { + return true; + } + } + + // Check environment variables + for (const key of DEMO_MODE_ENV_KEYS) { + const value = (process.env[key] || '').toLowerCase(); + if (value === 'true' || value === 'podcast-only' || value === 'podcast_only') { + return true; + } + } + + return false; +} + +/** + * Check if the app should skip onboarding entirely. + * Returns true in podcast-only demo mode. + */ +export function shouldSkipOnboarding(): boolean { + return isPodcastOnlyDemoMode(); +}