Files
ALwrity/Roadmap TBDs/ONBOARDING_IMPROVEMENTS.md
2025-04-21 21:07:35 +05:30

631 lines
24 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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("""
<script>
var width = window.innerWidth;
if (width < 768) {
document.documentElement.style.setProperty('--layout', 'mobile');
} else {
document.documentElement.style.setProperty('--layout', 'desktop');
}
</script>
<style>
/* Mobile-first styles */
.container {
padding: 1rem;
margin-bottom: 1rem;
}
/* Desktop adjustments */
@media (min-width: 768px) {
.container {
padding: 2rem;
margin-bottom: 2rem;
}
}
</style>
""", 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"""
<div class="api-key-input {'required' if required else 'optional'}">
<label>{display_label}</label>
<div class="input-help-text">{help_text}</div>
</div>
""", 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("""
<div class="welcome-container">
<h1>Welcome to AI-Writer! 👋</h1>
<p class="welcome-subtitle">Let's get you set up in just a few minutes.</p>
</div>
""", 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.