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();
+}