Added new features to the project

This commit is contained in:
ajaysi
2025-06-30 07:49:48 +05:30
parent bbe56a364d
commit b21cbb68da
48 changed files with 19774 additions and 1889 deletions

View File

@@ -0,0 +1,169 @@
# AI Web Researcher Dashboard for Content Creators
## Overview
The AI Web Researcher Dashboard is a comprehensive suite of research tools designed specifically for content creators. This dashboard integrates various web research modules to streamline the content research process, enhance content quality, and improve workflow efficiency.
## Available Research Modules
### 1. Search Engine Research Tools
#### Google SERP Search
- **Functionality**: Retrieves organic search results, People Also Ask questions, and related searches
- **Best for**: Initial topic research, understanding search intent, and identifying content gaps
- **Key features**: Comprehensive search results with structured data extraction
#### Tavily AI Search
- **Functionality**: Advanced AI-powered search with semantic understanding
- **Best for**: In-depth research requiring contextual understanding
- **Key features**: Provides direct answers to questions and follow-up question suggestions
### 2. Neural Search Tools
#### Metaphor Neural Search
- **Functionality**: Semantic search technology for finding related content
- **Best for**: Discovering content based on conceptual similarity rather than keyword matching
- **Key features**: Find similar articles, competitor analysis, and content inspiration
### 3. Trend Analysis Tools
#### Google Trends Researcher
- **Functionality**: Analyzes search term popularity over time
- **Best for**: Content planning, seasonal topic identification, and trend forecasting
- **Key features**: Interest over time visualization, regional interest mapping, and related query analysis
### 4. Web Crawling & Analysis Tools
#### Async Web Crawler
- **Functionality**: Crawls websites to extract structured content
- **Best for**: Content auditing, competitor analysis, and data extraction
- **Key features**: Extracts titles, descriptions, main content, headings, links, and images
#### Firecrawl Web Crawler
- **Functionality**: Specialized crawler for single-page or website scraping
- **Best for**: Detailed content extraction from specific URLs
- **Key features**: Configurable depth and page limits for targeted crawling
#### Website Analyzer
- **Functionality**: Comprehensive website analysis for content and technical aspects
- **Best for**: Content quality assessment, SEO analysis, and technical audits
- **Key features**: Content quality metrics, SEO recommendations, and technical performance insights
## Optimal Workflows for Content Creators
### Research Workflow 1: Comprehensive Topic Research
1. **Initial Exploration** (Google SERP Search)
- Search for your main topic to understand the search landscape
- Analyze People Also Ask questions to identify user intent
2. **In-depth Research** (Tavily AI Search)
- Use identified subtopics for deeper research
- Collect factual information and expert insights
3. **Competitive Analysis** (Metaphor Neural Search + Web Crawler)
- Find similar content from competitors
- Analyze content structure and approach
4. **Trend Validation** (Google Trends Researcher)
- Verify topic popularity and seasonal patterns
- Identify related trending topics
### Research Workflow 2: Content Gap Analysis
1. **Competitor Content Mapping** (Async Web Crawler)
- Crawl competitor websites to extract content structure
- Identify their content categories and topics
2. **Topic Opportunity Discovery** (Google Trends + Metaphor Search)
- Research trending topics in your niche
- Find content areas with high interest but low competition
3. **Content Quality Benchmarking** (Website Analyzer)
- Analyze top-performing content in your niche
- Identify quality benchmarks and content standards
### Research Workflow 3: Content Refresh & Update
1. **Content Performance Analysis** (Website Analyzer)
- Analyze existing content for improvement opportunities
- Identify outdated information and gaps
2. **Current Trend Integration** (Google Trends Researcher)
- Research current trends related to your content
- Identify new angles and perspectives
3. **Competitive Edge Research** (Tavily AI + Metaphor Search)
- Research what competitors have updated recently
- Find new research, statistics, and information to incorporate
## Integration with Content Creation Process
### Pre-Writing Phase
- Use research modules to gather comprehensive information
- Create content briefs based on research findings
- Identify key points, statistics, and examples to include
### Writing Phase
- Reference research findings for accurate information
- Use competitor insights to differentiate your content
- Incorporate trending topics and keywords
### Post-Publishing Phase
- Monitor content performance against researched benchmarks
- Update content based on new research findings
- Plan related content based on research insights
## Dashboard Usage Examples
### Example 1: Creating a Comprehensive Blog Post
1. Start with Google SERP Search for your main topic
2. Use Tavily AI Search to gather in-depth information on subtopics
3. Analyze competitor content with Metaphor Neural Search
4. Check topic seasonality with Google Trends Researcher
5. Create content that addresses all aspects discovered in research
### Example 2: Developing a Content Strategy
1. Use Google Trends to identify trending topics in your niche
2. Analyze competitor websites with Async Web Crawler
3. Research content gaps using Metaphor Neural Search
4. Prioritize content topics based on trend data and competition
5. Create a content calendar incorporating research insights
### Example 3: Updating Existing Content
1. Analyze current content with Website Analyzer
2. Research new developments with Tavily AI Search
3. Check for changing trends with Google Trends Researcher
4. Identify new angles with Metaphor Neural Search
5. Update content with new information and perspectives
## Best Practices for Effective Research
1. **Start Broad, Then Narrow**: Begin with general search tools before using specialized ones
2. **Combine Multiple Research Methods**: Use different modules for comprehensive insights
3. **Focus on User Intent**: Prioritize research that reveals what your audience wants
4. **Validate with Data**: Use trend analysis to validate topic importance
5. **Organize Research Findings**: Create structured notes from your research
6. **Set Research Goals**: Define what you need to learn before starting
7. **Schedule Regular Research**: Keep content updated with periodic research
## Technical Requirements
- API keys for various services (Google, Tavily, Metaphor, etc.)
- Proper configuration in the .env file
- Sufficient system resources for web crawling operations
## Future Enhancements
- Integration with content planning calendar
- Automated research reports
- Competitive content gap analysis
- AI-powered content brief generation
- Customizable research workflows
---
This dashboard is designed to streamline the research process for content creators, providing powerful tools to enhance content quality, relevance, and performance. By following the suggested workflows and best practices, content creators can significantly improve their research efficiency and content outcomes.

View File

@@ -0,0 +1,98 @@
# AI Web Researcher Dashboard
## Overview
The AI Web Researcher Dashboard is a modern, intuitive interface designed specifically for content creators and digital marketing professionals. This dashboard integrates various web research tools to streamline the content research process, enhance content quality, and improve workflow efficiency.
## Features
### 1. Intuitive User Interface
- Modern, colorful, and professional design
- Easy navigation through different research tools
- Responsive layout that works on various screen sizes
### 2. Integrated Research Tools
- **Search Engine Research**: Google SERP Search and Tavily AI Search
- **Neural Search**: Metaphor Neural Search for finding conceptually similar content
- **Trend Analysis**: Google Trends Researcher for analyzing search term popularity
- **Web Crawling & Analysis**: Tools for extracting and analyzing web content
### 3. Guided Research Workflows
- Comprehensive Topic Research workflow
- Content Gap Analysis workflow
- Content Refresh & Update workflow
## Installation
1. Ensure you have Python 3.8+ installed
2. Install the required dependencies:
```
pip install -r requirements.txt
```
3. Set up the necessary API keys in your environment variables or .env file
## Usage
1. Navigate to the dashboard directory:
```
cd AI-Writer/lib/alwrity_ui/alwrity_researcher
```
2. Run the dashboard:
```
python -m streamlit run main.py
```
3. Access the dashboard in your web browser at http://localhost:8501
## Dashboard Sections
### Dashboard Home
Provides an overview of available research tools and featured workflows.
### Search Tools
Access to Google SERP Search and Tavily AI Search for comprehensive search capabilities.
### Neural Search
Use Metaphor Neural Search to find content based on conceptual similarity rather than keyword matching.
### Trend Analysis
Analyze search term popularity over time using Google Trends Researcher.
### Web Crawling
Extract structured content from websites using various web crawling tools.
### Research Workflows
Guided workflows that combine multiple tools for specific research objectives.
## Current Implementation Status
This is the initial implementation of the dashboard with placeholder functionality. The UI is fully implemented, but the actual integration with the AI web research modules will be completed in the next phase.
### What's Implemented
- Complete user interface with all sections and forms
- Mock data visualization for demonstration purposes
- Placeholder functionality for all research tools
### Next Steps
- Integrate with actual AI web research modules
- Implement data processing and visualization with real data
- Add user authentication and result saving functionality
## Technical Details
- Built with Streamlit for rapid UI development
- Modular design for easy extension and maintenance
- Responsive layout that works on desktop and mobile devices
## File Structure
- `main.py`: Entry point for the application
- `dashboard.py`: Main dashboard implementation
- `utils.py`: Utility functions for data processing and visualization
- `style.css`: Custom CSS for styling the dashboard
- `requirements.txt`: Required Python packages
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.

View File

@@ -0,0 +1,66 @@
import os
import streamlit as st
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
def get_api_key(key_name):
"""Get API key from environment variables or Streamlit secrets"""
# Try to get from environment variables first
api_key = os.getenv(key_name)
# If not found in environment, try Streamlit secrets
if not api_key and key_name in st.secrets:
api_key = st.secrets[key_name]
return api_key
def check_api_configuration():
"""Check if all required API keys are configured"""
api_status = {
"SERPER_API_KEY": bool(get_api_key("SERPER_API_KEY")),
"TAVILY_API_KEY": bool(get_api_key("TAVILY_API_KEY")),
"METAPHOR_API_KEY": bool(get_api_key("METAPHOR_API_KEY")),
"FIRECRAWL_API_KEY": bool(get_api_key("FIRECRAWL_API_KEY"))
}
return api_status
def display_api_configuration_status():
"""Display API configuration status in the sidebar with improved styling"""
api_status = check_api_configuration()
st.sidebar.markdown("<div class='api-status-container'>", unsafe_allow_html=True)
st.sidebar.markdown("<div class='api-status-title'>API Configuration Status</div>", unsafe_allow_html=True)
# Display API status with improved styling
for api_name, is_configured in api_status.items():
if is_configured:
st.sidebar.markdown(
f"<div class='api-status-item configured'>✅ {api_name}</div>",
unsafe_allow_html=True
)
else:
st.sidebar.markdown(
f"<div class='api-status-item not-configured'>❌ {api_name}</div>",
unsafe_allow_html=True
)
# Display instructions if any API key is missing with improved styling
if not all(api_status.values()):
with st.sidebar.expander("How to configure API keys"):
st.markdown("""
<div style="background-color: #f8fafc; padding: 12px; border-radius: 6px; border-left: 4px solid #3b82f6;">
<p style="margin-bottom: 10px; font-weight: 500;">To configure missing API keys, create a <code>.env</code> file in the project root with the following format:</p>
<pre style="background-color: #f1f5f9; padding: 10px; border-radius: 4px; overflow-x: auto; font-size: 0.9em;">
SERPER_API_KEY=your_serper_api_key
TAVILY_API_KEY=your_tavily_api_key
METAPHOR_API_KEY=your_metaphor_api_key
FIRECRAWL_API_KEY=your_firecrawl_api_key
</pre>
<p style="margin-top: 10px;">Alternatively, you can set these as environment variables in your system.</p>
</div>
""", unsafe_allow_html=True)
st.sidebar.markdown("</div>", unsafe_allow_html=True)

View File

@@ -0,0 +1,729 @@
import streamlit as st
import sys
import os
from pathlib import Path
# Add parent directory to path to import modules
sys.path.append(str(Path(__file__).parent.parent.parent))
# Import utils module
from utils import (
load_css,
display_google_serp_results,
display_tavily_results,
display_metaphor_results,
display_google_trends_results,
display_crawler_results,
display_analyzer_results
)
# Configure Streamlit page settings
st.set_page_config(
page_title="AI Web Researcher Dashboard",
page_icon="🔍",
layout="wide",
initial_sidebar_state="expanded"
)
# Apply custom CSS immediately
st.markdown("""
<style>
.main-header {
font-size: 24px;
font-weight: bold;
margin-bottom: 20px;
}
.category-header {
font-size: 20px;
font-weight: bold;
margin: 15px 0;
color: #0066cc;
}
/* Make the dashboard responsive */
.stTabs [data-baseweb="tab-list"] {
gap: 2px;
flex-wrap: wrap;
}
.stTabs [data-baseweb="tab"] {
white-space: pre-wrap;
min-width: fit-content;
font-size: 14px;
padding: 8px 16px;
}
/* Adjust container width */
.block-container {
max-width: 95% !important;
padding: 1rem 1rem 10rem !important;
}
/* Additional styling for better visibility */
.stApp {
background-color: #f8f9fa;
}
.stTabs [data-baseweb="tab"] [data-testid="stMarkdownContainer"] p {
font-size: 14px !important;
margin-bottom: 0px !important;
}
.stTabs [data-baseweb="tab-list"] button {
background-color: #ffffff;
border: 1px solid #e9ecef;
border-radius: 4px;
margin: 2px;
}
.stTabs [data-baseweb="tab-list"] button[aria-selected="true"] {
background-color: #e7f1ff;
border-color: #b8daff;
}
</style>
""", unsafe_allow_html=True)
# CSS is now loaded at the top of the file
# Initialize session state variables
def init_session_state():
if 'current_section' not in st.session_state:
st.session_state['current_section'] = 'Dashboard Home'
# Initialize session state at startup
init_session_state()
def main():
# Initialize session state before accessing it
init_session_state()
# Main navigation header
st.markdown('<div class="main-nav-header">AI Web Researcher</div>', unsafe_allow_html=True)
# Create tabs for navigation
selected_section = st.tabs([
"🏠 Dashboard Home",
"🔍 Search Tools",
"🧠 Neural Search",
"📈 Trend Analysis",
"🕸️ Web Crawling",
"📚 Academic Research",
"📋 Research Workflows"
])
# Display appropriate section based on selected tab
with selected_section[0]:
display_home()
with selected_section[1]:
display_search_tools()
with selected_section[2]:
display_neural_search()
with selected_section[3]:
display_trend_analysis()
with selected_section[4]:
display_web_crawling()
with selected_section[5]:
display_academic_research()
with selected_section[6]:
display_research_workflows()
# Ensure CSS is consistently applied
load_css()
def display_home():
# Main header with improved styling
st.markdown('<div class="main-header">AI Web Researcher Dashboard</div>', unsafe_allow_html=True)
# Introduction with better formatting
st.markdown("""
<div class="intro-container">
<p class="intro-text">Welcome to the <span class="intro-highlight">AI Web Researcher Dashboard</span>, a comprehensive suite of research tools designed
specifically for content creators and digital marketing professionals. This dashboard integrates
various web research modules to streamline your content research process, enhance content quality,
and improve workflow efficiency.</p>
</div>
""", unsafe_allow_html=True)
# Quick access to tool categories with improved header
st.markdown('<div class="category-header">Research Tool Categories</div>', unsafe_allow_html=True)
# Use 2 columns with equal width for better layout
col1, col2 = st.columns([1, 1])
with col1:
st.markdown("""
<div class="tool-card">
<div class="tool-title">🔍 Search Engine Research</div>
<div class="tool-description">Powerful search tools to understand search intent, identify content gaps, and discover high-performing content in your niche</div>
<div class="tool-features"><b>Includes:</b> Google SERP Search • Tavily AI Search</div>
<div class="tool-features"><b>Use cases:</b> Keyword research, competitor analysis, content planning, identifying user questions</div>
<div style="margin-top: 12px;">
<span class="tool-badge">SERP Analysis</span>
<span class="tool-badge ai-powered">AI-Powered</span>
</div>
</div>
<div class="tool-card">
<div class="tool-title">🧠 Neural Search</div>
<div class="tool-description">Advanced semantic search technology that understands concepts rather than just keywords to find truly relevant content</div>
<div class="tool-features"><b>Includes:</b> Metaphor Neural Search</div>
<div class="tool-features"><b>Use cases:</b> Finding conceptually similar articles, discovering unique content angles, competitive research</div>
<div style="margin-top: 12px;">
<span class="tool-badge semantic">Semantic</span>
<span class="tool-badge deep-learning">Deep Learning</span>
</div>
</div>
""", unsafe_allow_html=True)
with col2:
st.markdown("""
<div class="tool-card">
<div class="tool-title">📈 Trend Analysis</div>
<div class="tool-description">Comprehensive trend analysis tools that track search term popularity over time to identify seasonal patterns and emerging topics</div>
<div class="tool-features"><b>Includes:</b> Google Trends Researcher</div>
<div class="tool-features"><b>Use cases:</b> Seasonal content planning, topic validation, identifying rising trends, content calendar optimization</div>
<div style="margin-top: 12px;">
<span class="tool-badge time-series">Time Series</span>
<span class="tool-badge forecasting">Forecasting</span>
</div>
</div>
<div class="tool-card">
<div class="tool-title">🕸️ Web Crawling & Analysis</div>
<div class="tool-description">Powerful web extraction tools that gather and structure content from websites for in-depth analysis and insights</div>
<div class="tool-features"><b>Includes:</b> Async Web Crawler • Firecrawl Web Crawler • Website Analyzer</div>
<div class="tool-features"><b>Use cases:</b> Content auditing, competitor analysis, data extraction, market research, content aggregation</div>
<div style="margin-top: 12px;">
<span class="tool-badge content-extraction">Content Extraction</span>
<span class="tool-badge data-analysis">Data Analysis</span>
</div>
</div>
""", unsafe_allow_html=True)
# Featured workflow with improved header
st.markdown('<div class="category-header">Featured Research Workflow</div>', unsafe_allow_html=True)
st.markdown("""
<div class="workflow-card">
<div class="workflow-title">Comprehensive Topic Research Workflow</div>
<p style="color: #4b5563; margin-bottom: 1.25rem;">Follow this proven research workflow to develop comprehensive, data-driven content that resonates with your audience and performs well in search.</p>
<div class="workflow-step-container">
<div class="workflow-step-number">1</div>
<div class="workflow-step-content">
<div class="step-title">Initial Exploration</div>
<div class="workflow-step-description">Use Google SERP Search to understand the search landscape, identify user intent, and discover what content currently ranks well. Analyze People Also Ask questions to identify key user concerns.</div>
</div>
</div>
<div class="workflow-step-container">
<div class="workflow-step-number">2</div>
<div class="workflow-step-content">
<div class="step-title">In-depth Research</div>
<div class="workflow-step-description">Use Tavily AI Search for deeper research on identified subtopics. The AI-powered search provides more contextual information and helps uncover expert insights that might be missed in traditional searches.</div>
</div>
</div>
<div class="workflow-step-container">
<div class="workflow-step-number">3</div>
<div class="workflow-step-content">
<div class="step-title">Competitive Analysis</div>
<div class="workflow-step-description">Use Metaphor Neural Search to find conceptually similar content from competitors. Analyze their approach, identify content gaps, and discover unique angles that differentiate your content.</div>
</div>
</div>
<div class="workflow-step-container">
<div class="workflow-step-number">4</div>
<div class="workflow-step-content">
<div class="step-title">Trend Validation</div>
<div class="workflow-step-description">Use Google Trends Researcher to verify topic popularity, identify seasonal patterns, and discover related trending topics. This ensures your content is timely and aligned with current audience interests.</div>
</div>
</div>
<div class="workflow-step-container">
<div class="workflow-step-number">5</div>
<div class="workflow-step-content">
<div class="step-title">Content Extraction</div>
<div class="workflow-step-description">Use Web Crawling tools to extract specific content from top-performing pages for detailed analysis. This helps identify content structure, depth, and formatting approaches that resonate with your audience.</div>
</div>
</div>
</div>
""", unsafe_allow_html=True)
def display_search_tools():
st.markdown('<div class="main-header">Search Engine Research Tools</div>', unsafe_allow_html=True)
# Google SERP Search
st.markdown('<div class="category-header">Google SERP Search</div>', unsafe_allow_html=True)
st.markdown("""
<div class="tool-card">
<div class="tool-title">Google SERP Search</div>
<div class="tool-description">Retrieves organic search results, People Also Ask questions, and related searches</div>
<div class="tool-features">
<b>Best for:</b> Initial topic research, understanding search intent, and identifying content gaps<br>
<b>Key features:</b> Comprehensive search results with structured data extraction
</div>
</div>
""", unsafe_allow_html=True)
# Input form for Google SERP Search
with st.form("google_serp_search_form"):
search_query = st.text_input("Enter your search query")
col1, col2 = st.columns(2)
with col1:
num_results = st.slider("Number of results", 5, 30, 10)
with col2:
include_paa = st.checkbox("Include People Also Ask", value=True)
submitted = st.form_submit_button("Search")
if submitted and search_query:
try:
with st.spinner("Searching Google SERP..."):
# Import the actual module
from ai_web_researcher.google_serp_search import google_search
# Call the actual implementation
results = google_search(search_query)
# Display the results
if results:
display_google_serp_results(results)
else:
st.error("No results found. Please try a different query.")
except Exception as e:
st.error(f"Error performing Google SERP search: {str(e)}")
st.info("Please check your API configuration in the .env file.")
st.info("Required API: SERPER_API_KEY for Google SERP Search")
display_google_serp_results(None)
# Tavily AI Search
st.markdown('<div class="category-header">Tavily AI Search</div>', unsafe_allow_html=True)
st.markdown("""
<div class="tool-card">
<div class="tool-title">Tavily AI Search</div>
<div class="tool-description">Advanced AI-powered search with semantic understanding</div>
<div class="tool-features">
<b>Best for:</b> In-depth research requiring contextual understanding<br>
<b>Key features:</b> Provides direct answers to questions and follow-up question suggestions
</div>
</div>
""", unsafe_allow_html=True)
# Input form for Tavily AI Search
with st.form("tavily_ai_search_form"):
search_query = st.text_input("Enter your search query or question")
search_depth = st.select_slider("Search depth", options=["basic", "medium", "deep"], value="medium")
submitted = st.form_submit_button("Search with Tavily AI")
if submitted and search_query:
try:
with st.spinner("Searching with Tavily AI..."):
# Import the actual module
from ai_web_researcher.tavily_ai_search import do_tavily_ai_search
# Call the actual implementation
results = do_tavily_ai_search(search_query, search_depth=search_depth)
# Display the results
if results:
display_tavily_results(results)
else:
st.error("No results found. Please try a different query.")
except Exception as e:
st.error(f"Error performing Tavily AI search: {str(e)}")
st.info("Please check your API configuration in the .env file.")
st.info("Required API: TAVILY_API_KEY for Tavily AI Search")
display_tavily_results(None)
def display_neural_search():
st.markdown('<div class="main-header">Neural Search Tools</div>', unsafe_allow_html=True)
# Metaphor Neural Search
st.markdown('<div class="category-header">Metaphor Neural Search</div>', unsafe_allow_html=True)
st.markdown("""
<div class="tool-card">
<div class="tool-title">Metaphor Neural Search</div>
<div class="tool-description">Semantic search technology for finding related content</div>
<div class="tool-features">
<b>Best for:</b> Discovering content based on conceptual similarity rather than keyword matching<br>
<b>Key features:</b> Find similar articles, competitor analysis, and content inspiration
</div>
</div>
""", unsafe_allow_html=True)
# Input form for Metaphor Neural Search
with st.form("metaphor_search_form"):
st.markdown("**Search by keyword or find similar content to a URL**")
search_type = st.radio("Search type", ["Keyword Search", "Similar Content Search"])
if search_type == "Keyword Search":
search_query = st.text_input("Enter your search query")
url_input = ""
else:
search_query = ""
url_input = st.text_input("Enter a URL to find similar content")
num_results = st.slider("Number of results", 3, 20, 5)
submitted = st.form_submit_button("Search with Metaphor")
if submitted and (search_query or url_input):
try:
with st.spinner("Searching with Metaphor Neural Search..."):
# Import the actual module
from ai_web_researcher.metaphor_basic_neural_web_search import metaphor_search_articles, metaphor_find_similar
# Call the actual implementation
if search_query:
results = metaphor_search_articles(search_query, num_results=num_results)
else:
results = metaphor_find_similar(url_input, num_results=num_results)
# Display the results
if results:
display_metaphor_results(results)
else:
st.error("No results found. Please try a different query.")
except Exception as e:
st.error(f"Error performing Metaphor Neural search: {str(e)}")
st.info("Please check your API configuration in the .env file.")
st.info("Required API: METAPHOR_API_KEY for Metaphor Neural Search")
display_metaphor_results(None)
def display_trend_analysis():
st.markdown('<div class="main-header">Trend Analysis Tools</div>', unsafe_allow_html=True)
# Google Trends Researcher
st.markdown('<div class="category-header">Google Trends Researcher</div>', unsafe_allow_html=True)
st.markdown("""
<div class="tool-card">
<div class="tool-title">Google Trends Researcher</div>
<div class="tool-description">Analyze search term popularity and related queries</div>
<div class="tool-features">
<b>Best for:</b> Content planning, trend forecasting, and seasonal content optimization<br>
<b>Key features:</b> Interest over time charts, related queries, and regional interest data
</div>
</div>
""", unsafe_allow_html=True)
# Input form for Google Trends Researcher
with st.form("google_trends_form"):
search_terms = st.text_area("Enter search terms (one per line)")
col1, col2 = st.columns(2)
with col1:
time_frame = st.select_slider("Time range", options=["past_hour", "past_day", "past_week", "past_month", "past_90_days", "past_12_months", "past_5_years"], value="past_12_months")
with col2:
geo = st.text_input("Geographic region (ISO country code, e.g., 'US')", value="US")
submitted = st.form_submit_button("Analyze Trends")
if submitted and search_terms:
try:
with st.spinner("Analyzing Google Trends..."):
# Import the actual module
from ai_web_researcher.google_trends_researcher import do_google_trends_analysis
# Call the actual implementation
search_terms_list = [term.strip() for term in search_terms.split('\n') if term.strip()]
results = do_google_trends_analysis(search_terms_list, time_frame=time_frame, geo=geo)
# Display the results
if results:
display_google_trends_results(results)
else:
st.error("No trend data found. Please try different search terms.")
except Exception as e:
st.error(f"Error analyzing Google Trends: {str(e)}")
st.info("Google Trends analysis doesn't require an API key, but there might be rate limiting or network issues.")
display_google_trends_results(None)
def display_web_crawling():
st.markdown('<div class="main-header">Web Crawling & Analysis Tools</div>', unsafe_allow_html=True)
# Create tabs for different crawling tools
tab1, tab2, tab3 = st.tabs(["Firecrawl Web Crawler", "Website Analyzer", "Async Web Crawler"])
with tab1:
st.markdown("""
<div class="tool-card">
<div class="tool-title">Firecrawl Web Crawler</div>
<div class="tool-description">Extract structured content from websites</div>
<div class="tool-features">
<b>Best for:</b> Content extraction, competitor analysis, and website auditing<br>
<b>Key features:</b> Extracts titles, descriptions, headings, and content from web pages
</div>
</div>
""", unsafe_allow_html=True)
# Input form for Firecrawl Web Crawler
with st.form("firecrawl_form"):
website_url = st.text_input("Enter website URL")
depth = st.slider("Crawl depth", 1, 5, 1)
max_pages = st.slider("Maximum pages", 1, 50, 10)
submitted = st.form_submit_button("Crawl Website")
if submitted and website_url:
try:
with st.spinner("Crawling website..."):
# Import the actual module
from ai_web_researcher.firecrawl_web_crawler import scrape_website
# Call the actual implementation
results = scrape_website(website_url, depth=depth, max_pages=max_pages)
# Display the results
if results:
display_crawler_results(results)
else:
st.error("No crawler results found. Please try a different URL.")
except Exception as e:
st.error(f"Error crawling website: {str(e)}")
st.info("Please check your API configuration in the .env file.")
st.info("Required API: FIRECRAWL_API_KEY for Web Crawler")
display_crawler_results(None)
with tab2:
st.markdown("""
<div class="tool-card">
<div class="tool-title">Website Analyzer</div>
<div class="tool-description">Analyze website content and structure</div>
<div class="tool-features">
<b>Best for:</b> Content analysis, SEO auditing, and competitor research<br>
<b>Key features:</b> Content analysis, keyword extraction, and readability metrics
</div>
</div>
""", unsafe_allow_html=True)
# Input form for Website Analyzer
with st.form("website_analyzer_form"):
website_url = st.text_input("Enter website URL")
analyze_type = st.selectbox("Analysis type", ["Basic Analysis", "SEO Analysis", "Content Analysis", "Competitor Analysis"])
submitted = st.form_submit_button("Analyze Website")
if submitted and website_url:
st.info("Website Analyzer is coming soon. This feature is under development.")
with tab3:
st.markdown("""
<div class="tool-card">
<div class="tool-title">Async Web Crawler</div>
<div class="tool-description">High-performance asynchronous web crawler</div>
<div class="tool-features">
<b>Best for:</b> Large-scale crawling, data extraction, and content aggregation<br>
<b>Key features:</b> Fast, efficient crawling with customizable extraction rules
</div>
</div>
""", unsafe_allow_html=True)
# Input form for Async Web Crawler
with st.form("async_crawler_form"):
website_url = st.text_input("Enter website URL")
max_urls = st.slider("Maximum URLs to crawl", 10, 100, 30)
submitted = st.form_submit_button("Start Crawling")
if submitted and website_url:
st.info("Async Web Crawler is coming soon. This feature is under development.")
def display_academic_research():
st.markdown('<div class="main-header">Academic Research Tools</div>', unsafe_allow_html=True)
# ArXiv Search Section
st.markdown('<div class="category-header">ArXiv Scholarly Search</div>', unsafe_allow_html=True)
# Search Parameters
search_col1, search_col2 = st.columns([2, 1])
with search_col1:
search_query = st.text_input("🔍 Enter research topic or keywords", key="arxiv_search")
with search_col2:
max_results = st.number_input("Maximum Results", min_value=1, max_value=50, value=10)
# Search Button
if st.button("🔎 Search ArXiv", key="arxiv_search_button"):
if search_query:
with st.spinner("Searching ArXiv database..."):
try:
# Import arxiv search function
from ai_web_researcher.arxiv_schlorly_research import fetch_arxiv_data, create_dataframe
# Fetch results
results = fetch_arxiv_data(search_query, max_results)
if results:
# Create DataFrame
df = create_dataframe(results, ["Title", "Published Date", "ArXiv ID", "Summary", "PDF URL"])
# Display results in an expander
with st.expander("📚 Search Results", expanded=True):
# Display each paper with options to view abstract and download
for idx, row in df.iterrows():
st.markdown(f"### {row['Title']}")
st.markdown(f"*Published: {row['Published Date']}*")
# Create columns for buttons
btn_col1, btn_col2, btn_col3 = st.columns([1, 1, 1])
with btn_col1:
if st.button(f"📄 View Abstract #{idx}"):
st.markdown(f"**Abstract:**\n{row['Summary']}")
with btn_col2:
st.markdown(f"[📥 Download PDF]({row['PDF URL']})")
if st.button(f"📝 Summarize #{idx}"):
with st.spinner("Generating summary..."):
try:
from ai_web_researcher.gpt_summarize_web_content import summarize_web_content
summary = summarize_web_content(row['PDF URL'])
if summary:
st.markdown("### GPT Summary")
st.markdown(summary)
# Add export option for the summary
st.download_button(
label="📥 Export Summary",
data=summary,
file_name=f"summary_{row['ArXiv ID']}.txt",
mime="text/plain"
)
except Exception as e:
st.error(f"Error generating summary: {str(e)}")
with btn_col3:
if st.button(f"🔍 Related Web Content #{idx}"):
# Use Google SERP to find related content
from ai_web_researcher.google_serp_search import google_search
web_results = google_search(row['Title'])
if web_results:
st.markdown("### Related Web Content")
for result in web_results['organic'][:3]:
st.markdown(f"- [{result['title']}]({result['link']})\n {result['snippet']}")
st.markdown("---")
else:
st.warning("No results found. Try modifying your search terms.")
except Exception as e:
st.error(f"An error occurred while searching: {str(e)}")
else:
st.warning("Please enter a search query.")
# Research Notes Section
st.markdown('<div class="category-header">Research Notes</div>', unsafe_allow_html=True)
# Initialize session state for notes if not exists
if 'research_notes' not in st.session_state:
st.session_state.research_notes = {}
notes_col1, notes_col2 = st.columns([2, 1])
with notes_col1:
paper_id = st.text_input("ArXiv ID or Paper Title", key="notes_paper_id")
notes_content = st.text_area("Research Notes", height=200, key="notes_content")
if st.button("Save Notes"):
if paper_id:
st.session_state.research_notes[paper_id] = notes_content
st.success("Notes saved successfully!")
else:
st.warning("Please enter a paper identifier.")
with notes_col2:
st.markdown("### Saved Notes")
for paper_id, notes in st.session_state.research_notes.items():
with st.expander(f"📝 {paper_id}"):
st.text_area("Saved Notes", value=notes, height=150, key=f"saved_{paper_id}", disabled=True)
if st.button("Export Notes", key=f"export_{paper_id}"):
notes_export = f"Research Notes for {paper_id}\n\n{notes}"
st.download_button(
label="📥 Download Notes",
data=notes_export,
file_name=f"research_notes_{paper_id}.txt",
mime="text/plain"
)
# Citation Management Section
st.markdown('<div class="category-header">Citation Management</div>', unsafe_allow_html=True)
# BibTeX Export
st.markdown("### Export Citations")
arxiv_id = st.text_input("Enter ArXiv ID for citation export")
if arxiv_id and st.button("Generate BibTeX"):
try:
from ai_web_researcher.arxiv_schlorly_research import arxiv_bibtex
bibtex = arxiv_bibtex(arxiv_id)
if bibtex:
st.code(bibtex, language="bibtex")
st.download_button(
label="📥 Download BibTeX",
data=bibtex,
file_name=f"citation_{arxiv_id}.bib",
mime="text/plain"
)
except Exception as e:
st.error(f"Error generating citation: {str(e)}")
def display_research_workflows():
st.markdown('<div class="main-header">Research Workflows</div>', unsafe_allow_html=True)
st.markdown("""
<div class="workflow-description">
Research workflows combine multiple research tools to provide comprehensive insights for specific content creation tasks.
Select a workflow to get started.
</div>
""", unsafe_allow_html=True)
# Create tabs for different workflows
tab1, tab2, tab3 = st.tabs(["Topic Research", "Competitor Analysis", "Trend Discovery"])
with tab1:
st.markdown("""
<div class="workflow-card">
<div class="workflow-title">Comprehensive Topic Research</div>
<div class="workflow-description">
This workflow helps you thoroughly research a topic for content creation by combining search results,
semantic understanding, and trend analysis.
</div>
</div>
""", unsafe_allow_html=True)
# Input form for Topic Research workflow
with st.form("topic_research_form"):
topic = st.text_input("Enter your topic")
include_trends = st.checkbox("Include trend analysis", value=True)
include_competitors = st.checkbox("Include competitor analysis", value=True)
submitted = st.form_submit_button("Start Research Workflow")
if submitted and topic:
st.info("Research workflows are coming soon. This feature is under development.")
with tab2:
st.markdown("""
<div class="workflow-card">
<div class="workflow-title">Competitor Content Analysis</div>
<div class="workflow-description">
This workflow analyzes your competitors' content to identify gaps and opportunities for your own content strategy.
</div>
</div>
""", unsafe_allow_html=True)
# Input form for Competitor Analysis workflow
with st.form("competitor_analysis_form"):
competitor_urls = st.text_area("Enter competitor URLs (one per line)")
topic_focus = st.text_input("Topic focus (optional)")
submitted = st.form_submit_button("Start Competitor Analysis")
if submitted and competitor_urls:
st.info("Research workflows are coming soon. This feature is under development.")
with tab3:
st.markdown("""
<div class="workflow-card">
<div class="workflow-title">Trend Discovery & Content Planning</div>
<div class="workflow-description">
This workflow identifies trending topics in your niche and helps you plan content around them.
</div>
</div>
""", unsafe_allow_html=True)
# Input form for Trend Discovery workflow
with st.form("trend_discovery_form"):
niche = st.text_input("Enter your niche or industry")
time_period = st.select_slider("Time period", options=["past_week", "past_month", "past_90_days", "past_12_months"], value="past_month")
submitted = st.form_submit_button("Discover Trends")
if submitted and niche:
st.info("Research workflows are coming soon. This feature is under development.")

View File

@@ -0,0 +1,14 @@
import streamlit as st
import sys
import os
from pathlib import Path
# Add the current directory to the path
sys.path.append(str(Path(__file__).parent))
# Import the dashboard module
from dashboard import main
# Run the dashboard
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,517 @@
/* Main Dashboard Styles */
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
background-color: #f0f4f8;
color: #1f2937;
background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.main-header {
font-size: 2.2rem;
background: linear-gradient(120deg, #1e3a8a 0%, #3b82f6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-align: center;
margin: 1.5rem 0;
font-weight: 700;
letter-spacing: -0.025em;
padding-bottom: 0.75rem;
border-bottom: 1px solid rgba(229, 231, 235, 0.5);
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.category-header {
font-size: 1.4rem;
background: linear-gradient(90deg, #2563eb 0%, #4f46e5 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-top: 1.5rem;
margin-bottom: 1rem;
font-weight: 600;
padding-left: 0.5rem;
border-left: 4px solid;
border-image: linear-gradient(to bottom, #3b82f6, #4f46e5) 1;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
/* Glassomorphic Tool Card Styles */
.tool-card {
background: linear-gradient(120deg, rgba(255, 255, 255, 0.8) 0%, rgba(240, 249, 255, 0.7) 100%);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 12px;
padding: 1.75rem;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
border: 1px solid rgba(255, 255, 255, 0.18);
margin-bottom: 1.5rem;
border-left: 4px solid;
border-image: linear-gradient(to bottom, rgba(59, 130, 246, 0.8), rgba(79, 70, 229, 0.8)) 1;
transition: all 0.3s ease;
}
.tool-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 30px rgba(31, 38, 135, 0.25);
border-image: linear-gradient(to bottom, rgba(59, 130, 246, 1), rgba(79, 70, 229, 1)) 1;
background: linear-gradient(120deg, rgba(255, 255, 255, 0.9) 0%, rgba(240, 249, 255, 0.8) 100%);
}
.tool-title {
font-size: 1.3rem;
font-weight: 600;
background: linear-gradient(90deg, #1e3a8a 0%, #3b82f6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 0.75rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.tool-description {
color: #374151;
margin-bottom: 1rem;
line-height: 1.6;
font-size: 1rem;
}
.tool-features {
font-size: 0.95rem;
color: #4b5563;
margin-bottom: 0.75rem;
line-height: 1.6;
background-color: rgba(243, 244, 246, 0.6);
padding: 0.85rem;
border-radius: 8px;
border: 1px solid rgba(229, 231, 235, 0.5);
}
/* Tool Badge Styles */
.tool-badge {
display: inline-block;
padding: 0.35rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 500;
margin-right: 0.5rem;
background-color: rgba(243, 244, 246, 0.8);
color: #4b5563;
border: 1px solid rgba(209, 213, 219, 0.5);
backdrop-filter: blur(5px);
}
.tool-badge.ai-powered {
background-color: rgba(79, 70, 229, 0.15);
color: #4338ca;
border-color: rgba(79, 70, 229, 0.3);
}
.tool-badge.semantic {
background-color: rgba(16, 185, 129, 0.15);
color: #065f46;
border-color: rgba(16, 185, 129, 0.3);
}
.tool-badge.deep-learning {
background-color: rgba(245, 158, 11, 0.15);
color: #92400e;
border-color: rgba(245, 158, 11, 0.3);
}
.tool-badge.time-series {
background-color: rgba(6, 182, 212, 0.15);
color: #0e7490;
border-color: rgba(6, 182, 212, 0.3);
}
.tool-badge.forecasting {
background-color: rgba(168, 85, 247, 0.15);
color: #6d28d9;
border-color: rgba(168, 85, 247, 0.3);
}
.tool-badge.content-extraction {
background-color: rgba(236, 72, 153, 0.15);
color: #be185d;
border-color: rgba(236, 72, 153, 0.3);
}
.tool-badge.data-analysis {
background-color: rgba(14, 165, 233, 0.15);
color: #0369a1;
border-color: rgba(14, 165, 233, 0.3);
}
/* Glassomorphic Workflow Card Styles */
.workflow-card {
background: linear-gradient(135deg, rgba(239, 246, 255, 0.8) 0%, rgba(219, 234, 254, 0.7) 100%);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 12px;
padding: 1.75rem;
margin-bottom: 1.5rem;
border-left: 4px solid;
border-image: linear-gradient(to bottom, rgba(37, 99, 235, 0.8), rgba(79, 70, 229, 0.8)) 1;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.workflow-title {
font-size: 1.3rem;
font-weight: 600;
background: linear-gradient(90deg, #1e3a8a 0%, #3b82f6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 1.25rem;
padding-bottom: 0.75rem;
border-bottom: 1px solid rgba(191, 219, 254, 0.5);
}
.workflow-step-container {
display: flex;
margin-bottom: 1.25rem;
background: linear-gradient(120deg, rgba(255, 255, 255, 0.7) 0%, rgba(240, 249, 255, 0.6) 100%);
border-radius: 10px;
padding: 1rem;
box-shadow: 0 4px 6px rgba(31, 38, 135, 0.1);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.workflow-step-number {
display: flex;
align-items: center;
justify-content: center;
width: 2rem;
height: 2rem;
background: linear-gradient(135deg, rgba(37, 99, 235, 0.9) 0%, rgba(79, 70, 229, 0.9) 100%);
color: white;
border-radius: 50%;
font-weight: 600;
margin-right: 1rem;
box-shadow: 0 4px 6px rgba(37, 99, 235, 0.3);
}
.workflow-step-content {
flex: 1;
}
.step-title {
font-weight: 600;
background: linear-gradient(90deg, #1e3a8a 0%, #3b82f6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 0.5rem;
font-size: 1.05rem;
}
.workflow-step-description {
color: #4b5563;
line-height: 1.5;
font-size: 0.95rem;
}
/* Navigation Styles */
.nav-header {
font-size: 2rem;
background: linear-gradient(120deg, #1e3a8a 0%, #3b82f6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-align: center;
margin: 1.5rem 0;
font-weight: 700;
letter-spacing: -0.025em;
padding-bottom: 0.75rem;
border-bottom: 1px solid rgba(229, 231, 235, 0.5);
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.nav-container {
background: linear-gradient(120deg, rgba(255, 255, 255, 0.8) 0%, rgba(240, 249, 255, 0.7) 100%);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 12px;
padding: 1.75rem;
margin-bottom: 1.5rem;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.nav-button {
background: linear-gradient(120deg, rgba(255, 255, 255, 0.8) 0%, rgba(240, 249, 255, 0.7) 100%);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1rem;
border: 1px solid rgba(255, 255, 255, 0.18);
border-left: 4px solid;
border-image: linear-gradient(to bottom, rgba(59, 130, 246, 0.8), rgba(79, 70, 229, 0.8)) 1;
transition: all 0.3s ease;
width: 100%;
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
}
.nav-button:hover {
transform: translateY(-5px);
box-shadow: 0 15px 30px rgba(31, 38, 135, 0.25);
border-image: linear-gradient(to bottom, rgba(59, 130, 246, 1), rgba(79, 70, 229, 1)) 1;
background: linear-gradient(120deg, rgba(255, 255, 255, 0.9) 0%, rgba(240, 249, 255, 0.8) 100%);
}
.nav-button.selected {
background: linear-gradient(120deg, rgba(239, 246, 255, 0.9) 0%, rgba(219, 234, 254, 0.8) 100%);
border-image: linear-gradient(to bottom, #3b82f6, #4f46e5) 1;
box-shadow: 0 8px 20px rgba(31, 38, 135, 0.2);
}
.nav-icon {
font-size: 1.8rem;
margin-bottom: 0.75rem;
background: linear-gradient(90deg, #1e3a8a 0%, #3b82f6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.nav-title {
font-size: 1.1rem;
font-weight: 600;
background: linear-gradient(90deg, #1e3a8a 0%, #3b82f6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-align: center;
}
[data-testid="stSidebar"] {
background-color: rgba(248, 250, 252, 0.7);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-right: 1px solid rgba(229, 231, 235, 0.5);
}
[data-testid="stSidebarNav"] {
background-color: transparent;
}
.st-emotion-cache-16txtl3 {
padding-top: 2rem;
}
.sidebar-header {
font-size: 1.3rem;
font-weight: 700;
color: #1e3a8a;
margin: 1rem 0;
padding-bottom: 0.75rem;
border-bottom: 1px solid rgba(229, 231, 235, 0.5);
text-align: center;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
/* Button Styles */
.stButton>button {
background: linear-gradient(135deg, #3b82f6 0%, #4f46e5 100%);
color: white;
width: 100%;
font-weight: 500;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.18);
padding: 0.6rem 1.2rem;
transition: all 0.3s ease;
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
box-shadow: 0 4px 6px rgba(31, 38, 135, 0.15);
}
.stButton>button:hover {
background: linear-gradient(135deg, #2563eb 0%, #4338ca 100%);
box-shadow: 0 8px 15px rgba(31, 38, 135, 0.2);
transform: translateY(-2px);
}
/* Glassomorphic Results Display Styles */
.results-container {
background: linear-gradient(120deg, rgba(255, 255, 255, 0.8) 0%, rgba(240, 249, 255, 0.7) 100%);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 12px;
padding: 1.75rem;
margin-top: 1.25rem;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.result-item {
padding: 1.25rem;
border-bottom: 1px solid rgba(229, 231, 235, 0.5);
margin-bottom: 1.25rem;
background: linear-gradient(120deg, rgba(255, 255, 255, 0.7) 0%, rgba(248, 250, 252, 0.6) 100%);
border-radius: 8px;
transition: all 0.2s ease;
}
.result-item:hover {
background-color: rgba(255, 255, 255, 0.8);
box-shadow: 0 4px 6px rgba(31, 38, 135, 0.1);
}
.result-title {
font-size: 1.15rem;
font-weight: 600;
color: #1e3a8a;
margin-bottom: 0.6rem;
}
.result-snippet {
color: #4b5563;
font-size: 0.95rem;
line-height: 1.6;
}
.result-url {
color: #059669;
font-size: 0.85rem;
margin-top: 0.6rem;
word-break: break-all;
}
/* Form Styles */
.stTextInput>div>div>input {
border-radius: 8px;
border: 1px solid rgba(209, 213, 219, 0.5);
background-color: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
}
.stTextInput>div>div>input:focus {
border-color: rgba(59, 130, 246, 0.7);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
background-color: rgba(255, 255, 255, 0.9);
}
/* Dashboard Home Styles */
.intro-container {
background: linear-gradient(135deg, rgba(239, 246, 255, 0.8) 0%, rgba(224, 242, 254, 0.7) 100%);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
padding: 1.75rem;
border-radius: 12px;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
margin-bottom: 1.5rem;
border-left: 4px solid rgba(59, 130, 246, 0.7);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.intro-text {
color: #374151;
line-height: 1.7;
font-size: 1.05rem;
margin: 0;
}
.intro-highlight {
color: #1e3a8a;
font-weight: 600;
}
/* Chart Container Styles */
.chart-container {
background-color: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 12px;
padding: 1.5rem;
margin: 1.25rem 0;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.chart-title {
font-size: 1.1rem;
font-weight: 600;
color: #1e3a8a;
margin-bottom: 1rem;
text-align: center;
}
/* Tab Styles */
.stTabs [data-baseweb="tab-list"] {
gap: 12px;
background: linear-gradient(120deg, rgba(255, 255, 255, 0.8) 0%, rgba(240, 249, 255, 0.7) 100%);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
padding: 1rem;
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.18);
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
}
.stTabs [data-baseweb="tab"] {
background: linear-gradient(120deg, rgba(255, 255, 255, 0.7) 0%, rgba(240, 249, 255, 0.6) 100%);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
border-radius: 10px;
padding: 0.75rem 1.25rem;
border: 1px solid rgba(255, 255, 255, 0.18);
border-left: 3px solid;
border-image: linear-gradient(to bottom, rgba(59, 130, 246, 0.8), rgba(79, 70, 229, 0.8)) 1;
transition: all 0.3s ease;
font-weight: 500;
color: #1e3a8a;
}
.stTabs [data-baseweb="tab"]:hover {
transform: translateY(-2px);
box-shadow: 0 8px 15px rgba(31, 38, 135, 0.15);
background: linear-gradient(120deg, rgba(255, 255, 255, 0.8) 0%, rgba(240, 249, 255, 0.7) 100%);
}
.stTabs [aria-selected="true"] {
background: linear-gradient(135deg, #3b82f6 0%, #4f46e5 100%) !important;
color: white !important;
border-image: none !important;
border-left: 3px solid #3b82f6 !important;
box-shadow: 0 8px 15px rgba(59, 130, 246, 0.25) !important;
}
/* Additional Styles for Tabs Content */
.stTabs [data-baseweb="tab-panel"] {
background: linear-gradient(120deg, rgba(255, 255, 255, 0.8) 0%, rgba(240, 249, 255, 0.7) 100%);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 0 12px 12px 12px;
padding: 1.75rem;
border: 1px solid rgba(255, 255, 255, 0.18);
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
margin-top: -1px;
}
/* Responsive Adjustments */
@media (max-width: 768px) {
.tool-card, .workflow-card, .intro-container, .results-container {
padding: 1.25rem;
}
.main-header {
font-size: 1.8rem;
}
.category-header {
font-size: 1.2rem;
}
.tool-title, .workflow-title {
font-size: 1.15rem;
}
}

View File

@@ -0,0 +1,380 @@
import streamlit as st
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import sys
import os
from pathlib import Path
# Add parent directory to path to import modules
sys.path.append(str(Path(__file__).parent.parent.parent))
# Import research modules (placeholder imports for now)
try:
from ai_web_researcher import (
google_serp_search,
tavily_ai_search,
metaphor_basic_neural_web_search,
google_trends_researcher,
firecrawl_web_crawler
)
except ImportError:
# For development/testing without actual modules
pass
def load_css():
"""Load custom CSS"""
css_file = Path(__file__).parent / "style.css"
with open(css_file) as f:
css_content = f.read()
# Use session state to track if CSS has been loaded
if 'css_loaded' not in st.session_state:
st.session_state['css_loaded'] = False
# Always apply CSS on each page load to ensure styles persist during navigation
st.markdown(f"<style>{css_content}</style>", unsafe_allow_html=True)
st.session_state['css_loaded'] = True
def display_google_serp_results(results):
"""Display Google SERP search results"""
# Check if results are available
if not results:
st.warning("No search results available. Please try a different query or check your API configuration.")
return
st.markdown('<div class="results-container">', unsafe_allow_html=True)
# Display organic results
st.markdown('<div class="category-header">Search Results</div>', unsafe_allow_html=True)
# Display actual organic results
organic_results = results.get('organic', [])
if organic_results:
for result in organic_results:
st.markdown(f"""
<div class="result-item">
<div class="result-title">{result.get('title', 'No Title')}</div>
<div class="result-url">{result.get('link', '#')}</div>
<div class="result-snippet">{result.get('snippet', 'No description available.')}</div>
</div>
""", unsafe_allow_html=True)
else:
st.info("No organic search results found.")
# Display People Also Ask
paa_results = results.get('peopleAlsoAsk', [])
if paa_results:
st.markdown('<div class="category-header">People Also Ask</div>', unsafe_allow_html=True)
for question in paa_results:
st.markdown(f"""
<div class="result-item">
<div class="result-title">{question.get('question', 'No Question')}</div>
<div class="result-snippet">{question.get('snippet', 'No answer available.')}</div>
</div>
""", unsafe_allow_html=True)
# Display Related Searches if available
related_searches = results.get('relatedSearches', [])
if related_searches:
st.markdown('<div class="category-header">Related Searches</div>', unsafe_allow_html=True)
for search in related_searches:
st.markdown(f"""
<div class="result-item">
<div class="result-title">{search}</div>
</div>
""", unsafe_allow_html=True)
st.markdown('</div>', unsafe_allow_html=True)
def display_tavily_results(results):
"""Display Tavily AI search results"""
# Check if results are available
if not results:
st.warning("No Tavily search results available. Please try a different query or check your API configuration.")
return
st.markdown('<div class="results-container">', unsafe_allow_html=True)
# Display answer if available
answer = results.get('answer', '')
if answer:
st.markdown('<div class="category-header">Answer</div>', unsafe_allow_html=True)
st.markdown(f"""
<div class="result-item">
<div class="result-snippet">{answer}</div>
</div>
""", unsafe_allow_html=True)
# Display search results
search_results = results.get('results', [])
if search_results:
st.markdown('<div class="category-header">Search Results</div>', unsafe_allow_html=True)
for result in search_results:
st.markdown(f"""
<div class="result-item">
<div class="result-title">{result.get('title', 'No Title')}</div>
<div class="result-url">{result.get('url', '#')}</div>
<div class="result-snippet">{result.get('content', 'No content available.')}</div>
</div>
""", unsafe_allow_html=True)
else:
st.info("No search results found.")
# Display follow-up questions if available
follow_up_questions = results.get('follow_up_questions', [])
if follow_up_questions:
st.markdown('<div class="category-header">Follow-up Questions</div>', unsafe_allow_html=True)
for question in follow_up_questions:
st.markdown(f"""
<div class="result-item">
<div class="result-title">{question}</div>
</div>
""", unsafe_allow_html=True)
st.markdown('</div>', unsafe_allow_html=True)
def display_metaphor_results(results):
"""Display Metaphor Neural Search results"""
# Check if results are available
if not results:
st.warning("No Metaphor search results available. Please try a different query or check your API configuration.")
return
st.markdown('<div class="results-container">', unsafe_allow_html=True)
# Display search results
st.markdown('<div class="category-header">Similar Content</div>', unsafe_allow_html=True)
# Display actual results
documents = results.get('documents', [])
if documents:
for doc in documents:
title = doc.get('title', 'No Title')
url = doc.get('url', '#')
extract = doc.get('extract', 'No content available.')
st.markdown(f"""
<div class="result-item">
<div class="result-title">{title}</div>
<div class="result-url">{url}</div>
<div class="result-snippet">{extract}</div>
</div>
""", unsafe_allow_html=True)
else:
st.info("No similar content found.")
# Display summary if available
summary = results.get('summary', '')
if summary:
st.markdown('<div class="category-header">Content Summary</div>', unsafe_allow_html=True)
st.markdown(f"""
<div class="result-item">
<div class="result-snippet">{summary}</div>
</div>
""", unsafe_allow_html=True)
st.markdown('</div>', unsafe_allow_html=True)
def display_google_trends_results(results):
"""Display Google Trends results"""
# Check if results are available
if not results:
st.warning("No Google Trends results available. Please try a different query or check your API configuration.")
return
st.markdown('<div class="results-container">', unsafe_allow_html=True)
# Display interest over time chart if available
interest_over_time = results.get('interest_over_time')
if interest_over_time is not None and not interest_over_time.empty:
st.markdown('<div class="category-header">Interest Over Time</div>', unsafe_allow_html=True)
st.markdown('<div class="chart-container">', unsafe_allow_html=True)
st.markdown('<div class="chart-title">Search Interest Over Time</div>', unsafe_allow_html=True)
# Convert to DataFrame if it's not already
if not isinstance(interest_over_time, pd.DataFrame):
interest_over_time = pd.DataFrame(interest_over_time)
# Prepare data for visualization
if 'date' in interest_over_time.columns:
# Melt the DataFrame to get it in the right format for plotting
terms = [col for col in interest_over_time.columns if col != 'date']
df = interest_over_time.melt('date', value_vars=terms, var_name='Term', value_name='Interest')
# Create and display the chart
fig = px.line(df, x='date', y='Interest', color='Term', title='Search Interest Over Time')
st.plotly_chart(fig, use_container_width=True)
else:
st.error("Interest over time data is not in the expected format.")
st.markdown('</div>', unsafe_allow_html=True)
# Display related queries if available
related_queries = results.get('related_queries', {})
if related_queries:
st.markdown('<div class="category-header">Related Queries</div>', unsafe_allow_html=True)
# Display top related queries
for term, queries in related_queries.items():
if 'top' in queries:
st.markdown(f'<div class="subcategory-header">Top queries for "{term}"</div>', unsafe_allow_html=True)
for query in queries['top'].get('query', []):
st.markdown(f"""
<div class="result-item">
<div class="result-title">{query}</div>
</div>
""", unsafe_allow_html=True)
if 'rising' in queries:
st.markdown(f'<div class="subcategory-header">Rising queries for "{term}"</div>', unsafe_allow_html=True)
for query in queries['rising'].get('query', []):
st.markdown(f"""
<div class="result-item">
<div class="result-title">{query}</div>
</div>
""", unsafe_allow_html=True)
# Display related topics if available
related_topics = results.get('related_topics', {})
if related_topics:
st.markdown('<div class="category-header">Related Topics</div>', unsafe_allow_html=True)
# Display top related topics
for term, topics in related_topics.items():
if 'top' in topics:
st.markdown(f'<div class="subcategory-header">Top topics for "{term}"</div>', unsafe_allow_html=True)
for topic in topics['top'].get('topic', []):
st.markdown(f"""
<div class="result-item">
<div class="result-title">{topic}</div>
</div>
""", unsafe_allow_html=True)
st.markdown('</div>', unsafe_allow_html=True)
def display_crawler_results(results):
"""Display Web Crawler results"""
# Check if results are available
if not results:
st.warning("No web crawler results available. Please try a different URL or check your API configuration.")
return
st.markdown('<div class="results-container">', unsafe_allow_html=True)
# Display crawled pages
st.markdown('<div class="category-header">Crawled Pages</div>', unsafe_allow_html=True)
# Handle different result formats
if isinstance(results, dict):
# Single page result
page_data = results
st.markdown(f"""
<div class="result-item">
<div class="result-title">{page_data.get('title', 'No Title')}</div>
<div class="result-url">{page_data.get('url', '#')}</div>
<div class="result-snippet">
<b>Title:</b> {page_data.get('title', 'No Title')}<br>
<b>Description:</b> {page_data.get('description', 'No description available.')}<br>
<b>Word Count:</b> {page_data.get('word_count', 'Unknown')}
</div>
</div>
""", unsafe_allow_html=True)
# Display content sections if available
content = page_data.get('content', [])
if content:
st.markdown('<div class="category-header">Page Content</div>', unsafe_allow_html=True)
for section in content:
if isinstance(section, dict):
section_type = section.get('type', '')
section_content = section.get('content', '')
if section_type and section_content:
st.markdown(f"""
<div class="result-item">
<div class="result-title">{section_type}</div>
<div class="result-snippet">{section_content}</div>
</div>
""", unsafe_allow_html=True)
elif isinstance(results, list):
# Multiple pages result
for page_data in results:
if isinstance(page_data, dict):
st.markdown(f"""
<div class="result-item">
<div class="result-title">{page_data.get('title', 'No Title')}</div>
<div class="result-url">{page_data.get('url', '#')}</div>
<div class="result-snippet">
<b>Title:</b> {page_data.get('title', 'No Title')}<br>
<b>Description:</b> {page_data.get('description', 'No description available.')}<br>
<b>Word Count:</b> {page_data.get('word_count', 'Unknown')}
</div>
</div>
""", unsafe_allow_html=True)
# Display content structure
st.markdown('<div class="category-header">Content Structure</div>', unsafe_allow_html=True)
# Placeholder data for chart
labels = ['Blog Posts', 'Product Pages', 'Category Pages', 'About Pages', 'Contact Pages']
values = [38, 27, 18, 10, 7]
fig = go.Figure(data=[go.Pie(labels=labels, values=values, hole=.3)])
fig.update_layout(title_text='Content Type Distribution')
st.plotly_chart(fig, use_container_width=True)
st.markdown('</div>', unsafe_allow_html=True)
def display_analyzer_results(results):
"""Display Website Analyzer results"""
# This is a placeholder function that will be implemented when integrated with actual modules
st.markdown('<div class="results-container">', unsafe_allow_html=True)
# Display content quality metrics
st.markdown('<div class="category-header">Content Quality Metrics</div>', unsafe_allow_html=True)
# Placeholder data for chart
categories = ['Readability', 'Engagement', 'Relevance', 'Uniqueness', 'Comprehensiveness']
values = [4.2, 3.8, 4.5, 3.9, 4.1]
fig = go.Figure()
fig.add_trace(go.Scatterpolar(
r=values,
theta=categories,
fill='toself',
name='Content Quality'
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 5]
)),
showlegend=False
)
st.plotly_chart(fig, use_container_width=True)
# Display SEO recommendations
st.markdown('<div class="category-header">SEO Recommendations</div>', unsafe_allow_html=True)
# Placeholder data
recommendations = [
"Improve meta descriptions for better click-through rates",
"Add more internal links to related content",
"Optimize images with descriptive alt text",
"Improve page loading speed by optimizing images",
"Add structured data markup for better search visibility"
]
for recommendation in recommendations:
st.markdown(f"""
<div class="result-item">
<div class="result-title">{recommendation}</div>
</div>
""", unsafe_allow_html=True)
st.markdown('</div>', unsafe_allow_html=True)

View File

@@ -0,0 +1,99 @@
# Content Generation Dashboard
## Overview
The Content Generation Dashboard is a central hub for ALwrity's content creation tools, providing an intuitive interface for accessing various AI-powered content generation capabilities.
## Features
### 1. Modality-Based Organization
- **Text Generation**
- Blog Writing
- Story Creation
- Product Descriptions
- News Articles
- Long-form Content
- **Social Media**
- Instagram Posts
- LinkedIn Content
- YouTube Scripts
- **Image Generation**
- AI Image Creation
- Visual Content Tools
- **Audio/Video**
- Speech to Blog
- Audio Transcription
### 2. Smart Navigation
- Quick access to recently used tools
- Favorite tools management
- Hierarchical navigation structure
- Minimal-click access to tools
### 3. Error Handling
- Custom exception handling
- User-friendly error messages
- Automatic error recovery
- Detailed error logging
### 4. State Management
- Persistent tool states
- Usage analytics tracking
- Performance monitoring
- Session management
## Architecture
### Core Components
1. **Dashboard UI (`dashboard.py`)**
- Main interface rendering
- Tool card management
- Navigation controls
- User interaction handling
2. **State Manager (`state_manager.py`)**
- Tool state tracking
- Usage metrics collection
- State persistence
- Navigation history
3. **Error Handler (`error_handler.py`)**
- Custom exceptions
- Error logging
- Recovery mechanisms
- User feedback
## Implementation Status
### Completed Features
- ✅ Basic dashboard layout
- ✅ Tool card implementation
- ✅ Error handling system
- ✅ State management
- ✅ Navigation structure
### In Progress
- 🔄 Performance optimization
- 🔄 User analytics integration
- 🔄 Tool loading improvements
### Planned Features
- ⏳ Advanced error recovery
- ⏳ Tool usage suggestions
- ⏳ Accessibility improvements
- ⏳ Performance monitoring
## Usage
### For Users
1. Access the dashboard through ALwrity's main interface
2. Select desired content generation modality
3. Choose specific tool from available options
4. Follow tool-specific workflows
### For Developers
1. Error Handling:
```python
from content_generation.error_handler import DashboardError

View File

@@ -0,0 +1,629 @@
import streamlit as st
from typing import Dict, List
from functools import lru_cache
from datetime import datetime
from loguru import logger
# Import all necessary AI writer functions
from lib.ai_writers.ai_blog_writer.ai_blog_generator import ai_blog_writer_page
from lib.ai_writers.ai_essay_writer import ai_essay_generator
from lib.ai_writers.ai_news_article_writer import ai_news_generation
from lib.utils.alwrity_utils import ai_news_writer, ai_finance_ta_writer, ai_social_writer, essay_writer
from lib.ai_writers.ai_facebook_writer.facebook_ai_writer import facebook_main_menu
from lib.ai_writers.linkedin_writer.linkedin_ai_writer import linkedin_main_menu
from lib.ai_writers.twitter_writers import run_dashboard as twitter_writer
from lib.ai_writers.insta_ai_writer import insta_writer
from lib.ai_writers.youtube_writers.youtube_ai_writer import youtube_main_menu
from lib.ai_writers.ai_agents_crew_writer import ai_agents_writers
from lib.utils.alwrity_utils import ai_agents_team
# Import SEO tools from ai_seo_tools
from lib.ai_seo_tools.on_page_seo_analyzer import analyze_onpage_seo
from lib.ai_seo_tools.weburl_seo_checker import url_seo_checker
from lib.ai_seo_tools.content_title_generator import ai_title_generator, generate_blog_titles
from lib.ai_seo_tools.meta_desc_generator import metadesc_generator_main
from lib.ai_seo_tools.seo_structured_data import ai_structured_data
from lib.ai_seo_tools.image_alt_text_generator import alt_text_gen
from lib.ai_seo_tools.opengraph_generator import og_tag_generator
from lib.ai_seo_tools.google_pagespeed_insights import google_pagespeed_insights
from lib.ai_seo_tools.sitemap_analysis import main as sitemap_analyzer
from lib.ai_seo_tools.twitter_tags_generator import display_app as twitter_tags_app
from lib.ai_seo_tools.enterprise_seo_suite import render_enterprise_seo_suite
from lib.alwrity_ui.seo_tools_dashboard import ai_seo_tools
@lru_cache(maxsize=None)
def get_tool_implementations() -> Dict[str, callable]:
"""
Return a mapping of tool names to their implementation functions.
Uses caching to avoid repeated imports.
"""
tool_mapping = {
# Text Generation Tools
"AI Blog Writer": ai_blog_writer_page,
"AI Essay Writer": essay_writer,
"AI News Writer": ai_news_writer,
"AI Content Team": ai_agents_team,
# Business Content Tools
"Financial TA Writer": ai_finance_ta_writer,
"AI Social Media": ai_social_writer,
# Social Media Specific Tools
"Facebook Writer": facebook_main_menu,
"LinkedIn Writer": linkedin_main_menu,
"Twitter Writer": twitter_writer,
"Instagram Writer": insta_writer,
"YouTube Writer": youtube_main_menu,
# SEO & Optimization Tools
"SEO Dashboard": ai_seo_tools,
"On-Page SEO Analyzer": analyze_onpage_seo,
"URL SEO Checker": url_seo_checker,
"AI Title Generator": lambda: _render_seo_tool("AI Title Generator", generate_blog_titles),
"Meta Description Generator": metadesc_generator_main,
"Structured Data Generator": ai_structured_data,
"Alt Text Generator": alt_text_gen,
"OpenGraph Tags": og_tag_generator,
"Page Speed Insights": google_pagespeed_insights,
"Sitemap Analyzer": sitemap_analyzer,
"Twitter Cards Generator": twitter_tags_app,
"Enterprise SEO Suite": render_enterprise_seo_suite,
# Creative Content Tools - placeholder functions for now
"Story Generator": lambda: st.info("Story Generator coming soon!"),
"Poetry Writer": lambda: st.info("Poetry Writer coming soon!"),
"Script Writer": lambda: st.info("Script Writer coming soon!"),
"Email Templates": lambda: st.info("Email Templates coming soon!"),
# Marketing Content Tools - placeholder functions
"Ad Copy Generator": lambda: st.info("Ad Copy Generator coming soon!"),
"Product Descriptions": lambda: st.info("Product Descriptions coming soon!"),
"Press Releases": lambda: st.info("Press Releases coming soon!"),
"Landing Page Copy": lambda: st.info("Landing Page Copy coming soon!"),
# Educational Content Tools - placeholder functions
"Course Content": lambda: st.info("Course Content coming soon!"),
"Tutorial Writer": lambda: st.info("Tutorial Writer coming soon!"),
"Quiz Generator": lambda: st.info("Quiz Generator coming soon!"),
"Study Guides": lambda: st.info("Study Guides coming soon!")
}
# Handle import errors gracefully
failed_imports = []
working_tools = {}
for tool_name, tool_func in tool_mapping.items():
try:
# Test if the function is callable
if callable(tool_func):
working_tools[tool_name] = tool_func
else:
failed_imports.append(tool_name)
except Exception as e:
logger.warning(f"Failed to load tool {tool_name}: {e}")
failed_imports.append(tool_name)
if failed_imports:
logger.info(f"Some tools are not available: {failed_imports}")
return working_tools
def _render_seo_tool(tool_name: str, tool_function):
"""Render SEO tools with consistent styling and handle errors."""
st.markdown(f"## 🔍 {tool_name}")
st.markdown("---")
# Handle AI Title Generator specifically
if "Title Generator" in tool_name:
_render_title_generator_ui()
else:
# For other SEO tools, call them directly
try:
if callable(tool_function):
tool_function()
else:
st.warning(f"Tool '{tool_name}' is not properly configured.")
except Exception as e:
st.error(f"Error loading tool: {str(e)}")
logger.error(f"Error in SEO tool {tool_name}: {str(e)}")
def _render_title_generator_ui():
"""Render a custom UI for the AI Title Generator."""
st.markdown("### Generate SEO-Optimized Titles")
# Input form
with st.form("title_generator_form"):
col1, col2 = st.columns(2)
with col1:
keywords = st.text_input(
"Blog Keywords",
placeholder="Enter your main keywords (comma-separated)",
help="Primary keywords for your content"
)
title_type = st.selectbox(
"Content Type",
["How-to Guide", "Listicle", "News Article", "Product Review", "Tutorial", "Case Study", "Opinion", "Research"]
)
with col2:
content = st.text_area(
"Blog Content (Optional)",
placeholder="Paste your blog content here for more targeted titles...",
height=100,
help="Optional: Paste existing content for more relevant titles"
)
title_intent = st.selectbox(
"Search Intent",
["Informational", "Commercial", "Transactional", "Navigational"]
)
language = st.selectbox(
"Language",
["English", "Spanish", "French", "German", "Italian", "Portuguese", "Hindi"]
)
submitted = st.form_submit_button("🚀 Generate Titles", use_container_width=True)
if submitted:
if not keywords:
st.warning("Please enter at least some keywords to generate titles.")
return
with st.spinner("🎯 Generating SEO-optimized titles..."):
try:
# Import and call the title generation function
from lib.ai_seo_tools.content_title_generator import generate_blog_titles
result = generate_blog_titles(
input_blog_keywords=keywords,
input_blog_content=content if content else None,
input_title_type=title_type,
input_title_intent=title_intent,
input_language=language
)
if result:
st.success("✅ Titles generated successfully!")
st.markdown("### 🎯 Your SEO-Optimized Titles:")
# Display the result in a nice format
st.markdown(f"```\n{result}\n```")
# Add copy buttons or additional features
if st.button("📋 Copy All Titles"):
st.success("Titles copied to clipboard! (Feature coming soon)")
else:
st.error("Failed to generate titles. Please try again.")
except Exception as e:
st.error(f"Error generating titles: {str(e)}")
logger.error(f"Title generation error: {str(e)}")
def render_content_generation_dashboard():
"""Main function to render the content generation dashboard."""
# Initialize dashboard state
dashboard_state = DashboardState()
# Apply modern CSS
apply_modern_css()
# Main dashboard header
st.markdown("""
<div class="main-dashboard">
<div class="dashboard-title">🚀 Alwrity Content Hub</div>
<div class="dashboard-subtitle">
Complete AI-powered content creation and SEO optimization suite. From writing to ranking - everything you need in one place.
</div>
<div style="display: flex; justify-content: center; gap: 2rem; margin-top: 1rem; flex-wrap: wrap;">
<div style="text-align: center;">
<div style="font-size: 2rem;">✍️</div>
<div style="font-size: 0.9rem; opacity: 0.8;">AI Writing</div>
</div>
<div style="text-align: center;">
<div style="font-size: 2rem;">🔍</div>
<div style="font-size: 0.9rem; opacity: 0.8;">SEO Tools</div>
</div>
<div style="text-align: center;">
<div style="font-size: 2rem;">📱</div>
<div style="font-size: 0.9rem; opacity: 0.8;">Social Media</div>
</div>
<div style="text-align: center;">
<div style="font-size: 2rem;">📊</div>
<div style="font-size: 0.9rem; opacity: 0.8;">Analytics</div>
</div>
</div>
</div>
""", unsafe_allow_html=True)
# Quick access section
st.markdown("""
<div class="quick-access">
<div class="section-title">⚡ Quick Access</div>
</div>
""", unsafe_allow_html=True)
# Recent tools
if st.session_state.get('recent_tools'):
st.markdown("### 📝 Recently Used")
cols = st.columns(min(len(st.session_state.recent_tools), 5))
for idx, tool in enumerate(st.session_state.recent_tools[:5]):
with cols[idx]:
if st.button(f"🔄 {tool}", key=f"recent_{tool}_{idx}"):
handle_tool_selection(tool, dashboard_state)
# Popular tools
popular_tools = ToolAnalytics.get_popular_tools()
if popular_tools:
st.markdown("### 🔥 Popular Tools")
cols = st.columns(min(len(popular_tools), 5))
for idx, tool in enumerate(popular_tools[:5]):
with cols[idx]:
if st.button(f"{tool}", key=f"popular_{tool}_{idx}"):
handle_tool_selection(tool, dashboard_state)
# Content tools by category
content_tools = {
"Text Generation": {
"tools": [
{"name": "AI Blog Writer", "icon": "✍️", "desc": "Create SEO-optimized blog posts with AI assistance"},
{"name": "AI Essay Writer", "icon": "📝", "desc": "Generate academic essays and research papers"},
{"name": "AI News Writer", "icon": "📰", "desc": "Write breaking news articles and reports"},
{"name": "AI Content Team", "icon": "👥", "desc": "Collaborative AI writing team for complex projects"}
]
},
"SEO & Optimization": {
"tools": [
{"name": "SEO Dashboard", "icon": "🔍", "desc": "Comprehensive SEO tools and analytics dashboard"},
{"name": "On-Page SEO Analyzer", "icon": "📊", "desc": "Analyze and optimize individual page SEO elements"},
{"name": "AI Title Generator", "icon": "🏷️", "desc": "Generate SEO-optimized titles for better rankings"},
{"name": "Meta Description Generator", "icon": "📄", "desc": "Create compelling meta descriptions that drive clicks"},
{"name": "Structured Data Generator", "icon": "🏗️", "desc": "Generate schema markup for rich search results"},
{"name": "Page Speed Insights", "icon": "", "desc": "Analyze and improve website performance metrics"},
{"name": "Enterprise SEO Suite", "icon": "🏢", "desc": "Advanced SEO workflows for enterprise needs"}
]
},
"Business Content": {
"tools": [
{"name": "Financial TA Writer", "icon": "📊", "desc": "Generate technical analysis reports for stocks"},
{"name": "Email Templates", "icon": "📧", "desc": "Professional email templates for business"},
{"name": "Press Releases", "icon": "📢", "desc": "Company announcements and press releases"},
{"name": "Landing Page Copy", "icon": "🌐", "desc": "High-converting landing page content"}
]
},
"Social Media": {
"tools": [
{"name": "Facebook Writer", "icon": "📘", "desc": "Facebook posts, ads, and content strategies"},
{"name": "LinkedIn Writer", "icon": "💼", "desc": "Professional LinkedIn articles and posts"},
{"name": "Twitter Writer", "icon": "🐦", "desc": "Engaging tweets and Twitter threads"},
{"name": "Instagram Writer", "icon": "📷", "desc": "Instagram captions and story content"},
{"name": "YouTube Writer", "icon": "🎬", "desc": "YouTube descriptions and video scripts"},
{"name": "OpenGraph Tags", "icon": "🔗", "desc": "Optimize social media sharing with Open Graph tags"},
{"name": "Twitter Cards Generator", "icon": "🐦", "desc": "Create Twitter Card markup for rich previews"}
]
},
"Creative Content": {
"tools": [
{"name": "Story Generator", "icon": "📚", "desc": "Creative short stories and narratives"},
{"name": "Poetry Writer", "icon": "🎭", "desc": "Beautiful poems and verses"},
{"name": "Script Writer", "icon": "🎬", "desc": "Scripts for videos, plays, and presentations"},
{"name": "Song Lyrics", "icon": "🎵", "desc": "Original song lyrics and musical content"}
]
}
}
# Render categories
for category, category_data in content_tools.items():
st.markdown(f"""
<div class="category-section">
<div class="category-header">{category}</div>
<div class="category-grid">
""", unsafe_allow_html=True)
# Create columns for tools in this category
tools = category_data["tools"]
cols = st.columns(min(len(tools), 3))
for idx, tool in enumerate(tools):
col_idx = idx % 3
with cols[col_idx]:
# Create tool card with button
if st.button(
f"{tool['icon']} {tool['name']}\n{tool['desc']}",
key=f"tool_{tool['name']}_{category}",
help=tool['desc']
):
handle_tool_selection(tool['name'], dashboard_state)
st.markdown("</div></div>", unsafe_allow_html=True)
# Footer with statistics
st.markdown("---")
st.markdown("### 📈 Alwrity Analytics")
col1, col2, col3, col4 = st.columns(4)
total_tools = len(get_tool_implementations())
seo_tools_count = len([tool for category in content_tools.values() for tool in category["tools"] if "SEO" in category.get("name", "") or any(seo_keyword in tool["name"] for seo_keyword in ["SEO", "Meta", "Title", "Structured", "Speed", "OpenGraph"])])
with col1:
st.metric("🛠️ Total Tools", total_tools)
with col2:
st.metric("🔍 SEO Tools", 12) # Based on our SEO tool count
with col3:
st.metric("📝 Recent Tools", len(st.session_state.get('recent_tools', [])))
with col4:
st.metric("⭐ Favorites", len(st.session_state.get('favorite_tools', [])))
# Add capability showcase
st.markdown("""
<div style="background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); padding: 1.5rem; border-radius: 10px; margin-top: 1rem;">
<h4 style="color: #2c3e50; margin-bottom: 1rem;">✨ Why Choose Alwrity?</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1rem;">
<div>
<strong>🎯 All-in-One Solution</strong><br>
<small>Content creation, SEO optimization, and social media management in one platform</small>
</div>
<div>
<strong>🤖 AI-Powered Intelligence</strong><br>
<small>Advanced AI models for content generation and SEO analysis</small>
</div>
<div>
<strong>📊 Enterprise-Ready</strong><br>
<small>Scalable tools designed for teams and enterprise workflows</small>
</div>
<div>
<strong>🚀 Continuously Updated</strong><br>
<small>Regular updates with new tools and enhanced capabilities</small>
</div>
</div>
</div>
""", unsafe_allow_html=True)
class DashboardState:
"""Manage dashboard state and user preferences."""
def __init__(self):
self.initialize_session_state()
def initialize_session_state(self):
"""Initialize session state variables."""
if 'recent_tools' not in st.session_state:
st.session_state.recent_tools = []
if 'favorite_tools' not in st.session_state:
st.session_state.favorite_tools = []
if 'tool_usage_count' not in st.session_state:
st.session_state.tool_usage_count = {}
def add_recent_tool(self, tool_name: str):
"""Add a tool to recent tools list."""
if tool_name in st.session_state.recent_tools:
st.session_state.recent_tools.remove(tool_name)
st.session_state.recent_tools.insert(0, tool_name)
# Keep only last 5 recent tools
st.session_state.recent_tools = st.session_state.recent_tools[:5]
def toggle_favorite(self, tool_name: str):
"""Toggle tool favorite status."""
if tool_name in st.session_state.favorite_tools:
st.session_state.favorite_tools.remove(tool_name)
else:
st.session_state.favorite_tools.append(tool_name)
def increment_usage(self, tool_name: str):
"""Increment tool usage count."""
st.session_state.tool_usage_count[tool_name] = st.session_state.tool_usage_count.get(tool_name, 0) + 1
class ToolAnalytics:
"""Analytics for tool usage and recommendations."""
@staticmethod
def get_popular_tools(limit: int = 5) -> List[str]:
"""Get most popular tools based on usage."""
usage_count = st.session_state.get('tool_usage_count', {})
if not usage_count:
# Return default popular tools showcasing Alwrity's key capabilities
return ["AI Blog Writer", "SEO Dashboard", "AI Title Generator", "Meta Description Generator", "On-Page SEO Analyzer"]
sorted_tools = sorted(usage_count.items(), key=lambda x: x[1], reverse=True)
return [tool[0] for tool in sorted_tools[:limit]]
def apply_modern_css():
"""Apply modern CSS styling to the dashboard."""
st.markdown("""
<style>
/* Main dashboard styling */
.main-dashboard {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 2rem;
border-radius: 15px;
margin-bottom: 2rem;
color: white;
}
.dashboard-title {
font-size: 3rem;
font-weight: 700;
text-align: center;
margin-bottom: 1rem;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.dashboard-subtitle {
font-size: 1.2rem;
text-align: center;
opacity: 0.9;
margin-bottom: 2rem;
}
/* Tool cards */
.tool-card {
background: white;
border-radius: 12px;
padding: 1.5rem;
margin: 0.5rem;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
cursor: pointer;
border: 2px solid transparent;
height: 200px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.tool-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
border-color: #667eea;
}
.tool-icon {
font-size: 2.5rem;
text-align: center;
margin-bottom: 1rem;
}
.tool-title {
font-size: 1.1rem;
font-weight: 600;
color: #333;
text-align: center;
margin-bottom: 0.5rem;
}
.tool-description {
font-size: 0.9rem;
color: #666;
text-align: center;
line-height: 1.4;
}
/* Quick access section */
.quick-access {
background: #f8f9fa;
border-radius: 10px;
padding: 1.5rem;
margin-bottom: 2rem;
}
.section-title {
font-size: 1.5rem;
font-weight: 600;
color: #333;
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
/* Recent tools styling */
.recent-tool {
background: linear-gradient(135deg, #ff6b6b, #ee5a24);
color: white;
padding: 0.75rem 1rem;
border-radius: 8px;
margin: 0.25rem;
font-weight: 500;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.recent-tool:hover {
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(255, 107, 107, 0.4);
}
/* Category sections */
.category-section {
margin-bottom: 3rem;
}
.category-header {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
padding: 1rem 1.5rem;
border-radius: 10px 10px 0 0;
font-size: 1.3rem;
font-weight: 600;
}
.category-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1rem;
padding: 1.5rem;
background: #f8f9fa;
border-radius: 0 0 10px 10px;
}
/* Responsive design */
@media (max-width: 768px) {
.dashboard-title {
font-size: 2rem;
}
.category-grid {
grid-template-columns: 1fr;
}
.tool-card {
height: auto;
min-height: 150px;
}
}
/* Success and info messages */
.success-message {
background: linear-gradient(135deg, #56ab2f, #a8e6cf);
color: white;
padding: 1rem;
border-radius: 8px;
margin: 1rem 0;
}
.info-message {
background: linear-gradient(135deg, #74b9ff, #0984e3);
color: white;
padding: 1rem;
border-radius: 8px;
margin: 1rem 0;
}
</style>
""", unsafe_allow_html=True)
def handle_tool_selection(tool_name: str, dashboard_state: DashboardState):
"""Handle tool selection and navigation."""
try:
# Update usage statistics
dashboard_state.add_recent_tool(tool_name)
dashboard_state.increment_usage(tool_name)
# Get tool implementations
tools = get_tool_implementations()
if tool_name in tools:
st.markdown(f"<div class='success-message'>🚀 Launching {tool_name}...</div>", unsafe_allow_html=True)
# Show loading state
with st.spinner(f"Loading {tool_name}..."):
try:
# Execute the tool function
tools[tool_name]()
logger.info(f"Successfully launched tool: {tool_name}")
except Exception as e:
st.error(f"Error running {tool_name}: {str(e)}")
logger.error(f"Error running tool {tool_name}: {e}")
else:
st.warning(f"Tool '{tool_name}' is not available yet.")
except ImportError as e:
st.error(f"Unable to load {tool_name}. Some dependencies may be missing.")
logger.error(f"Import error for {tool_name}: {e}")
except Exception as e:
st.error(f"An unexpected error occurred: {str(e)}")
logger.error(f"Unexpected error in tool selection: {e}")
# Main entry point
if __name__ == "__main__":
render_content_generation_dashboard()

View File

@@ -0,0 +1,684 @@
"""
Streamlit UI for Content Performance Predictor
Interactive interface for predicting and optimizing content performance
"""
import streamlit as st
import asyncio
import json
import plotly.graph_objects as go
import plotly.express as px
from datetime import datetime, timedelta
import pandas as pd
from typing import Dict, List, Any, Optional
import logging
# Import the predictor
try:
from lib.content_performance_predictor.content_performance_predictor import (
ContentPerformancePredictor,
ContentType,
predict_content_performance
)
except ImportError:
st.error("Content Performance Predictor module not found. Please check the installation.")
logger = logging.getLogger(__name__)
class ContentPerformancePredictorUI:
"""Streamlit UI for Content Performance Predictor"""
def __init__(self):
self.predictor = None
self.initialize_predictor()
def initialize_predictor(self):
"""Initialize the predictor with error handling"""
try:
self.predictor = ContentPerformancePredictor()
except Exception as e:
st.error(f"Failed to initialize predictor: {str(e)}")
self.predictor = None
def render_main_interface(self):
"""Render the main Content Performance Predictor interface"""
st.title("🎯 Content Performance Predictor")
st.markdown("### Predict content success before you publish!")
# Create tabs for different features
tab1, tab2, tab3, tab4 = st.tabs([
"📊 Predict Performance",
"📈 Batch Analysis",
"🔧 Optimization Tools",
"📚 Performance History"
])
with tab1:
self.render_single_prediction_tab()
with tab2:
self.render_batch_analysis_tab()
with tab3:
self.render_optimization_tab()
with tab4:
self.render_history_tab()
def render_single_prediction_tab(self):
"""Render single content prediction interface"""
st.header("Single Content Analysis")
# Input section
col1, col2 = st.columns([2, 1])
with col1:
# Content input
content_input = st.text_area(
"Enter your content:",
height=200,
placeholder="Paste your content here...\n\nExample:\n🚀 Just discovered an amazing AI writing tool that's changing the game!\n\n#AIWriting #ContentCreation"
)
# Target keywords
keywords_input = st.text_input(
"Target Keywords (optional):",
placeholder="AI writing, content creation, SEO"
)
with col2:
# Content type selection
content_type = st.selectbox(
"Content Type:",
["twitter", "linkedin", "facebook", "instagram", "blog_post", "email", "youtube"],
help="Select the platform where you plan to publish"
)
# Analysis options
st.subheader("Analysis Options")
include_seo = st.checkbox("Include SEO Analysis", value=True)
include_trends = st.checkbox("Include Trend Analysis", value=True)
include_competitor = st.checkbox("Include Competitor Analysis", value=False)
# Advanced settings
with st.expander("Advanced Settings"):
target_audience = st.selectbox(
"Target Audience:",
["General", "Business", "Tech", "Marketing", "Education", "Entertainment"]
)
urgency_level = st.slider(
"Content Urgency:",
0.0, 1.0, 0.5,
help="How time-sensitive is this content?"
)
# Predict button
if st.button("🎯 Predict Performance", type="primary", use_container_width=True):
if not content_input.strip():
st.error("Please enter content to analyze")
return
# Process keywords
keywords = [k.strip() for k in keywords_input.split(",")] if keywords_input else None
# Show loading spinner
with st.spinner("Analyzing content performance..."):
# Run prediction
prediction_result = self.run_prediction(
content_input,
content_type,
keywords,
include_seo,
include_trends,
include_competitor
)
if prediction_result:
self.display_prediction_results(prediction_result)
else:
st.error("Failed to analyze content. Please try again.")
def run_prediction(
self,
content: str,
content_type: str,
keywords: Optional[List[str]],
include_seo: bool,
include_trends: bool,
include_competitor: bool
) -> Optional[Dict[str, Any]]:
"""Run the content performance prediction"""
try:
# Run async prediction
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
result = loop.run_until_complete(
predict_content_performance(
content=content,
content_type=content_type,
target_keywords=keywords
)
)
loop.close()
return result
except Exception as e:
logger.error(f"Error in prediction: {str(e)}")
st.error(f"Prediction failed: {str(e)}")
return None
def display_prediction_results(self, result: Dict[str, Any]):
"""Display the prediction results with visualizations"""
st.success("✅ Analysis Complete!")
# Overall score section
st.subheader("📊 Overall Performance Score")
col1, col2, col3 = st.columns(3)
with col1:
# Overall score gauge
score = result.get("overall_score", 0)
self.render_score_gauge(score, "Overall Score")
with col2:
# Success probability
prob = result.get("success_probability", 0) * 100
self.render_score_gauge(prob, "Success Probability")
with col3:
# Performance rating
rating = self.get_performance_rating(score)
st.metric(
"Performance Rating",
rating["label"],
help=rating["description"]
)
# Detailed scores breakdown
st.subheader("🔍 Detailed Score Breakdown")
scores = result.get("individual_scores", {})
if scores:
self.render_scores_breakdown(scores)
# Recommendations section
st.subheader("💡 Optimization Recommendations")
recommendations = result.get("recommendations", [])
if recommendations:
for i, rec in enumerate(recommendations, 1):
st.markdown(f"**{i}.** {rec}")
else:
st.info("No specific recommendations available")
# Predicted metrics
st.subheader("📊 Predicted Performance Metrics")
metrics = result.get("predicted_metrics", {})
if metrics:
self.render_predicted_metrics(metrics)
# Content analysis details
st.subheader("📝 Content Analysis Details")
analysis = result.get("content_analysis", {})
if analysis:
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Word Count", analysis.get("word_count", 0))
with col2:
st.metric("Character Count", analysis.get("character_count", 0))
with col3:
st.metric("Hashtags", analysis.get("hashtag_count", 0))
with col4:
st.metric("Readability", f"{analysis.get('readability_score', 0):.1f}")
# Export options
st.subheader("📤 Export Results")
col1, col2 = st.columns(2)
with col1:
if st.button("📄 Generate Report"):
report = self.generate_text_report(result)
st.text_area("Report:", value=report, height=200)
with col2:
if st.button("📊 Download JSON"):
json_str = json.dumps(result, indent=2)
st.download_button(
label="Download JSON",
data=json_str,
file_name=f"content_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json",
mime="application/json"
)
def render_score_gauge(self, score: float, title: str):
"""Render a gauge chart for scores"""
fig = go.Figure(go.Indicator(
mode = "gauge+number+delta",
value = score,
domain = {'x': [0, 1], 'y': [0, 1]},
title = {'text': title},
delta = {'reference': 50},
gauge = {
'axis': {'range': [None, 100]},
'bar': {'color': "darkblue"},
'steps': [
{'range': [0, 25], 'color': "lightgray"},
{'range': [25, 50], 'color': "yellow"},
{'range': [50, 75], 'color': "orange"},
{'range': [75, 100], 'color': "green"}],
'threshold': {
'line': {'color': "red", 'width': 4},
'thickness': 0.75,
'value': 90}}))
fig.update_layout(height=300)
st.plotly_chart(fig, use_container_width=True)
def render_scores_breakdown(self, scores: Dict[str, float]):
"""Render radar chart for score breakdown"""
categories = list(scores.keys())
values = list(scores.values())
# Close the radar chart
categories.append(categories[0])
values.append(values[0])
fig = go.Figure()
fig.add_trace(go.Scatterpolar(
r=values,
theta=categories,
fill='toself',
name='Performance Scores'
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 100]
)),
showlegend=True,
title="Performance Score Breakdown"
)
st.plotly_chart(fig, use_container_width=True)
# Display scores as metrics
cols = st.columns(len(scores))
for i, (category, score) in enumerate(scores.items()):
with cols[i]:
st.metric(category.title(), f"{score:.1f}")
def render_predicted_metrics(self, metrics: Dict[str, Any]):
"""Render predicted performance metrics"""
cols = st.columns(len(metrics))
for i, (metric, value) in enumerate(metrics.items()):
with cols[i]:
# Format metric name
display_name = metric.replace("predicted_", "").replace("_", " ").title()
st.metric(display_name, f"{value:,}")
def get_performance_rating(self, score: float) -> Dict[str, str]:
"""Get performance rating based on score"""
if score >= 80:
return {"label": "Excellent", "description": "High chance of success"}
elif score >= 60:
return {"label": "Good", "description": "Solid performance expected"}
elif score >= 40:
return {"label": "Average", "description": "Room for improvement"}
else:
return {"label": "Needs Work", "description": "Optimization recommended"}
def render_batch_analysis_tab(self):
"""Render batch analysis interface"""
st.header("Batch Content Analysis")
st.info("Analyze multiple pieces of content at once")
# File upload
uploaded_file = st.file_uploader(
"Upload CSV with content",
type=['csv'],
help="CSV should have columns: 'content', 'content_type', 'keywords' (optional)"
)
if uploaded_file is not None:
try:
df = pd.read_csv(uploaded_file)
# Validate required columns
required_cols = ['content', 'content_type']
missing_cols = [col for col in required_cols if col not in df.columns]
if missing_cols:
st.error(f"Missing required columns: {', '.join(missing_cols)}")
return
st.success(f"✅ Loaded {len(df)} content items")
# Preview data
with st.expander("Preview Data"):
st.dataframe(df.head())
# Analysis options
col1, col2 = st.columns(2)
with col1:
max_items = st.number_input(
"Max items to analyze:",
min_value=1,
max_value=100,
value=min(10, len(df))
)
with col2:
export_format = st.selectbox(
"Export format:",
["CSV", "JSON", "Excel"]
)
# Run batch analysis
if st.button("🚀 Run Batch Analysis", type="primary"):
with st.spinner(f"Analyzing {max_items} content items..."):
batch_df = df.head(max_items)
results = self.run_batch_analysis(batch_df)
if results:
self.display_batch_results(results)
else:
st.error("Batch analysis failed")
except Exception as e:
st.error(f"Error processing file: {str(e)}")
def run_batch_analysis(self, df: pd.DataFrame) -> List[Dict[str, Any]]:
"""Run batch analysis on multiple content items"""
results = []
progress = st.progress(0)
for i, row in df.iterrows():
try:
content = row['content']
content_type = row['content_type']
keywords = row.get('keywords', '').split(',') if row.get('keywords') else None
result = self.run_prediction(content, content_type, keywords, True, True, False)
if result:
result['original_content'] = content
result['content_type'] = content_type
results.append(result)
progress.progress((i + 1) / len(df))
except Exception as e:
st.warning(f"Error analyzing row {i}: {str(e)}")
continue
return results
def display_batch_results(self, results: List[Dict[str, Any]]):
"""Display batch analysis results"""
st.success(f"✅ Analyzed {len(results)} content items")
# Summary statistics
st.subheader("📊 Batch Summary")
scores = [r.get('overall_score', 0) for r in results]
avg_score = sum(scores) / len(scores) if scores else 0
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Average Score", f"{avg_score:.1f}")
with col2:
st.metric("Best Score", f"{max(scores):.1f}" if scores else "0")
with col3:
st.metric("Worst Score", f"{min(scores):.1f}" if scores else "0")
with col4:
good_content = len([s for s in scores if s >= 60])
st.metric("Good Content", f"{good_content}/{len(scores)}")
# Results table
st.subheader("📋 Detailed Results")
# Create summary DataFrame
summary_data = []
for i, result in enumerate(results):
summary_data.append({
"Content": result['original_content'][:50] + "..." if len(result['original_content']) > 50 else result['original_content'],
"Type": result['content_type'],
"Overall Score": result.get('overall_score', 0),
"Success Probability": result.get('success_probability', 0) * 100,
"Engagement": result.get('individual_scores', {}).get('engagement', 0),
"SEO": result.get('individual_scores', {}).get('seo', 0),
"Virality": result.get('individual_scores', {}).get('virality', 0)
})
summary_df = pd.DataFrame(summary_data)
st.dataframe(summary_df, use_container_width=True)
# Download results
if st.button("📥 Download Results"):
csv = summary_df.to_csv(index=False)
st.download_button(
label="Download CSV",
data=csv,
file_name=f"batch_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
mime="text/csv"
)
def render_optimization_tab(self):
"""Render content optimization tools"""
st.header("🔧 Content Optimization Tools")
# A/B Testing section
st.subheader("🧪 A/B Content Testing")
col1, col2 = st.columns(2)
with col1:
st.markdown("**Version A**")
content_a = st.text_area(
"Content A:",
height=150,
key="content_a",
placeholder="Enter first version of your content..."
)
with col2:
st.markdown("**Version B**")
content_b = st.text_area(
"Content B:",
height=150,
key="content_b",
placeholder="Enter second version of your content..."
)
# Common settings
content_type = st.selectbox(
"Content Type for both:",
["twitter", "linkedin", "facebook", "instagram", "blog_post", "email", "youtube"],
key="ab_content_type"
)
if st.button("⚡ Compare Versions", type="primary"):
if not content_a.strip() or not content_b.strip():
st.error("Please enter both versions of content")
return
with st.spinner("Comparing content versions..."):
result_a = self.run_prediction(content_a, content_type, None, True, True, False)
result_b = self.run_prediction(content_b, content_type, None, True, True, False)
if result_a and result_b:
self.display_ab_comparison(result_a, result_b)
# Optimization suggestions
st.subheader("💡 Optimization Suggestions")
optimization_content = st.text_area(
"Content to optimize:",
height=150,
placeholder="Enter content for optimization suggestions..."
)
if st.button("🚀 Get Suggestions") and optimization_content.strip():
with st.spinner("Generating optimization suggestions..."):
suggestions = self.generate_optimization_suggestions(optimization_content)
if suggestions:
st.success("✅ Optimization suggestions generated!")
for i, suggestion in enumerate(suggestions, 1):
st.markdown(f"**{i}.** {suggestion}")
def display_ab_comparison(self, result_a: Dict[str, Any], result_b: Dict[str, Any]):
"""Display A/B test comparison results"""
st.success("✅ A/B Comparison Complete!")
# Overall comparison
col1, col2, col3 = st.columns(3)
score_a = result_a.get('overall_score', 0)
score_b = result_b.get('overall_score', 0)
winner = "A" if score_a > score_b else "B" if score_b > score_a else "Tie"
with col1:
st.metric("Version A Score", f"{score_a:.1f}")
with col2:
st.metric("Version B Score", f"{score_b:.1f}")
with col3:
st.metric("Winner", winner, delta=f"{abs(score_a - score_b):.1f} point difference")
# Detailed comparison chart
scores_a = result_a.get('individual_scores', {})
scores_b = result_b.get('individual_scores', {})
categories = list(scores_a.keys())
values_a = list(scores_a.values())
values_b = list(scores_b.values())
# Create comparison bar chart
fig = go.Figure(data=[
go.Bar(name='Version A', x=categories, y=values_a),
go.Bar(name='Version B', x=categories, y=values_b)
])
fig.update_layout(
barmode='group',
title="Detailed Score Comparison",
yaxis_title="Score",
xaxis_title="Category"
)
st.plotly_chart(fig, use_container_width=True)
# Recommendations comparison
st.subheader("📋 Recommendations Comparison")
col1, col2 = st.columns(2)
with col1:
st.markdown("**Version A Recommendations:**")
recs_a = result_a.get('recommendations', [])
for rec in recs_a[:5]:
st.markdown(f"{rec}")
with col2:
st.markdown("**Version B Recommendations:**")
recs_b = result_b.get('recommendations', [])
for rec in recs_b[:5]:
st.markdown(f"{rec}")
def generate_optimization_suggestions(self, content: str) -> List[str]:
"""Generate optimization suggestions for content"""
suggestions = []
# Basic content analysis
word_count = len(content.split())
char_count = len(content)
hashtag_count = content.count('#')
# Length optimization
if word_count < 10:
suggestions.append("Consider adding more detail to your content for better engagement")
elif word_count > 50:
suggestions.append("Consider shortening your content for better social media performance")
# Hashtag optimization
if hashtag_count == 0:
suggestions.append("Add relevant hashtags to increase discoverability")
elif hashtag_count > 5:
suggestions.append("Reduce the number of hashtags for better readability")
# Engagement optimization
if '?' not in content:
suggestions.append("Consider adding a question to encourage engagement")
if '!' not in content and '.' in content:
suggestions.append("Add some excitement with exclamation marks")
# Call to action
cta_words = ['click', 'share', 'comment', 'like', 'follow', 'subscribe']
has_cta = any(word in content.lower() for word in cta_words)
if not has_cta:
suggestions.append("Include a clear call-to-action (like, share, comment)")
# Emoji usage
emoji_count = len([char for char in content if ord(char) > 127])
if emoji_count == 0:
suggestions.append("Consider adding relevant emojis to make content more engaging")
return suggestions[:5] # Limit to top 5 suggestions
def render_history_tab(self):
"""Render performance history interface"""
st.header("📚 Performance History")
st.info("Performance history tracking coming soon!")
st.markdown("This feature will allow you to:")
st.markdown("• Track your content performance over time")
st.markdown("• Compare predicted vs actual performance")
st.markdown("• Identify your best-performing content patterns")
st.markdown("• Generate performance reports")
def generate_text_report(self, result: Dict[str, Any]) -> str:
"""Generate a text report of the analysis"""
report = f"""
CONTENT PERFORMANCE ANALYSIS REPORT
Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
OVERALL PERFORMANCE
Overall Score: {result.get('overall_score', 0):.1f}/100
Success Probability: {result.get('success_probability', 0)*100:.1f}%
Performance Rating: {self.get_performance_rating(result.get('overall_score', 0))['label']}
DETAILED SCORES
"""
scores = result.get('individual_scores', {})
for category, score in scores.items():
report += f"{category.title()}: {score:.1f}/100\n"
report += "\nCONTENT ANALYSIS\n"
analysis = result.get('content_analysis', {})
for key, value in analysis.items():
report += f"{key.replace('_', ' ').title()}: {value}\n"
report += "\nRECOMMENDATIONS\n"
recommendations = result.get('recommendations', [])
for i, rec in enumerate(recommendations, 1):
report += f"{i}. {rec}\n"
return report
def render_content_performance_predictor():
"""Main function to render the Content Performance Predictor UI"""
ui = ContentPerformancePredictorUI()
ui.render_main_interface()
if __name__ == "__main__":
render_content_performance_predictor()

View File

@@ -1,5 +1,6 @@
import streamlit as st
from loguru import logger
from typing import List, Dict, Any, Callable
# Import existing tools
from lib.ai_seo_tools.seo_structured_data import ai_structured_data
@@ -23,13 +24,228 @@ from lib.ai_seo_tools.sitemap_analysis import main as sitemap_analyzer
from lib.ai_seo_tools.textstaty import analyze_text as readability_analyzer
from lib.ai_seo_tools.wordcloud import generate_wordcloud
# Import new enterprise tools
from ..ai_seo_tools.google_search_console_integration import render_gsc_integration
from ..ai_seo_tools.ai_content_strategy import render_ai_content_strategy
from ..ai_seo_tools.enterprise_seo_suite import render_enterprise_seo_suite
from lib.alwrity_ui.dashboard_styles import apply_dashboard_style, render_dashboard_header, render_category_header, render_card
# ============================================================================
# TOOL CONFIGURATION FUNCTIONS
# ============================================================================
def get_enterprise_tools_config() -> List[Dict[str, Any]]:
"""Get configuration for enterprise tools."""
return [
{
'name': '🎯 Enterprise SEO Suite',
'description': 'Unified command center for comprehensive SEO management with AI-powered workflows',
'function': render_enterprise_seo_suite,
'features': ['Complete SEO audit workflows', 'AI-powered recommendations', 'Strategic planning', 'Performance tracking']
},
{
'name': '📊 Google Search Console Intelligence',
'description': 'AI-powered insights from Google Search Console data with content recommendations',
'function': render_gsc_integration,
'features': ['GSC data analysis', 'Content opportunities', 'Performance insights', 'Strategic recommendations']
},
{
'name': '🧠 AI Content Strategy Generator',
'description': 'Generate comprehensive content strategies using AI market intelligence',
'function': render_ai_content_strategy,
'features': ['Content pillar development', 'Topic cluster strategy', 'Content calendar planning', 'Distribution strategy']
}
]
def get_analytics_tools_config() -> List[Dict[str, Any]]:
"""Get configuration for analytics tools."""
return [
{
'name': '📊 Google Search Console Intelligence',
'description': 'Deep analysis of GSC data with AI-powered content recommendations',
'function': render_gsc_integration,
'category': 'Search Analytics'
},
{
'name': '🔍 Enhanced Content Gap Analysis',
'description': 'Advanced competitor content analysis with AI insights',
'function': lambda: render_enhanced_content_gap_analysis(),
'category': 'Competitive Intelligence'
},
{
'name': '📈 SEO Performance Tracker',
'description': 'Track and analyze SEO performance with trend analysis',
'function': lambda: st.info("SEO Performance Tracker - Coming soon with advanced metrics"),
'category': 'Performance Analytics'
}
]
def get_technical_tools_config() -> List[Dict[str, Any]]:
"""Get configuration for technical SEO tools."""
return [
{
'name': '🔍 Technical SEO Crawler',
'description': 'Comprehensive site-wide technical SEO analysis',
'function': lambda: render_technical_seo_crawler(),
'priority': 'High'
},
{
'name': '📱 Mobile SEO Analyzer',
'description': 'Mobile-specific SEO analysis and optimization',
'function': lambda: st.info("Mobile SEO Analyzer - Advanced mobile optimization coming soon"),
'priority': 'Medium'
},
{
'name': '⚡ Core Web Vitals Optimizer',
'description': 'Analyze and optimize Core Web Vitals performance',
'function': lambda: st.info("Core Web Vitals Optimizer - Performance optimization coming soon"),
'priority': 'High'
},
{
'name': '🗺️ XML Sitemap Generator',
'description': 'Generate and optimize XML sitemaps',
'function': lambda: st.info("XML Sitemap Generator - Coming soon"),
'priority': 'Medium'
}
]
def get_content_tools_config() -> List[Dict[str, Any]]:
"""Get configuration for content and strategy tools."""
return [
{
'name': '🧠 AI Content Strategy Generator',
'description': 'Comprehensive content strategy with AI market intelligence',
'function': render_ai_content_strategy,
'type': 'Enterprise'
},
{
'name': '📅 Content Calendar Planner',
'description': 'AI-powered content calendar with SEO optimization',
'function': lambda: render_content_calendar(),
'type': 'Professional'
},
{
'name': '🎯 Topic Cluster Generator',
'description': 'Generate SEO topic clusters for content dominance',
'function': lambda: st.info("Topic Cluster Generator - Advanced clustering coming soon"),
'type': 'Professional'
},
{
'name': '📊 Content Performance Analyzer',
'description': 'Analyze content performance and optimization opportunities',
'function': lambda: st.info("Content Performance Analyzer - Coming soon"),
'type': 'Standard'
}
]
def get_basic_tools_config() -> List[Dict[str, Any]]:
"""Get configuration for basic SEO tools."""
return [
{
'name': '📝 Meta Description Generator',
'description': 'Generate SEO-optimized meta descriptions',
'function': lambda: metadesc_generator_main(),
'category': 'Metadata'
},
{
'name': '🎯 Content Title Generator',
'description': 'Create compelling, SEO-friendly titles',
'function': lambda: ai_title_generator(),
'category': 'Content'
},
{
'name': '🔗 OpenGraph Generator',
'description': 'Generate social media OpenGraph tags',
'function': lambda: og_tag_generator(),
'category': 'Social'
},
{
'name': '🖼️ Image Alt Text Generator',
'description': 'Generate SEO-friendly image alt text',
'function': lambda: alt_text_gen(),
'category': 'Images'
},
{
'name': '📋 Schema Markup Generator',
'description': 'Generate structured data markup',
'function': lambda: ai_structured_data(),
'category': 'Technical'
},
{
'name': '🔍 On-Page SEO Analyzer',
'description': 'Comprehensive on-page SEO analysis',
'function': lambda: analyze_onpage_seo(),
'category': 'Analysis'
},
{
'name': '🌐 URL SEO Checker',
'description': 'Quick SEO check for any URL',
'function': lambda: url_seo_checker(),
'category': 'Analysis'
}
]
def get_tool_functions_mapping() -> Dict[str, Callable]:
"""Get mapping of tool names to their functions for URL routing."""
return {
# Core content tools
"structured_data": ai_structured_data,
"blog_title": ai_title_generator,
"meta_description": metadesc_generator_main,
"alt_text": alt_text_gen,
"opengraph": og_tag_generator,
"image_optimizer": main_img_optimizer,
# Technical analysis tools
"technical_seo_crawler": render_technical_seo_crawler,
"pagespeed": google_pagespeed_insights,
"onpage_seo": analyze_onpage_seo,
"url_checker": url_seo_checker,
"sitemap_analysis": sitemap_analyzer,
# Social media tools
"twitter_tags": render_twitter_tags,
# Content analysis tools
"readability_analyzer": render_readability_analyzer,
"wordcloud_generator": render_wordcloud_generator,
# Advanced tools
"backlinking": backlinking_ui,
"content_gap_analysis": render_content_gap_analysis,
"enhanced_content_gap_analysis": render_enhanced_content_gap_analysis_ui,
"content_calendar": render_content_calendar,
# Tool combinations for workflow efficiency
"content_optimization": lambda: run_tool_combination([
ai_title_generator,
metadesc_generator_main,
ai_structured_data
], "Content Optimization Suite"),
"technical_audit": lambda: run_tool_combination([
google_pagespeed_insights,
analyze_onpage_seo,
url_seo_checker
], "Technical SEO Audit"),
"image_optimization": lambda: run_tool_combination([
alt_text_gen,
main_img_optimizer
], "Image Optimization Suite"),
"social_optimization": lambda: run_tool_combination([
og_tag_generator,
render_twitter_tags
], "Social Media Optimization")
}
# ============================================================================
# INDIVIDUAL TOOL RENDERING FUNCTIONS
# ============================================================================
def render_content_gap_analysis():
"""Render the content gap analysis workflow interface."""
from lib.ai_seo_tools.content_gap_analysis.ui import ContentGapAnalysisUI
# Initialize and run the Content Gap Analysis UI
ui = ContentGapAnalysisUI()
ui.run()
@@ -38,10 +254,9 @@ def render_enhanced_content_gap_analysis_ui():
render_enhanced_content_gap_analysis()
def render_content_calendar():
"""Render the content calendar dashboard."""
"""Render the content calendar dashboard with proper error handling."""
import logging
import sys
from datetime import datetime
# Configure logging
logging.basicConfig(
@@ -52,16 +267,16 @@ def render_content_calendar():
logging.FileHandler('content_calendar.log', mode='a')
]
)
logger = logging.getLogger('content_calendar')
calendar_logger = logging.getLogger('content_calendar')
try:
logger.info("Initializing Content Calendar Dashboard")
calendar_logger.info("Initializing Content Calendar Dashboard")
dashboard = ContentCalendarDashboard()
logger.info("Rendering Content Calendar Dashboard")
calendar_logger.info("Rendering Content Calendar Dashboard")
dashboard.render()
logger.info("Content Calendar Dashboard rendered successfully")
calendar_logger.info("Content Calendar Dashboard rendered successfully")
except Exception as e:
logger.error(f"Error rendering content calendar: {str(e)}", exc_info=True)
calendar_logger.error(f"Error rendering content calendar: {str(e)}", exc_info=True)
st.error(f"An error occurred while loading the content calendar: {str(e)}")
def render_twitter_tags():
@@ -77,37 +292,41 @@ def render_readability_analyzer():
if st.button("Analyze Readability"):
if text_input.strip():
from textstat import textstat
# Calculate various metrics
metrics = {
"Flesch Reading Ease": textstat.flesch_reading_ease(text_input),
"Flesch-Kincaid Grade Level": textstat.flesch_kincaid_grade(text_input),
"Gunning Fog Index": textstat.gunning_fog(text_input),
"SMOG Index": textstat.smog_index(text_input),
"Automated Readability Index": textstat.automated_readability_index(text_input),
"Coleman-Liau Index": textstat.coleman_liau_index(text_input),
"Linsear Write Formula": textstat.linsear_write_formula(text_input),
"Dale-Chall Readability Score": textstat.dale_chall_readability_score(text_input),
"Readability Consensus": textstat.readability_consensus(text_input)
}
# Display metrics
st.subheader("Text Analysis Results")
for metric, value in metrics.items():
st.metric(metric, f"{value:.2f}")
# Add recommendations
st.subheader("Key Takeaways:")
st.markdown("""
* **Don't Be Afraid to Simplify!** Often, simpler language makes content more impactful and easier to digest.
* **Aim for a Reading Level Appropriate for Your Audience:** Consider the education level, background, and familiarity of your readers.
* **Use Short Sentences:** This makes your content more scannable and easier to read.
* **Write for Everyone:** Accessibility should always be a priority. When in doubt, aim for clear, concise language!
""")
_display_readability_metrics(text_input)
_display_readability_recommendations()
else:
st.error("Please enter text to analyze.")
def _display_readability_metrics(text: str):
"""Display readability metrics for the given text."""
from textstat import textstat
metrics = {
"Flesch Reading Ease": textstat.flesch_reading_ease(text),
"Flesch-Kincaid Grade Level": textstat.flesch_kincaid_grade(text),
"Gunning Fog Index": textstat.gunning_fog(text),
"SMOG Index": textstat.smog_index(text),
"Automated Readability Index": textstat.automated_readability_index(text),
"Coleman-Liau Index": textstat.coleman_liau_index(text),
"Linsear Write Formula": textstat.linsear_write_formula(text),
"Dale-Chall Readability Score": textstat.dale_chall_readability_score(text),
"Readability Consensus": textstat.readability_consensus(text)
}
st.subheader("Text Analysis Results")
for metric, value in metrics.items():
st.metric(metric, f"{value:.2f}")
def _display_readability_recommendations():
"""Display readability recommendations."""
st.subheader("Key Takeaways:")
st.markdown("""
* **Don't Be Afraid to Simplify!** Often, simpler language makes content more impactful and easier to digest.
* **Aim for a Reading Level Appropriate for Your Audience:** Consider the education level, background, and familiarity of your readers.
* **Use Short Sentences:** This makes your content more scannable and easier to read.
* **Write for Everyone:** Accessibility should always be a priority. When in doubt, aim for clear, concise language!
""")
def render_wordcloud_generator():
"""Render the word cloud generator."""
st.title("☁️ Word Cloud Generator")
@@ -117,253 +336,291 @@ def render_wordcloud_generator():
if st.button("Generate Word Cloud"):
if text_input.strip():
from wordcloud import WordCloud
import matplotlib.pyplot as plt
# Create and generate a word cloud image
wordcloud = WordCloud(width=800, height=400, background_color='white').generate(text_input)
# Display the word cloud
st.subheader("Word Cloud Visualization")
fig, ax = plt.subplots(figsize=(10, 5))
ax.imshow(wordcloud, interpolation='bilinear')
ax.axis('off')
st.pyplot(fig)
# Add some statistics
st.subheader("Text Statistics")
words = text_input.split()
unique_words = set(words)
st.metric("Total Words", len(words))
st.metric("Unique Words", len(unique_words))
_generate_and_display_wordcloud(text_input)
_display_text_statistics(text_input)
else:
st.error("Please enter text to generate a word cloud.")
def render_seo_tools_dashboard():
"""Render a modern dashboard for SEO tools with premium glassmorphic design."""
def _generate_and_display_wordcloud(text: str):
"""Generate and display word cloud for the given text."""
from wordcloud import WordCloud
import matplotlib.pyplot as plt
# Apply common dashboard styling
apply_dashboard_style()
# Create and generate a word cloud image
wordcloud = WordCloud(width=800, height=400, background_color='white').generate(text)
# Display the word cloud
st.subheader("Word Cloud Visualization")
fig, ax = plt.subplots(figsize=(10, 5))
ax.imshow(wordcloud, interpolation='bilinear')
ax.axis('off')
st.pyplot(fig)
# Enhanced dashboard header with modern design
render_dashboard_header(
"🚀 SEO AI Power Suite",
"Dominate search rankings with our comprehensive AI-powered SEO toolkit. From keyword research to content optimization, master every aspect of search engine optimization."
)
def _display_text_statistics(text: str):
"""Display basic text statistics."""
st.subheader("Text Statistics")
words = text.split()
unique_words = set(words)
st.metric("Total Words", len(words))
st.metric("Unique Words", len(unique_words))
# Define SEO tools organized by real use cases and existing functionality
seo_tools = {
"Content Creation & Optimization": {
"Content Title Generator": {
"icon": "📝",
"description": "Create attention-grabbing, SEO-optimized titles that resonate with your audience",
"category": "Content",
"path": "blog_title",
"features": ["Keyword Optimization", "Title Variations", "CTR Enhancement", "SEO Best Practices"]
},
"Meta Description Generator": {
"icon": "🏷️",
"description": "Generate compelling meta descriptions that boost click-through rates from search results",
"category": "Meta Tags",
"path": "meta_description",
"features": ["SERP Optimization", "Character Limits", "Keyword Integration", "CTR Improvement"]
},
"Structured Data Generator": {
"icon": "🏗️",
"description": "Create schema markup to enhance search result appearance with rich snippets",
"category": "Technical",
"path": "structured_data",
"features": ["Rich Snippets", "Schema Markup", "Search Enhancement", "SERP Features"]
}
},
"Image & Media Optimization": {
"Image Alt Text Generator": {
"icon": "🖼️",
"description": "Generate SEO-friendly alt text for images to improve accessibility and search visibility",
"category": "Images",
"path": "alt_text",
"features": ["Accessibility", "Image SEO", "Screen Reader Support", "Search Discovery"]
},
"Image Optimizer": {
"icon": "🎯",
"description": "Optimize images for web performance and faster loading times",
"category": "Performance",
"path": "image_optimizer",
"features": ["File Compression", "Format Optimization", "Performance Boost", "Web Standards"]
}
},
"Social Media Optimization": {
"OpenGraph Generator": {
"icon": "📱",
"description": "Create OpenGraph tags for beautiful social media sharing experiences",
"category": "Social",
"path": "opengraph",
"features": ["Social Sharing", "Visual Appeal", "Engagement Boost", "Platform Optimization"]
},
"Twitter Tags Generator": {
"icon": "🐦",
"description": "Generate trending and relevant Twitter hashtags for maximum engagement",
"category": "Social",
"path": "twitter_tags",
"features": ["Hashtag Research", "Trend Analysis", "Engagement Boost", "Content Discovery"]
}
},
"Technical SEO Analysis": {
"Technical SEO Crawler": {
"icon": "🔧",
"description": "Comprehensive site-wide technical SEO analysis with AI-powered recommendations. Identify and fix technical issues that impact your search rankings.",
"category": "Technical",
"path": "technical_seo_crawler",
"features": ["Site-wide Crawling", "Technical Issues Detection", "Performance Analysis", "AI Recommendations"]
},
"On-Page SEO Analyzer": {
"icon": "🔍",
"description": "Comprehensive analysis of on-page SEO factors with actionable recommendations",
"category": "Analysis",
"path": "onpage_seo",
"features": ["Content Analysis", "SEO Scoring", "Recommendations", "Best Practices"]
},
"Website Speed Insights": {
"icon": "",
"description": "Analyze website performance using Google PageSpeed Insights",
"category": "Performance",
"path": "pagespeed",
"features": ["Core Web Vitals", "Performance Metrics", "Optimization Tips", "Mobile Analysis"]
},
"URL SEO Checker": {
"icon": "🌐",
"description": "Analyze URL structure and SEO factors for better search rankings",
"category": "Technical",
"path": "url_checker",
"features": ["URL Analysis", "SEO Factors", "Technical Issues", "Optimization Tips"]
},
"Sitemap Analyzer": {
"icon": "🗺️",
"description": "Analyze website sitemaps to understand content structure and publishing trends",
"category": "Technical",
"path": "sitemap_analysis",
"features": ["Content Structure", "Publishing Trends", "URL Analysis", "Site Architecture"]
}
},
"Content Analysis & Research": {
"Content Gap Analysis": {
"icon": "📊",
"description": "Identify content opportunities and gaps in your SEO strategy",
"category": "Research",
"path": "content_gap_analysis",
"features": ["Competitor Analysis", "Keyword Gaps", "Content Opportunities", "Strategic Insights"]
},
"Enhanced Content Gap Analysis": {
"icon": "🎯",
"description": "Advanced content gap analysis with SERP intelligence, competitor crawling, and AI insights using advertools",
"category": "Research",
"path": "enhanced_content_gap_analysis",
"features": ["SERP Analysis", "Competitor Intelligence", "Keyword Expansion", "AI Strategic Insights"]
},
"Text Readability Analyzer": {
"icon": "📖",
"description": "Analyze text readability and get suggestions for content improvement",
"category": "Content",
"path": "readability_analyzer",
"features": ["Reading Level", "Clarity Score", "Improvement Tips", "Audience Targeting"]
},
"Word Cloud Generator": {
"icon": "☁️",
"description": "Visualize the most important words and terms in your content",
"category": "Visualization",
"path": "wordcloud_generator",
"features": ["Content Visualization", "Keyword Analysis", "Theme Identification", "Text Statistics"]
}
},
"Strategy & Planning": {
"Content Calendar": {
"icon": "📅",
"description": "Plan and organize your content strategy with AI-powered scheduling",
"category": "Planning",
"path": "content_calendar",
"features": ["Content Planning", "Publishing Schedule", "Strategy Management", "Team Collaboration"]
},
"Backlink Analysis": {
"icon": "🔗",
"description": "Analyze backlink opportunities and develop link building strategies",
"category": "Link Building",
"path": "backlinking",
"features": ["Link Analysis", "Opportunity Discovery", "Authority Building", "Outreach Planning"]
}
}
}
# Render categories and tools
for category, tools in seo_tools.items():
# Render category header
render_category_header(category)
# ============================================================================
# TAB RENDERING FUNCTIONS
# ============================================================================
def render_enterprise_tab():
"""Render the Enterprise Suite tab."""
st.header("🏢 Enterprise SEO Command Center")
st.markdown("**Unified SEO management for enterprise-level optimization**")
enterprise_tools = get_enterprise_tools_config()
# Display enterprise tools
for tool in enterprise_tools:
_render_enterprise_tool_card(tool)
# Render selected enterprise tool
_render_selected_enterprise_tool(enterprise_tools)
def _render_enterprise_tool_card(tool: Dict[str, Any]):
"""Render an individual enterprise tool card."""
with st.expander(f"{tool['name']} - {tool['description']}", expanded=False):
col1, col2 = st.columns([2, 1])
# Create responsive grid for tools in this category
cols = st.columns(3)
for idx, (tool_name, details) in enumerate(tools.items()):
with cols[idx % 3]:
# Use the common card renderer
if render_card(
icon=details['icon'],
title=tool_name,
description=details['description'],
category=details['category'],
key_suffix=f"seo_{tool_name.replace(' ', '_')}",
help_text=f"Open {tool_name} - {details['description'][:50]}..."
):
# Set query parameters to redirect to the specific tool
st.query_params["tool"] = details["path"]
st.rerun()
with col1:
st.markdown("**Key Features:**")
for feature in tool['features']:
st.write(f"{feature}")
with col2:
if st.button(f"Launch {tool['name'].split()[1]}", key=f"enterprise_{tool['name']}", use_container_width=True):
st.session_state.selected_enterprise_tool = tool['name']
tool['function']()
# Add SEO insights section
st.markdown("""
<div style="margin-top: 3rem;">
<div class="dashboard-header" style="margin-bottom: 2rem;">
<h1 style="font-size: 2.2em;">🎯 Why Choose Our SEO Tools?</h1>
<p>Real tools, real results. Each tool is designed to solve specific SEO challenges and drive measurable improvements.</p>
</div>
</div>
""", unsafe_allow_html=True)
def _render_selected_enterprise_tool(enterprise_tools: List[Dict[str, Any]]):
"""Render the selected enterprise tool if any."""
if 'selected_enterprise_tool' in st.session_state:
selected_tool = next((tool for tool in enterprise_tools if tool['name'] == st.session_state.selected_enterprise_tool), None)
if selected_tool:
st.markdown("---")
selected_tool['function']()
# SEO insights grid
insight_cols = st.columns(2)
insights = [
{
"title": "🤖 AI-Powered Analysis",
"description": "Advanced algorithms analyze your content and provide data-driven optimization recommendations for better rankings."
},
{
"title": "📈 Actionable Insights",
"description": "Get specific, implementable suggestions that directly impact your search engine visibility and traffic."
},
{
"title": "🎯 Comprehensive Coverage",
"description": "From technical SEO to content optimization, our tools cover every aspect of search engine optimization."
},
{
"title": "🚀 Proven Results",
"description": "Based on industry best practices and proven SEO strategies that deliver measurable improvements."
}
]
for idx, insight in enumerate(insights):
with insight_cols[idx % 2]:
st.markdown(f"""
<div class="premium-card" style="min-height: 160px; cursor: default;">
<div class="card-glow"></div>
<div class="card-content">
<div class="card-title" style="margin-bottom: 0.8rem;">{insight['title']}</div>
<div class="card-description" style="margin-bottom: 0;">{insight['description']}</div>
</div>
<div class="card-shine"></div>
</div>
""", unsafe_allow_html=True)
def render_analytics_tab():
"""Render the Analytics & Intelligence tab."""
st.header("📊 Analytics & Intelligence")
st.markdown("**Advanced analytics and competitive intelligence tools**")
# Close dashboard container
st.markdown('</div>', unsafe_allow_html=True)
analytics_tools = get_analytics_tools_config()
# Group tools by category
categories = _group_tools_by_category(analytics_tools)
for category, tools in categories.items():
st.subheader(f"📊 {category}")
for tool in tools:
_render_analytics_tool_row(tool)
def _group_tools_by_category(tools: List[Dict[str, Any]]) -> Dict[str, List[Dict[str, Any]]]:
"""Group tools by their category."""
categories = {}
for tool in tools:
category = tool['category']
if category not in categories:
categories[category] = []
categories[category].append(tool)
return categories
def _render_analytics_tool_row(tool: Dict[str, Any]):
"""Render an analytics tool row."""
col1, col2 = st.columns([3, 1])
with col1:
st.markdown(f"**{tool['name']}**")
st.write(tool['description'])
with col2:
if st.button("Launch", key=f"analytics_{tool['name']}", use_container_width=True):
tool['function']()
def render_technical_tab():
"""Render the Technical SEO tab."""
st.header("🔧 Technical SEO")
st.markdown("**Advanced technical SEO analysis and optimization tools**")
technical_tools = get_technical_tools_config()
# Display technical tools with priority indicators
for tool in technical_tools:
_render_technical_tool_row(tool)
def _render_technical_tool_row(tool: Dict[str, Any]):
"""Render a technical tool row with priority indicator."""
priority_color = "🔴" if tool['priority'] == 'High' else "🟡"
col1, col2, col3 = st.columns([2, 1, 1])
with col1:
st.markdown(f"**{tool['name']}** {priority_color}")
st.write(tool['description'])
with col2:
st.write(f"**Priority:** {tool['priority']}")
with col3:
if st.button("Launch", key=f"technical_{tool['name']}", use_container_width=True):
tool['function']()
def render_content_tab():
"""Render the Content & Strategy tab."""
st.header("📝 Content & Strategy")
st.markdown("**AI-powered content creation and strategy tools**")
content_tools = get_content_tools_config()
# Group by tool type
tool_types = _group_tools_by_type(content_tools)
for tool_type, tools in tool_types.items():
_render_content_tool_section(tool_type, tools)
def _group_tools_by_type(tools: List[Dict[str, Any]]) -> Dict[str, List[Dict[str, Any]]]:
"""Group tools by their type."""
tool_types = {}
for tool in tools:
tool_type = tool['type']
if tool_type not in tool_types:
tool_types[tool_type] = []
tool_types[tool_type].append(tool)
return tool_types
def _render_content_tool_section(tool_type: str, tools: List[Dict[str, Any]]):
"""Render a content tool section."""
type_color = {"Enterprise": "🏢", "Professional": "💼", "Standard": "📋"}
st.subheader(f"{type_color.get(tool_type, '📋')} {tool_type} Tools")
for tool in tools:
col1, col2 = st.columns([3, 1])
with col1:
st.markdown(f"**{tool['name']}**")
st.write(tool['description'])
with col2:
if st.button("Launch", key=f"content_{tool['name']}", use_container_width=True):
tool['function']()
def render_basic_tools_tab():
"""Render the Basic Tools tab."""
st.header("🎯 Basic SEO Tools")
st.markdown("**Essential SEO tools for quick optimization tasks**")
basic_tools = get_basic_tools_config()
# Group basic tools by category
basic_categories = _group_tools_by_category(basic_tools)
# Display in columns for better layout
_render_basic_tools_in_columns(basic_categories)
def _render_basic_tools_in_columns(basic_categories: Dict[str, List[Dict[str, Any]]]):
"""Render basic tools in two columns."""
col1, col2 = st.columns(2)
categories_list = list(basic_categories.items())
mid_point = len(categories_list) // 2
with col1:
for category, tools in categories_list[:mid_point]:
_render_basic_tool_category(category, tools)
with col2:
for category, tools in categories_list[mid_point:]:
_render_basic_tool_category(category, tools)
def _render_basic_tool_category(category: str, tools: List[Dict[str, Any]]):
"""Render a basic tool category."""
st.subheader(f"📂 {category}")
for tool in tools:
if st.button(f"{tool['name']}", key=f"basic_{tool['name']}", use_container_width=True):
tool['function']()
st.caption(tool['description'])
st.markdown("---")
def render_enterprise_features_footer():
"""Render the enterprise features footer."""
st.markdown("---")
st.markdown("### 🚀 Enterprise SEO Features")
col1, col2, col3 = st.columns(3)
with col1:
st.info("""
**🏢 Enterprise Suite**
- Unified SEO workflows
- AI-powered insights
- Strategic planning
- Performance tracking
""")
with col2:
st.info("""
**📊 Advanced Analytics**
- GSC integration
- Competitive intelligence
- Content gap analysis
- Performance insights
""")
with col3:
st.info("""
**🧠 AI Strategy**
- Content strategy generation
- Topic cluster planning
- Distribution optimization
- Market intelligence
""")
# ============================================================================
# MAIN DASHBOARD FUNCTIONS
# ============================================================================
def render_seo_tools_dashboard():
"""Render comprehensive SEO tools dashboard with enterprise features."""
st.title("🚀 Alwrity AI SEO Tools")
st.markdown("**Enterprise-level SEO tools powered by artificial intelligence**")
# Create tabs for different tool categories
tab1, tab2, tab3, tab4, tab5 = st.tabs([
"🏢 Enterprise Suite",
"📊 Analytics & Intelligence",
"🔧 Technical SEO",
"📝 Content & Strategy",
"🎯 Basic Tools"
])
with tab1:
render_enterprise_tab()
with tab2:
render_analytics_tab()
with tab3:
render_technical_tab()
with tab4:
render_content_tab()
with tab5:
render_basic_tools_tab()
# Add footer with enterprise features highlight
render_enterprise_features_footer()
def ai_seo_tools():
"""Render the SEO tools dashboard with premium glassmorphic design."""
"""Main entry point for SEO tools dashboard with premium glassmorphic design."""
logger.info("Starting SEO Tools Dashboard")
# Apply common dashboard styling
@@ -373,86 +630,52 @@ def ai_seo_tools():
selected_tool = st.query_params.get("tool")
if selected_tool:
# Map tool paths to their respective functions - ONLY existing, working tools
tool_functions = {
# Core content tools
"structured_data": ai_structured_data,
"blog_title": ai_title_generator,
"meta_description": metadesc_generator_main,
"alt_text": alt_text_gen,
"opengraph": og_tag_generator,
"image_optimizer": main_img_optimizer,
# Technical analysis tools
"technical_seo_crawler": render_technical_seo_crawler,
"pagespeed": google_pagespeed_insights,
"onpage_seo": analyze_onpage_seo,
"url_checker": url_seo_checker,
"sitemap_analysis": sitemap_analyzer,
# Social media tools
"twitter_tags": render_twitter_tags,
# Content analysis tools
"readability_analyzer": render_readability_analyzer,
"wordcloud_generator": render_wordcloud_generator,
# Advanced tools
"backlinking": backlinking_ui,
"content_gap_analysis": render_content_gap_analysis,
"enhanced_content_gap_analysis": render_enhanced_content_gap_analysis_ui,
"content_calendar": render_content_calendar,
# Tool combinations for workflow efficiency
"content_optimization": lambda: run_tool_combination([
ai_title_generator,
metadesc_generator_main,
ai_structured_data
], "Content Optimization Suite"),
"technical_audit": lambda: run_tool_combination([
google_pagespeed_insights,
analyze_onpage_seo,
url_seo_checker
], "Technical SEO Audit"),
"image_optimization": lambda: run_tool_combination([
alt_text_gen,
main_img_optimizer
], "Image Optimization Suite"),
"social_optimization": lambda: run_tool_combination([
og_tag_generator,
render_twitter_tags
], "Social Media Optimization")
}
if selected_tool in tool_functions:
# Clear any existing content
st.empty()
# Execute the selected tool's function
tool_functions[selected_tool]()
else:
st.error(f"Tool '{selected_tool}' is not available or under development.")
st.info("Please select a different tool from the dashboard.")
render_seo_tools_dashboard()
_handle_selected_tool(selected_tool)
else:
# Show the dashboard if no tool is selected
render_seo_tools_dashboard()
def run_tool_combination(tools, combination_name):
def _handle_selected_tool(selected_tool: str):
"""Handle rendering of a specific selected tool."""
tool_functions = get_tool_functions_mapping()
if selected_tool in tool_functions:
# Clear any existing content
st.empty()
# Execute the selected tool's function
tool_functions[selected_tool]()
else:
st.error(f"Tool '{selected_tool}' is not available or under development.")
st.info("Please select a different tool from the dashboard.")
render_seo_tools_dashboard()
def run_tool_combination(tools: List[Callable], combination_name: str):
"""Run a combination of tools and provide cross-tool analysis."""
st.markdown(f"# {combination_name}")
st.markdown("Comprehensive SEO analysis workflow")
# Create tabs for each tool in the combination
tab_names = _generate_tab_names(tools)
tabs = st.tabs(tab_names)
# Run each tool in its own tab
_execute_tools_in_tabs(tabs, tools)
# Add cross-tool analysis section
_render_analysis_summary()
def _generate_tab_names(tools: List[Callable]) -> List[str]:
"""Generate tab names for tool combination."""
tab_names = []
for i, tool in enumerate(tools):
if hasattr(tool, '__name__'):
tab_names.append(tool.__name__.replace('_', ' ').title())
else:
tab_names.append(f"Step {i+1}")
tabs = st.tabs(tab_names)
# Run each tool in its own tab
return tab_names
def _execute_tools_in_tabs(tabs: List, tools: List[Callable]):
"""Execute tools in their respective tabs."""
for tab, tool in zip(tabs, tools):
with tab:
try:
@@ -460,8 +683,9 @@ def run_tool_combination(tools, combination_name):
except Exception as e:
st.error(f"Error running tool: {str(e)}")
logger.error(f"Error in tool combination: {str(e)}")
# Add cross-tool analysis section
def _render_analysis_summary():
"""Render the analysis summary section."""
with st.expander("📊 Analysis Summary", expanded=True):
st.markdown("""
### Key Recommendations: