# Onboarding Process Improvements This document outlines a comprehensive plan to improve the user onboarding experience in AI-Writer, focusing on the API key management and initial setup process. ## Current Issues After analyzing the current onboarding process in `utils.api_key_manager`, several issues were identified: ### User Experience Issues - **Complex Multi-step Process**: The onboarding is split across multiple steps without clear indication of progress or purpose - **Confusing Navigation**: Users can get lost between steps with no clear path forward - **Required vs. Optional**: No clear distinction between required and optional API keys - **No Skip Option**: Users must go through all steps even if some are not relevant to them - **Limited Guidance**: Insufficient contextual help for users unfamiliar with API keys ### Technical Issues - **Inconsistent State Management**: Wizard state is initialized in multiple places - **Basic Validation**: API keys are only checked for non-emptiness, not actual validity - **Environment Variable Handling**: Not robust across different environments - **Error Handling**: Inconsistent error handling and user feedback - **No Testing Mechanism**: No way to test API keys during setup ### UI/Design Issues - **Inconsistent Styling**: Visual inconsistency across different components - **Poor Mobile Experience**: Limited responsiveness for mobile users - **Visual Hierarchy**: Lack of clear visual distinction for important elements - **Help Text Visibility**: Instructions and help text are not prominent enough ## Proposed Improvements ### 1. Redesigned Onboarding Flow #### Welcome Screen ``` ┌─────────────────────────────────────────────────────┐ │ │ │ Welcome to AI-Writer! 👋 │ │ │ │ Let's get you set up in just a few minutes. │ │ │ │ What would you like to do? │ │ │ │ ○ Quick Start (minimal setup) │ │ ○ Complete Setup (all features) │ │ ○ Import Configuration │ │ │ │ [Start Setup] │ │ │ └─────────────────────────────────────────────────────┘ ``` #### API Key Setup Screen ``` ┌─────────────────────────────────────────────────────┐ │ │ │ Step 1 of 4: Connect AI Models │ │ ━━━━━━━━━━○○○○ │ │ │ │ Required (choose at least one): │ │ ┌─────────────────────────────────────────────┐ │ │ │ ⭐ OpenAI API Key │ │ │ │ [••••••••••••••••••] │ │ │ │ ✓ Validated successfully! │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ ⭐ Google Gemini API Key │ │ │ │ [ ] │ │ │ │ ℹ️ Not configured (optional) │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ Optional: │ │ ┌─────────────────────────────────────────────┐ │ │ │ Anthropic API Key (Coming Soon) │ │ │ │ [ ] │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ [Skip Optional] [Test Keys] [Continue →] │ │ │ └─────────────────────────────────────────────────────┘ ``` #### Progress Summary Screen ``` ┌─────────────────────────────────────────────────────┐ │ │ │ Setup Complete! 🎉 │ │ │ │ Here's your configuration: │ │ │ │ AI Models: │ │ ✅ OpenAI API - Connected │ │ ❌ Google Gemini - Not configured │ │ │ │ Research Tools: │ │ ✅ Tavily Search - Connected │ │ ❌ Serper API - Not configured │ │ │ │ Publishing: │ │ ❌ WordPress - Not configured │ │ │ │ You can change these settings anytime from │ │ the Settings menu. │ │ │ │ [Edit Configuration] [Start Using AI-Writer] │ │ │ └─────────────────────────────────────────────────────┘ ``` ### 2. Technical Improvements #### Unified State Management ```python # Create a dedicated state manager class class OnboardingStateManager: """Manages the state of the onboarding process.""" def __init__(self): """Initialize the onboarding state.""" if 'onboarding_state' not in st.session_state: st.session_state.onboarding_state = { 'current_step': 1, 'total_steps': 4, 'completed_steps': set(), 'api_keys': {}, 'validated_keys': {}, 'setup_mode': 'quick_start', # or 'complete' 'setup_complete': False } def get_state(self): """Get the current onboarding state.""" return st.session_state.onboarding_state def update_state(self, updates): """Update the onboarding state.""" st.session_state.onboarding_state.update(updates) def next_step(self): """Move to the next step.""" current = st.session_state.onboarding_state['current_step'] total = st.session_state.onboarding_state['total_steps'] if current < total: st.session_state.onboarding_state['current_step'] += 1 st.session_state.onboarding_state['completed_steps'].add(current) def previous_step(self): """Move to the previous step.""" if st.session_state.onboarding_state['current_step'] > 1: st.session_state.onboarding_state['current_step'] -= 1 def skip_to_step(self, step): """Skip to a specific step.""" if 1 <= step <= st.session_state.onboarding_state['total_steps']: st.session_state.onboarding_state['current_step'] = step def mark_complete(self): """Mark the onboarding as complete.""" st.session_state.onboarding_state['setup_complete'] = True ``` #### Enhanced API Key Validation ```python async def validate_api_key(service, key): """Validate an API key by making a test request.""" try: if service == "openai": # Test OpenAI API key with a minimal request import openai client = openai.OpenAI(api_key=key) response = await client.models.list() return {"valid": True, "models": [model.id for model in response.data[:5]]} elif service == "gemini": # Test Google Gemini API key import google.generativeai as genai genai.configure(api_key=key) models = genai.list_models() return {"valid": True, "models": [model.name for model in models]} elif service == "tavily": # Test Tavily API key import requests response = requests.get( "https://api.tavily.com/health", headers={"x-api-key": key} ) if response.status_code == 200: return {"valid": True, "status": "healthy"} else: return {"valid": False, "error": f"Status code: {response.status_code}"} # Add more services as needed except Exception as e: return {"valid": False, "error": str(e)} ``` #### Secure API Key Storage ```python def save_api_keys(keys_dict): """Save API keys securely.""" try: # 1. Save to .env file env_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), '.env') # Read existing .env file env_contents = {} if os.path.exists(env_path): with open(env_path, 'r') as f: for line in f: if '=' in line: key, value = line.strip().split('=', 1) env_contents[key] = value # Update with new keys for key_name, key_value in keys_dict.items(): if key_value: # Only save non-empty keys env_key = f"{key_name.upper()}_API_KEY" env_contents[env_key] = key_value # Write back to .env file with open(env_path, 'w') as f: for key, value in env_contents.items(): f.write(f"{key}={value}\n") # 2. Also store in session state for immediate use for key_name, key_value in keys_dict.items(): if key_value: st.session_state[f"{key_name}_api_key"] = key_value # 3. Set environment variables for current session for key_name, key_value in keys_dict.items(): if key_value: os.environ[f"{key_name.upper()}_API_KEY"] = key_value return True except Exception as e: logger.error(f"Error saving API keys: {str(e)}") return False ``` ### 3. UI/UX Improvements #### Responsive Design ```python def render_responsive_layout(): """Render a responsive layout that works on mobile and desktop.""" # Check viewport width st.markdown(""" """, unsafe_allow_html=True) ``` #### Visual Hierarchy for Required vs Optional ```python def render_api_key_input(label, key_name, required=False, help_text=""): """Render an API key input with clear visual hierarchy.""" # Add required indicator if needed display_label = f"{label} {'*' if required else '(optional)'}" # Get existing value from session state or environment existing_value = st.session_state.get(f"{key_name}_api_key", "") or os.getenv(f"{key_name.upper()}_API_KEY", "") # Render the input with appropriate styling st.markdown(f"""
{help_text}
""", unsafe_allow_html=True) # The actual input field value = st.text_input( label="", # Empty because we use custom label above value=existing_value, type="password", key=f"input_{key_name}", label_visibility="collapsed" ) # Validation status if value: is_valid = key_name in st.session_state.get("validated_keys", {}) if is_valid: st.success(f"✓ {label} validated successfully") else: st.info(f"⚠️ {label} not validated yet") return value ``` #### Interactive Help and Tooltips ```python def render_help_section(service): """Render an interactive help section for getting API keys.""" help_content = { "openai": { "title": "How to get your OpenAI API key", "steps": [ "Go to [OpenAI's website](https://platform.openai.com)", "Sign up or log in to your account", "Navigate to the API section", "Click 'Create new secret key'", "Copy the generated key and paste it here" ], "note": "Keep your API key secure and never share it publicly.", "pricing": "$0.002 per 1K tokens for GPT-3.5, $0.06 per 1K tokens for GPT-4", "link": "https://platform.openai.com/account/api-keys" }, "gemini": { "title": "How to get your Google Gemini API key", "steps": [ "Visit [Google AI Studio](https://makersuite.google.com/app/apikey)", "Sign in with your Google account", "Click 'Create API key'", "Copy the generated key and paste it here" ], "note": "Make sure to enable the Gemini API in your Google Cloud Console.", "pricing": "Free tier available, then $0.0025 per 1K tokens", "link": "https://makersuite.google.com/app/apikey" } # Add more services as needed } if service in help_content: content = help_content[service] with st.expander(f"📋 {content['title']}", expanded=False): st.markdown("**Step-by-step guide:**") for i, step in enumerate(content["steps"], 1): st.markdown(f"{i}. {step}") st.markdown(f"**Note:** {content['note']}") st.markdown(f"**Pricing:** {content['pricing']}") st.markdown(f"[Get your API key here]({content['link']})") ``` ### 4. Implementation Plan #### Phase 1: Core Improvements 1. **Create Unified State Manager** - Implement the `OnboardingStateManager` class - Refactor existing code to use the new state manager - Add proper state persistence 2. **Enhance API Key Validation** - Implement real validation for each service - Add visual feedback for validation status - Create a "Test All Keys" function 3. **Improve Navigation** - Redesign step indicator with clear labels - Add skip options for optional steps - Implement a "Quick Start" mode #### Phase 2: UI/UX Enhancements 1. **Redesign Input Components** - Create clear visual hierarchy - Add responsive design for mobile - Implement interactive help sections 2. **Create Summary Screens** - Add welcome screen with setup options - Implement completion summary screen - Add configuration export/import 3. **Enhance Visual Design** - Update color scheme for better accessibility - Add animations for transitions - Implement progress indicators #### Phase 3: Advanced Features 1. **Guided Tours** - Add interactive tutorials - Create contextual help popups - Implement feature discovery 2. **Smart Defaults** - Suggest configurations based on user needs - Implement templates for common use cases - Add recommended settings 3. **Troubleshooting Assistance** - Add automatic error detection - Create guided troubleshooting flows - Implement self-healing for common issues ## Code Implementation Examples ### Welcome Screen Component ```python def render_welcome_screen(): """Render the welcome screen for onboarding.""" st.markdown("""

Welcome to AI-Writer! 👋

Let's get you set up in just a few minutes.

""", unsafe_allow_html=True) # Setup mode selection setup_mode = st.radio( "What would you like to do?", options=["Quick Start (minimal setup)", "Complete Setup (all features)", "Import Configuration"], index=0, key="setup_mode_selection" ) # Store the selection in state if "onboarding_state" in st.session_state: st.session_state.onboarding_state["setup_mode"] = setup_mode.split(" ")[0].lower() # Start button if st.button("Start Setup", use_container_width=True, type="primary"): if "onboarding_state" in st.session_state: st.session_state.onboarding_state["current_step"] = 1 st.rerun() ``` ### API Key Manager Component ```python def render_api_key_manager(): """Render the improved API key manager.""" # Get state manager state_manager = OnboardingStateManager() state = state_manager.get_state() # Render step indicator render_step_indicator(state["current_step"], state["total_steps"]) # Render appropriate step based on current_step if state["current_step"] == 1: render_ai_providers_step(state_manager) elif state["current_step"] == 2: render_research_tools_step(state_manager) elif state["current_step"] == 3: render_publishing_step(state_manager) elif state["current_step"] == 4: render_summary_step(state_manager) # Render navigation buttons render_navigation_buttons(state_manager) ``` ### Improved AI Providers Step ```python def render_ai_providers_step(state_manager): """Render the improved AI providers setup step.""" st.markdown("## Step 1: Connect AI Models") st.markdown("Configure the AI models you want to use for content generation.") # Create tabs for required vs optional tab1, tab2 = st.tabs(["Required (at least one)", "Optional Models"]) with tab1: col1, col2 = st.columns(2) with col1: # OpenAI openai_key = render_api_key_input( "OpenAI API Key", "openai", required=True, help_text="Powers GPT-3.5 and GPT-4 models" ) render_help_section("openai") with col2: # Google Gemini gemini_key = render_api_key_input( "Google Gemini API Key", "gemini", required=False, help_text="Powers Gemini Pro models" ) render_help_section("gemini") with tab2: col1, col2 = st.columns(2) with col1: # Anthropic anthropic_key = render_api_key_input( "Anthropic API Key", "anthropic", required=False, help_text="Powers Claude models" ) render_help_section("anthropic") with col2: # Mistral mistral_key = render_api_key_input( "Mistral API Key", "mistral", required=False, help_text="Powers Mistral models" ) render_help_section("mistral") # Test keys button if st.button("Test API Keys", use_container_width=True): with st.spinner("Testing API keys..."): # Test each provided key results = {} if openai_key: results["openai"] = asyncio.run(validate_api_key("openai", openai_key)) if gemini_key: results["gemini"] = asyncio.run(validate_api_key("gemini", gemini_key)) if anthropic_key: results["anthropic"] = asyncio.run(validate_api_key("anthropic", anthropic_key)) if mistral_key: results["mistral"] = asyncio.run(validate_api_key("mistral", mistral_key)) # Store validation results state_manager.update_state({"validated_keys": results}) # Display results for service, result in results.items(): if result.get("valid", False): st.success(f"✅ {service.title()} API key is valid") else: st.error(f"❌ {service.title()} API key is invalid: {result.get('error', 'Unknown error')}") # Save keys to state api_keys = { "openai": openai_key, "gemini": gemini_key, "anthropic": anthropic_key, "mistral": mistral_key } state_manager.update_state({"api_keys": api_keys}) # Check if we have at least one valid key has_valid_key = any([ openai_key and state_manager.get_state().get("validated_keys", {}).get("openai", {}).get("valid", False), gemini_key and state_manager.get_state().get("validated_keys", {}).get("gemini", {}).get("valid", False) ]) if not has_valid_key and (openai_key or gemini_key): st.warning("Please test your API keys before continuing") ``` ## Benefits of Improved Onboarding 1. **Increased User Retention** - Smoother onboarding leads to higher completion rates - Clear guidance reduces frustration and abandonment - Faster time-to-value improves user satisfaction 2. **Reduced Support Burden** - Better self-service options decrease support tickets - Clearer instructions prevent common setup issues - Automated validation catches problems early 3. **Higher Feature Adoption** - Users understand available features better - Guided setup encourages exploration of capabilities - Contextual help improves feature discovery 4. **Improved User Experience** - Consistent design creates a professional impression - Responsive layout works across all devices - Intuitive navigation reduces cognitive load 5. **Better Data Quality** - Proper validation ensures working API keys - Clear requirements improve data completeness - Structured setup leads to better configuration ## Implementation Timeline - **Week 1**: Design and prototype core improvements - **Week 2**: Implement unified state management and API validation - **Week 3**: Develop UI components and responsive design - **Week 4**: Create welcome and summary screens - **Week 5**: Add help content and contextual assistance - **Week 6**: Testing, refinement, and documentation ## Conclusion The proposed improvements to the onboarding process will significantly enhance the user experience for new AI-Writer users. By implementing a more intuitive, guided, and responsive setup flow, we can increase user retention, reduce support needs, and help users get value from the platform faster. These changes represent a comprehensive overhaul of the current system, addressing both technical and user experience issues while maintaining compatibility with the existing codebase.