diff --git a/backend/app.py b/backend/app.py index 80e2b72a..1d9e96c9 100644 --- a/backend/app.py +++ b/backend/app.py @@ -119,8 +119,10 @@ setup_clean_logging() # Import middleware from middleware.auth_middleware import get_current_user -# Import component logic endpoints (needs OnboardingSession, so import after models) -from api.component_logic import router as component_logic_router +# Import component logic endpoints (skip in podcast-only mode - uses seo_analyzer) +component_logic_router = None +if not PODCAST_ONLY_DEMO_MODE: + from api.component_logic import router as component_logic_router # Import subscription API endpoints from api.subscription import router as subscription_router @@ -130,8 +132,10 @@ step3_routes = None if not PODCAST_ONLY_DEMO_MODE: from api.onboarding_utils.step3_routes import router as step3_routes -# Import SEO tools router -from routers.seo_tools import router as seo_tools_router +# Import SEO tools router (skip in podcast-only mode - uses seo_analyzer) +seo_tools_router = None +if not PODCAST_ONLY_DEMO_MODE: + from routers.seo_tools import router as seo_tools_router # Skip Facebook Writer, LinkedIn, and other non-podcast routes in podcast-only mode # Also skip other heavy services that trigger PersonaAnalysisService initialization @@ -162,8 +166,11 @@ else: hallucination_detector_router = None writing_assistant_router = None -# Import research configuration router -from api.research_config import router as research_config_router +# Import research configuration router (skip in podcast-only mode) +if not is_podcast_only_demo_mode(): + from api.research_config import router as research_config_router +else: + research_config_router = None # Import user data endpoints # Import content planning endpoints (skip in podcast-only mode) @@ -174,7 +181,11 @@ else: content_planning_router = None strategy_copilot_router = None -from api.user_data import router as user_data_router +# Import user data endpoints (skip in podcast-only mode to save memory) +if not is_podcast_only_demo_mode(): + from api.user_data import router as user_data_router +else: + user_data_router = None # Import database service from services.database import close_database @@ -192,36 +203,65 @@ if not is_podcast_only_demo_mode(): else: oauth_token_monitoring_router = None -# Import SEO Dashboard endpoints -from api.seo_dashboard import ( - get_seo_dashboard_data, - get_seo_health_score, - get_seo_metrics, - get_platform_status, - get_ai_insights, - seo_dashboard_health_check, - analyze_seo_comprehensive, - analyze_seo_full, - get_seo_metrics_detailed, - get_analysis_summary, - batch_analyze_urls, - SEOAnalysisRequest, - get_seo_dashboard_overview, - get_gsc_raw_data, - get_bing_raw_data, - get_competitive_insights, - get_deep_competitor_analysis, - run_strategic_insights, - get_strategic_insights_history, - refresh_analytics_data, - analyze_urls_ai, - AnalyzeURLsRequest, - get_analyzed_pages, - get_semantic_health, - get_semantic_cache_stats, - get_sif_indexing_health, - get_onboarding_task_health, -) +# Import SEO Dashboard endpoints (skip in podcast-only mode to save memory) +if not is_podcast_only_demo_mode(): + from api.seo_dashboard import ( + get_seo_dashboard_data, + get_seo_health_score, + get_seo_metrics, + get_platform_status, + get_ai_insights, + seo_dashboard_health_check, + analyze_seo_comprehensive, + analyze_seo_full, + get_seo_metrics_detailed, + get_analysis_summary, + batch_analyze_urls, + SEOAnalysisRequest, + get_seo_dashboard_overview, + get_gsc_raw_data, + get_bing_raw_data, + get_competitive_insights, + get_deep_competitor_analysis, + run_strategic_insights, + get_strategic_insights_history, + refresh_analytics_data, + analyze_urls_ai, + AnalyzeURLsRequest, + get_analyzed_pages, + get_semantic_health, + get_semantic_cache_stats, + get_sif_indexing_health, + get_onboarding_task_health, + ) +else: + get_seo_dashboard_data = None + get_seo_health_score = None + get_seo_metrics = None + get_platform_status = None + get_ai_insights = None + seo_dashboard_health_check = None + analyze_seo_comprehensive = None + analyze_seo_full = None + get_seo_metrics_detailed = None + get_analysis_summary = None + batch_analyze_urls = None + SEOAnalysisRequest = None + get_seo_dashboard_overview = None + get_gsc_raw_data = None + get_bing_raw_data = None + get_competitive_insights = None + get_deep_competitor_analysis = None + run_strategic_insights = None + get_strategic_insights_history = None + refresh_analytics_data = None + analyze_urls_ai = None + AnalyzeURLsRequest = None + get_analyzed_pages = None + get_semantic_health = None + get_semantic_cache_stats = None + get_sif_indexing_health = None + get_onboarding_task_health = None # Initialize FastAPI app @@ -413,145 +453,143 @@ router_group_status["assets_serving"] = { "reason": "Required for podcast media assets", } -# SEO Dashboard endpoints -@app.get("/api/seo-dashboard/data") -async def seo_dashboard_data(): - """Get complete SEO dashboard data.""" - return await get_seo_dashboard_data() +# SEO Dashboard endpoints (skip in podcast-only mode) +if not is_podcast_only_demo_mode(): + @app.get("/api/seo-dashboard/data") + async def seo_dashboard_data(): + """Get complete SEO dashboard data.""" + return await get_seo_dashboard_data() -@app.get("/api/seo-dashboard/health-score") -async def seo_health_score(): - """Get SEO health score.""" - return await get_seo_health_score() + @app.get("/api/seo-dashboard/health-score") + async def seo_health_score(): + """Get SEO health score.""" + return await get_seo_health_score() -@app.get("/api/seo-dashboard/metrics") -async def seo_metrics(): - """Get SEO metrics.""" - return await get_seo_metrics() + @app.get("/api/seo-dashboard/metrics") + async def seo_metrics(): + """Get SEO metrics.""" + return await get_seo_metrics() -@app.get("/api/seo-dashboard/platforms") -async def seo_platforms(current_user: dict = Depends(get_current_user)): - """Get platform status.""" - return await get_platform_status(current_user) + @app.get("/api/seo-dashboard/platforms") + async def seo_platforms(current_user: dict = Depends(get_current_user)): + """Get platform status.""" + return await get_platform_status(current_user) -@app.get("/api/seo-dashboard/insights") -async def seo_insights(): - """Get AI insights.""" - return await get_ai_insights() + @app.get("/api/seo-dashboard/insights") + async def seo_insights(): + """Get AI insights.""" + return await get_ai_insights() -# New SEO Dashboard endpoints with real data -@app.get("/api/seo-dashboard/overview") -async def seo_dashboard_overview_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): - """Get comprehensive SEO dashboard overview with real GSC/Bing data.""" - return await get_seo_dashboard_overview(current_user, site_url) + @app.get("/api/seo-dashboard/overview") + async def seo_dashboard_overview_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): + """Get comprehensive SEO dashboard overview with real GSC/Bing data.""" + return await get_seo_dashboard_overview(current_user, site_url) -@app.get("/api/seo-dashboard/gsc/raw") -async def gsc_raw_data_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): - """Get raw GSC data for the specified site.""" - return await get_gsc_raw_data(current_user, site_url) + @app.get("/api/seo-dashboard/gsc/raw") + async def gsc_raw_data_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): + """Get raw GSC data for the specified site.""" + return await get_gsc_raw_data(current_user, site_url) -@app.get("/api/seo-dashboard/bing/raw") -async def bing_raw_data_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): - """Get raw Bing data for the specified site.""" - return await get_bing_raw_data(current_user, site_url) + @app.get("/api/seo-dashboard/bing/raw") + async def bing_raw_data_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): + """Get raw Bing data for the specified site.""" + return await get_bing_raw_data(current_user, site_url) -@app.get("/api/seo-dashboard/competitive-insights") -async def competitive_insights_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): - """Get competitive insights from onboarding step 3 data.""" - return await get_competitive_insights(current_user, site_url) + @app.get("/api/seo-dashboard/competitive-insights") + async def competitive_insights_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): + """Get competitive insights from onboarding step 3 data.""" + return await get_competitive_insights(current_user, site_url) -@app.get("/api/seo-dashboard/deep-competitor-analysis") -async def deep_competitor_analysis_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): - """Get deep competitor analysis results (auto-scheduled post-onboarding).""" - return await get_deep_competitor_analysis(current_user, site_url) + @app.get("/api/seo-dashboard/deep-competitor-analysis") + async def deep_competitor_analysis_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): + """Get deep competitor analysis results (auto-scheduled post-onboarding).""" + return await get_deep_competitor_analysis(current_user, site_url) -@app.post("/api/seo-dashboard/strategic-insights/run") -async def run_strategic_insights_endpoint(current_user: dict = Depends(get_current_user)): - """Run AI-powered strategic insights analysis manually.""" - return await run_strategic_insights(current_user) + @app.post("/api/seo-dashboard/strategic-insights/run") + async def run_strategic_insights_endpoint(current_user: dict = Depends(get_current_user)): + """Run AI-powered strategic insights analysis manually.""" + return await run_strategic_insights(current_user) -@app.get("/api/seo-dashboard/strategic-insights/history") -async def get_strategic_insights_history_endpoint(current_user: dict = Depends(get_current_user)): - """Fetch the history of strategic insights for the user.""" - return await get_strategic_insights_history(current_user) + @app.get("/api/seo-dashboard/strategic-insights/history") + async def get_strategic_insights_history_endpoint(current_user: dict = Depends(get_current_user)): + """Fetch the history of strategic insights for the user.""" + return await get_strategic_insights_history(current_user) -@app.post("/api/seo-dashboard/refresh") -async def refresh_analytics_data_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): - """Refresh analytics data by invalidating cache and fetching fresh data.""" - return await refresh_analytics_data(current_user, site_url) + @app.post("/api/seo-dashboard/refresh") + async def refresh_analytics_data_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): + """Refresh analytics data by invalidating cache and fetching fresh data.""" + return await refresh_analytics_data(current_user, site_url) + @app.get("/api/seo-dashboard/onboarding-task-health") + async def onboarding_task_health_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): + """Get consolidated health for onboarding-scheduled SEO tasks.""" + return await get_onboarding_task_health(current_user, site_url) -@app.get("/api/seo-dashboard/onboarding-task-health") -async def onboarding_task_health_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): - """Get consolidated health for onboarding-scheduled SEO tasks.""" - return await get_onboarding_task_health(current_user, site_url) + @app.get("/api/seo-dashboard/health") + async def seo_dashboard_health(): + """Health check for SEO dashboard.""" + return await seo_dashboard_health_check() -@app.get("/api/seo-dashboard/health") -async def seo_dashboard_health(): - """Health check for SEO dashboard.""" - return await seo_dashboard_health_check() - -# Phase 2B: Semantic health monitoring endpoint (24-hour polling) -@app.get("/api/seo-dashboard/semantic-health") -async def semantic_health_endpoint(current_user: dict = Depends(get_current_user)): - """ - Get real-time semantic health metrics for content and competitors. - This endpoint provides Phase 2B semantic intelligence monitoring data. - - Returns semantic health score, status, and recommendations. - Data is cached and updated every 24 hours via scheduler. - """ - return await get_semantic_health(current_user) + @app.get("/api/seo-dashboard/semantic-health") + async def semantic_health_endpoint(current_user: dict = Depends(get_current_user)): + """ + Get real-time semantic health metrics for content and competitors. + This endpoint provides Phase 2B semantic intelligence monitoring data. + + Returns semantic health score, status, and recommendations. + Data is cached and updated every 24 hours via scheduler. + """ + return await get_semantic_health(current_user) -@app.get("/api/seo-dashboard/cache-stats") -async def semantic_cache_stats_endpoint(current_user: dict = Depends(get_current_user)): - """ - Get semantic cache performance statistics. - Returns hit rate, memory usage, and eviction counts. - """ - return await get_semantic_cache_stats(current_user) + @app.get("/api/seo-dashboard/cache-stats") + async def semantic_cache_stats_endpoint(current_user: dict = Depends(get_current_user)): + """ + Get semantic cache performance statistics. + Returns hit rate, memory usage, and eviction counts. + """ + return await get_semantic_cache_stats(current_user) -@app.get("/api/seo-dashboard/sif-health") -async def sif_indexing_health_endpoint(current_user: dict = Depends(get_current_user)): - """ - Get SIF indexing health summary for the current user. - Used by the Semantic Indexing Status widget on the dashboard. - """ - return await get_sif_indexing_health(current_user) + @app.get("/api/seo-dashboard/sif-health") + async def sif_indexing_health_endpoint(current_user: dict = Depends(get_current_user)): + """ + Get SIF indexing health summary for the current user. + Used by the Semantic Indexing Status widget on the dashboard. + """ + return await get_sif_indexing_health(current_user) -# Comprehensive SEO Analysis endpoints -@app.post("/api/seo-dashboard/analyze-comprehensive") -async def analyze_seo_comprehensive_endpoint(request: SEOAnalysisRequest): - """Analyze a URL for comprehensive SEO performance.""" - return await analyze_seo_comprehensive(request) + # Comprehensive SEO Analysis endpoints + @app.post("/api/seo-dashboard/analyze-comprehensive") + async def analyze_seo_comprehensive_endpoint(request: SEOAnalysisRequest): + """Analyze a URL for comprehensive SEO performance.""" + return await analyze_seo_comprehensive(request) -@app.post("/api/seo-dashboard/analyze-full") -async def analyze_seo_full_endpoint(request: SEOAnalysisRequest): - """Analyze a URL for comprehensive SEO performance.""" - return await analyze_seo_full(request) + @app.post("/api/seo-dashboard/analyze-full") + async def analyze_seo_full_endpoint(request: SEOAnalysisRequest): + """Analyze a URL for comprehensive SEO performance.""" + return await analyze_seo_full(request) -@app.get("/api/seo-dashboard/metrics-detailed") -async def seo_metrics_detailed(url: str): - """Get detailed SEO metrics for a URL.""" - return await get_seo_metrics_detailed(url) + @app.get("/api/seo-dashboard/metrics-detailed") + async def seo_metrics_detailed(url: str): + """Get detailed SEO metrics for a URL.""" + return await get_seo_metrics_detailed(url) -@app.get("/api/seo-dashboard/analysis-summary") -async def seo_analysis_summary(url: str): - """Get a quick summary of SEO analysis for a URL.""" - return await get_analysis_summary(url) + @app.get("/api/seo-dashboard/analysis-summary") + async def seo_analysis_summary(url: str): + """Get a quick summary of SEO analysis for a URL.""" + return await get_analysis_summary(url) -@app.post("/api/seo-dashboard/batch-analyze") -async def batch_analyze_urls_endpoint(urls: list[str]): - """Analyze multiple URLs in batch.""" - return await batch_analyze_urls(urls) + @app.post("/api/seo-dashboard/batch-analyze") + async def batch_analyze_urls_endpoint(urls: list[str]): + """Analyze multiple URLs in batch.""" + return await batch_analyze_urls(urls) -@app.post("/api/seo-dashboard/analyze-urls-ai") -async def analyze_urls_ai_endpoint(request: AnalyzeURLsRequest, current_user: dict = Depends(get_current_user)): - """Run AI-powered SEO analysis on selected URLs.""" - return await analyze_urls_ai(request, current_user) + @app.post("/api/seo-dashboard/analyze-urls-ai") + async def analyze_urls_ai_endpoint(request: AnalyzeURLsRequest, current_user: dict = Depends(get_current_user)): + """Run AI-powered SEO analysis on selected URLs.""" + return await analyze_urls_ai(request, current_user) # Include platform analytics router if not PODCAST_ONLY_DEMO_MODE: diff --git a/backend/render-build.sh b/backend/render-build.sh index ae1c11c7..ed133c56 100644 --- a/backend/render-build.sh +++ b/backend/render-build.sh @@ -9,8 +9,9 @@ python -m pip install --upgrade pip setuptools wheel # 2. Install requirements based on mode echo "šŸ“¦ Checking ALWRITY_ENABLED_FEATURES..." ENABLED_FEATURES="${ALWRITY_ENABLED_FEATURES:-all}" +echo "DEBUG: ENABLED_FEATURES='$ENABLED_FEATURES'" -if [[ "$ENABLED_FEATURES" == *"podcast"* ]]; then +if [[ "$ENABLED_FEATURES" == "podcast" ]]; then echo "šŸ”Š Podcast-only mode: Installing lean requirements..." python -m pip install --no-cache-dir -r requirements-podcast.txt --only-binary :all: --retries 10 --timeout 120 else diff --git a/backend/requirements-podcast.txt b/backend/requirements-podcast.txt index 071b34d6..6f7103af 100644 --- a/backend/requirements-podcast.txt +++ b/backend/requirements-podcast.txt @@ -38,6 +38,7 @@ exa-py==1.9.1 # Text processing (minimal) markdown>=3.5.0 +beautifulsoup4>=4.12.0 # Data processing (numpy needed for moviepy) numpy>=1.24.0 diff --git a/backend/start_alwrity_backend.py b/backend/start_alwrity_backend.py index b42dde75..c02cdbe1 100644 --- a/backend/start_alwrity_backend.py +++ b/backend/start_alwrity_backend.py @@ -100,7 +100,7 @@ def bootstrap_linguistic_models() -> BootstrapResult: verbose = os.getenv("ALWRITY_VERBOSE", "false").lower() == "true" if verbose: - print("šŸ” Bootstrapping linguistic models...") + print("[DEBUG] Bootstrapping linguistic models...") # Check and download spaCy model try: @@ -108,7 +108,7 @@ def bootstrap_linguistic_models() -> BootstrapResult: try: nlp = spacy.load("en_core_web_sm") if verbose: - print(" āœ… spaCy model 'en_core_web_sm' available") + print(" [OK] spaCy model 'en_core_web_sm' available") except OSError: if verbose: print(" āš ļø spaCy model 'en_core_web_sm' not found, downloading...") @@ -117,10 +117,10 @@ def bootstrap_linguistic_models() -> BootstrapResult: sys.executable, "-m", "spacy", "download", "en_core_web_sm" ]) if verbose: - print(" āœ… spaCy model downloaded successfully") + print(" [OK] spaCy model downloaded successfully") except subprocess.CalledProcessError as e: if verbose: - print(f" āŒ Failed to download spaCy model: {e}") + print(f" [FAIL] Failed to download spaCy model: {e}") print(" Please run: python -m spacy download en_core_web_sm") return BootstrapResult(name="linguistic_models", success=False, skipped=False, reason="spacy_download_failed") except ImportError: @@ -140,14 +140,14 @@ def bootstrap_linguistic_models() -> BootstrapResult: try: nltk.data.find(path) if verbose: - print(f" āœ… NLTK {data_package} available") + print(f" [OK] NLTK {data_package} available") except LookupError: if verbose: print(f" āš ļø NLTK {data_package} not found, downloading...") try: nltk.download(data_package, quiet=True) if verbose: - print(f" āœ… NLTK {data_package} downloaded") + print(f" [OK] NLTK {data_package} downloaded") except Exception as e: if verbose: print(f" āš ļø Failed to download {data_package}: {e}") @@ -155,7 +155,7 @@ def bootstrap_linguistic_models() -> BootstrapResult: try: nltk.download('punkt', quiet=True) if verbose: - print(f" āœ… NLTK punkt (fallback) downloaded") + print(f" [OK] NLTK punkt (fallback) downloaded") except: pass except ImportError: @@ -163,7 +163,7 @@ def bootstrap_linguistic_models() -> BootstrapResult: print(" āš ļø NLTK not installed - skipping") if verbose: - print("āœ… Linguistic model bootstrap complete") + print("[OK] Linguistic model bootstrap complete") return BootstrapResult(name="linguistic_models", success=True, skipped=False) @@ -207,7 +207,7 @@ def bootstrap_local_llm_models() -> BootstrapResult: # This checks cache and downloads if missing snapshot_download(repo_id=target_model, repo_type="model") if verbose: - print(f" āœ… Local LLM '{target_model}' available") + print(f" [OK] Local LLM '{target_model}' available") except Exception as e: if verbose: print(f" āš ļø Failed to download/check local LLM: {e}") @@ -244,7 +244,7 @@ if __name__ == "__main__": features_str = ",".join(sorted(enabled_features)) os.environ["ALWRITY_ENABLED_FEATURES"] = features_str - print(f"\nšŸ“‹ Enabled features: {features_str}") + print(f"\n[OK] Enabled features: {features_str}") if should_bootstrap_linguistic_models(): result = bootstrap_linguistic_models() @@ -252,7 +252,7 @@ if __name__ == "__main__": else: verbose = os.getenv("ALWRITY_VERBOSE", "false").lower() == "true" if verbose: - print("ā­ļø Skipping linguistic model bootstrap (profile-gated)") + print("[SKIP] Skipping linguistic model bootstrap (profile-gated)") BOOTSTRAP_RESULTS.append(BootstrapResult(name="linguistic_models", success=True, skipped=True, reason="profile_gated")) if should_bootstrap_local_llm_models(): @@ -261,7 +261,7 @@ if __name__ == "__main__": else: verbose = os.getenv("ALWRITY_VERBOSE", "false").lower() == "true" if verbose: - print("ā­ļø Skipping local LLM model bootstrap (feature-gated)") + print("[SKIP] Skipping local LLM model bootstrap (feature-gated)") BOOTSTRAP_RESULTS.append(BootstrapResult(name="local_llm_models", success=True, skipped=True, reason="feature_gated")) summary = { @@ -270,9 +270,9 @@ if __name__ == "__main__": } os.environ["ALWRITY_BOOTSTRAP_SUMMARY"] = json.dumps(summary) - print(f"\nšŸ“‹ Bootstrap Summary:") + print(f"\n[INFO] Bootstrap Summary:") for r in BOOTSTRAP_RESULTS: - status = "ā­ļø Skipped" if r.skipped else ("āœ… Enabled" if r.success else "āŒ Failed") + status = "[SKIP] Skipped" if r.skipped else ("[OK] Enabled" if r.success else "[FAIL] Failed") print(f" {r.name}: {status}" + (f" ({r.reason})" if r.reason else "")) # NOW import modular utilities (after bootstrap) @@ -286,12 +286,12 @@ from alwrity_utils import ( def start_backend(enable_reload=False, production_mode=False): """Start the backend server.""" - print("šŸš€ Starting ALwrity Backend...") + print("==> Starting ALwrity Backend...") podcast_only_demo_mode = os.getenv("ALWRITY_PODCAST_ONLY_DEMO_MODE", os.getenv("PODCAST_ONLY_DEMO_MODE", "false")).lower() in {"1", "true", "yes", "on"} if podcast_only_demo_mode: print("\n" + "=" * 60) - print("šŸŽ™ļø PODCAST-ONLY DEMO MODE ACTIVE") + print("==> PODCAST-ONLY DEMO MODE ACTIVE") print(" Non-podcast router groups are intentionally skipped.") print("=" * 60) @@ -315,10 +315,10 @@ def start_backend(enable_reload=False, production_mode=False): # Set reload based on argument or environment variable if enable_reload and not production_mode: os.environ.setdefault("RELOAD", "true") - print(" šŸ”„ Development mode: Auto-reload enabled") + print(" [DEV] Development mode: Auto-reload enabled") else: os.environ.setdefault("RELOAD", "false") - print(" šŸ­ Production mode: Auto-reload disabled") + print(" [PROD] Production mode: Auto-reload disabled") host = os.getenv("HOST", "0.0.0.0") port = int(os.getenv("PORT", "8000")) @@ -326,9 +326,9 @@ def start_backend(enable_reload=False, production_mode=False): print(f"[DEBUG] Bind prepared - host={host}, port={port}, reload={reload}", flush=True) print(f"[DEBUG] ENV check - ALWRITY_ENABLED_FEATURES={os.getenv('ALWRITY_ENABLED_FEATURES')}", flush=True) - print(f" šŸ“ Host: {host}", flush=True) - print(f" šŸ”Œ Port: {port}", flush=True) - print(f" šŸ”„ Reload: {reload}", flush=True) + print(f" ==> Host: {host}", flush=True) + print(f" ==> Port: {port}", flush=True) + print(f" [DEV] Reload: {reload}", flush=True) print(f"[DEBUG] About to import app module...", flush=True) print("[DEBUG] >>> START APP IMPORT <<<", flush=True) @@ -342,7 +342,7 @@ def start_backend(enable_reload=False, production_mode=False): # Note: Database already initialized by DatabaseSetup in main() - print("\n🌐 ALwrity Backend Server", flush=True) + print("\n[WORLD] ALwrity Backend Server", flush=True) print("=" * 50, flush=True) print(f" šŸ“– API Documentation: http://localhost:{os.getenv('PORT', '8000')}/api/docs", flush=True) print(f" šŸ” Health Check: http://localhost:{os.getenv('PORT', '8000')}/health", flush=True) @@ -501,12 +501,12 @@ def main(): "Starting server" ] - print("šŸ”§ Initializing ALwrity...") + print("==> Initializing ALwrity...") # Apply production optimizations if needed if production_mode: if not production_optimizer.apply_production_optimizations(): - print("āŒ Production optimization failed") + print("[FAIL] Production optimization failed") return False # Step 1: Dependencies @@ -515,11 +515,11 @@ def main(): if not critical_ok: print("installing...", end=" ", flush=True) if not dependency_manager.install_requirements(): - print("āŒ Failed") + print("[FAIL] Failed") return False - print("āœ… Done") + print("[OK] Done") else: - print("āœ… Done") + print("[OK] Done") # Check optional dependencies (non-critical) - only in verbose mode if verbose_mode: @@ -528,24 +528,24 @@ def main(): # Step 2: Environment print(f" šŸ”§ {setup_steps[1]}...", end=" ", flush=True) if not environment_setup.setup_directories(): - print("āŒ Directory setup failed") + print("[FAIL] Directory setup failed") return False if not environment_setup.setup_environment_variables(): - print("āŒ Environment setup failed") + print("[FAIL] Environment setup failed") return False # Create .env file only in development if not production_mode: environment_setup.create_env_file() - print("āœ… Done") + print("[OK] Done") # Step 3: Database print(f" šŸ“Š {setup_steps[2]}...", end=" ", flush=True) if not database_setup.setup_essential_tables(): print("āš ļø Issues detected, continuing...") else: - print("āœ… Done") + print("[OK] Done") # Setup advanced features in development, verify in all modes if not production_mode: