import streamlit as st
import importlib
import sys
import os
from pathlib import Path
import time
import json
from typing import Dict, List, Callable, Optional, Tuple
# Add the parent directory to the path to allow importing from lib
current_dir = Path(__file__).parent
root_dir = current_dir.parent.parent.parent
sys.path.append(str(root_dir))
# Dictionary to store the input section functions
input_sections = {}
# List of copywriter modules to import
copywriter_modules = [
"ai_emotional_copywriter",
"acca_copywriter",
"app_copywriter",
"star_copywriter",
"oath_copywriter",
"quest_copywriter",
"aidppc_copywriter",
"aida_copywriter",
"pas_copywriter",
"fab_copywriter",
"4c_copywriter",
"4r_copywriter"
]
# Define formula categories for better organization
formula_categories = {
"Emotional Appeal": ["ai_emotional_copywriter", "oath_copywriter"],
"Structured Framework": ["acca_copywriter", "app_copywriter", "star_copywriter", "quest_copywriter"],
"Sales Funnel": ["aidppc_copywriter", "aida_copywriter"],
"Problem-Solution": ["pas_copywriter"],
"Feature-Benefit": ["fab_copywriter"],
"Messaging Framework": ["4c_copywriter", "4r_copywriter"]
}
# Define formula metadata for better display and filtering
formula_metadata = {
"ai_emotional_copywriter": {
"name": "Emotional Copywriter",
"icon": "🎭",
"description": "Create copy that resonates with your audience's emotions and drives action.",
"color": "#FF6B6B",
"difficulty": "Intermediate",
"best_for": ["Landing Pages", "Email", "Social Media"],
"tags": ["emotional", "persuasive", "engagement"]
},
"acca_copywriter": {
"name": "ACCA Copywriter",
"icon": "🎯",
"description": "Use the ACCA (Attention, Context, Content, Action) framework to create compelling copy.",
"color": "#4ECDC4",
"difficulty": "Beginner",
"best_for": ["Ads", "Email", "Landing Pages"],
"tags": ["structured", "conversion", "clear"]
},
"app_copywriter": {
"name": "APP Copywriter",
"icon": "🤝",
"description": "Implement the APP (Agree, Promise, Preview) formula to create persuasive copy.",
"color": "#45B7D1",
"difficulty": "Beginner",
"best_for": ["Blog Posts", "Sales Pages", "Email"],
"tags": ["persuasive", "agreement", "preview"]
},
"star_copywriter": {
"name": "STAR Copywriter",
"icon": "⭐",
"description": "Use the STAR (Situation, Task, Action, Result) framework to tell compelling stories.",
"color": "#FFD166",
"difficulty": "Intermediate",
"best_for": ["Case Studies", "Testimonials", "About Pages"],
"tags": ["storytelling", "results", "case-study"]
},
"oath_copywriter": {
"name": "OATH Copywriter",
"icon": "📜",
"description": "Apply the OATH (Oblivious, Apathetic, Thinking, Hurting) framework to target specific audience mindsets.",
"color": "#06D6A0",
"difficulty": "Advanced",
"best_for": ["Ads", "Landing Pages", "Email Sequences"],
"tags": ["audience", "mindset", "targeting"]
},
"quest_copywriter": {
"name": "QUEST Copywriter",
"icon": "🔍",
"description": "Use the QUEST (Question, Unpack, Emphasize, Solution, Transform) framework for narrative-driven copy.",
"color": "#118AB2",
"difficulty": "Intermediate",
"best_for": ["Long-form Content", "Sales Pages", "Video Scripts"],
"tags": ["narrative", "transformation", "solution"]
},
"aidppc_copywriter": {
"name": "AIDPPC Copywriter",
"icon": "💰",
"description": "Implement the AIDPPC (Attention, Interest, Desire, Proof, Persuasion, Call to Action) framework for PPC ads.",
"color": "#073B4C",
"difficulty": "Advanced",
"best_for": ["PPC Ads", "Social Ads", "Display Ads"],
"tags": ["advertising", "ppc", "conversion"]
},
"aida_copywriter": {
"name": "AIDA Copywriter",
"icon": "🎬",
"description": "Use the AIDA (Attention, Interest, Desire, Action) framework to guide customers through the sales funnel.",
"color": "#EF476F",
"difficulty": "Beginner",
"best_for": ["Sales Pages", "Email", "Product Descriptions"],
"tags": ["sales", "funnel", "conversion"]
},
"pas_copywriter": {
"name": "PAS Copywriter",
"icon": "🔧",
"description": "Apply the PAS (Problem, Agitate, Solution) formula to address pain points and offer solutions.",
"color": "#7209B7",
"difficulty": "Beginner",
"best_for": ["Ads", "Email", "Landing Pages"],
"tags": ["problem-solving", "pain-points", "solutions"]
},
"fab_copywriter": {
"name": "FAB Copywriter",
"icon": "💎",
"description": "Use the FAB (Features, Advantages, Benefits) framework to highlight product value.",
"color": "#3A0CA3",
"difficulty": "Beginner",
"best_for": ["Product Descriptions", "Sales Pages", "Brochures"],
"tags": ["product", "features", "benefits"]
},
"4c_copywriter": {
"name": "4C Copywriter",
"icon": "📝",
"description": "Implement the 4C (Clear, Concise, Credible, Compelling) framework for effective messaging.",
"color": "#4361EE",
"difficulty": "Intermediate",
"best_for": ["Brand Messaging", "Mission Statements", "Value Propositions"],
"tags": ["clarity", "concise", "credibility"]
},
"4r_copywriter": {
"name": "4R Copywriter",
"icon": "🔄",
"description": "Use the 4R (Relevance, Resonance, Response, Results) framework to connect with your audience.",
"color": "#F72585",
"difficulty": "Intermediate",
"best_for": ["Content Marketing", "Email", "Social Media"],
"tags": ["relevance", "resonance", "results"]
}
}
def load_user_preferences() -> Dict:
"""Load user preferences from session state or initialize if not present."""
if "copywriter_preferences" not in st.session_state:
st.session_state.copywriter_preferences = {
"recent_formulas": [],
"favorite_formulas": [],
"comparison_formulas": [],
"view_mode": "grid" # or "list"
}
return st.session_state.copywriter_preferences
def save_user_preferences(preferences: Dict) -> None:
"""Save user preferences to session state."""
st.session_state.copywriter_preferences = preferences
def add_recent_formula(module_name: str) -> None:
"""Add a formula to the recent formulas list."""
preferences = load_user_preferences()
# Remove if already exists
if module_name in preferences["recent_formulas"]:
preferences["recent_formulas"].remove(module_name)
# Add to the beginning of the list
preferences["recent_formulas"].insert(0, module_name)
# Keep only the 5 most recent
preferences["recent_formulas"] = preferences["recent_formulas"][:5]
save_user_preferences(preferences)
def toggle_favorite_formula(module_name: str) -> bool:
"""Toggle a formula as favorite and return the new state."""
preferences = load_user_preferences()
if module_name in preferences["favorite_formulas"]:
preferences["favorite_formulas"].remove(module_name)
is_favorite = False
else:
preferences["favorite_formulas"].append(module_name)
is_favorite = True
save_user_preferences(preferences)
return is_favorite
def is_favorite_formula(module_name: str) -> bool:
"""Check if a formula is in the favorites list."""
preferences = load_user_preferences()
return module_name in preferences["favorite_formulas"]
def add_to_comparison(module_name: str) -> None:
"""Add a formula to the comparison list."""
preferences = load_user_preferences()
if module_name not in preferences["comparison_formulas"]:
preferences["comparison_formulas"].append(module_name)
# Keep only up to 3 formulas for comparison
preferences["comparison_formulas"] = preferences["comparison_formulas"][:3]
save_user_preferences(preferences)
def remove_from_comparison(module_name: str) -> None:
"""Remove a formula from the comparison list."""
preferences = load_user_preferences()
if module_name in preferences["comparison_formulas"]:
preferences["comparison_formulas"].remove(module_name)
save_user_preferences(preferences)
def clear_comparison() -> None:
"""Clear the comparison list."""
preferences = load_user_preferences()
preferences["comparison_formulas"] = []
save_user_preferences(preferences)
def lazy_load_module(module_name: str) -> Optional[Callable]:
"""Lazily load a module and return its input_section function."""
if module_name in input_sections:
return input_sections[module_name]
try:
module_path = f"lib.ai_writers.ai_copywriter.{module_name}"
module = importlib.import_module(module_path)
if hasattr(module, "input_section"):
input_sections[module_name] = module.input_section
return module.input_section
else:
st.warning(f"Module {module_name} does not have an input_section function.")
return None
except Exception as e:
st.error(f"Error loading module {module_name}: {str(e)}")
return None
def render_formula_card(module_name: str, index: int, view_mode: str = "grid") -> None:
"""Render a formula card with its details."""
metadata = formula_metadata.get(module_name, {})
if not metadata:
return
is_favorite = is_favorite_formula(module_name)
favorite_icon = "★" if is_favorite else "☆"
favorite_tooltip = "Remove from favorites" if is_favorite else "Add to favorites"
if view_mode == "grid":
with st.container():
st.markdown(f"""
{favorite_icon}
{metadata["icon"]} {metadata["name"]}
{metadata["description"]}
{metadata["difficulty"]}
""", unsafe_allow_html=True)
col1, col2, col3 = st.columns(3)
with col1:
if st.button(f"Use {metadata['name']}", key=f"use_btn_{index}", use_container_width=True):
add_recent_formula(module_name)
st.session_state.selected_formula = {
"module": module_name,
"name": metadata["name"],
"icon": metadata["icon"],
"function": lazy_load_module(module_name)
}
st.rerun()
with col2:
if st.button(f"{favorite_icon} Favorite", key=f"fav_btn_{index}", help=favorite_tooltip, use_container_width=True):
toggle_favorite_formula(module_name)
st.rerun()
with col3:
if module_name in load_user_preferences()["comparison_formulas"]:
if st.button("Remove from Compare", key=f"comp_btn_{index}", use_container_width=True):
remove_from_comparison(module_name)
st.rerun()
else:
if st.button("Add to Compare", key=f"comp_btn_{index}", use_container_width=True):
add_to_comparison(module_name)
st.rerun()
else: # list view
with st.container():
col1, col2 = st.columns([3, 1])
with col1:
st.markdown(f"""
{metadata["icon"]} {metadata["name"]} {favorite_icon}
{metadata["description"]}
{metadata["difficulty"]}
Best for: {", ".join(metadata["best_for"][:2])}
""", unsafe_allow_html=True)
with col2:
if st.button(f"Use", key=f"use_list_btn_{index}", use_container_width=True):
add_recent_formula(module_name)
st.session_state.selected_formula = {
"module": module_name,
"name": metadata["name"],
"icon": metadata["icon"],
"function": lazy_load_module(module_name)
}
st.rerun()
if st.button(f"{favorite_icon}", key=f"fav_list_btn_{index}", help=favorite_tooltip):
toggle_favorite_formula(module_name)
st.rerun()
if module_name in load_user_preferences()["comparison_formulas"]:
if st.button("- Compare", key=f"comp_list_btn_{index}"):
remove_from_comparison(module_name)
st.rerun()
else:
if st.button("+ Compare", key=f"comp_list_btn_{index}"):
add_to_comparison(module_name)
st.rerun()
def render_formula_comparison() -> None:
"""Render a comparison of selected formulas."""
preferences = load_user_preferences()
comparison_formulas = preferences["comparison_formulas"]
if not comparison_formulas:
st.info("Add formulas to compare them side by side.")
return
# Create a table for comparison
comparison_data = []
for module_name in comparison_formulas:
metadata = formula_metadata.get(module_name, {})
if metadata:
comparison_data.append({
"Name": f"{metadata['icon']} {metadata['name']}",
"Description": metadata["description"],
"Difficulty": metadata["difficulty"],
"Best For": ", ".join(metadata["best_for"][:3]),
"Tags": ", ".join(metadata["tags"])
})
# Display the comparison table
st.markdown("### Formula Comparison")
# Create columns for each formula
cols = st.columns(len(comparison_data))
# Display headers
for i, col in enumerate(cols):
with col:
st.markdown(f"#### {comparison_data[i]['Name']}")
# Display description
st.markdown("##### Description")
for i, col in enumerate(cols):
with col:
st.write(comparison_data[i]["Description"])
# Display difficulty
st.markdown("##### Difficulty")
for i, col in enumerate(cols):
with col:
st.write(comparison_data[i]["Difficulty"])
# Display best for
st.markdown("##### Best For")
for i, col in enumerate(cols):
with col:
st.write(comparison_data[i]["Best For"])
# Display tags
st.markdown("##### Tags")
for i, col in enumerate(cols):
with col:
st.write(comparison_data[i]["Tags"])
# Add buttons to use each formula
st.markdown("##### Actions")
for i, col in enumerate(cols):
with col:
module_name = comparison_formulas[i]
if st.button(f"Use {formula_metadata[module_name]['name']}", key=f"use_comp_btn_{i}"):
add_recent_formula(module_name)
st.session_state.selected_formula = {
"module": module_name,
"name": formula_metadata[module_name]["name"],
"icon": formula_metadata[module_name]["icon"],
"function": lazy_load_module(module_name)
}
st.rerun()
# Add a button to clear the comparison
if st.button("Clear Comparison", key="clear_comparison"):
clear_comparison()
st.rerun()
def filter_formulas(formulas: List[str], search_term: str, category: str, difficulty: str) -> List[str]:
"""Filter formulas based on search term, category, and difficulty."""
filtered_formulas = []
for module_name in formulas:
metadata = formula_metadata.get(module_name, {})
if not metadata:
continue
# Check if the formula matches the search term
name_match = search_term.lower() in metadata["name"].lower()
desc_match = search_term.lower() in metadata["description"].lower()
tags_match = any(search_term.lower() in tag.lower() for tag in metadata.get("tags", []))
# Check if the formula matches the category
category_match = True
if category != "All Categories":
category_match = module_name in formula_categories.get(category, [])
# Check if the formula matches the difficulty
difficulty_match = True
if difficulty != "All Difficulties":
difficulty_match = metadata.get("difficulty", "") == difficulty
# Add the formula if it matches all criteria
if (name_match or desc_match or tags_match) and category_match and difficulty_match:
filtered_formulas.append(module_name)
return filtered_formulas
def copywriter_dashboard():
"""
Main function to display the copywriting dashboard.
This function can be called from content_generator.py when the user selects "AI Copywriter".
"""
# Load user preferences
preferences = load_user_preferences()
# Initialize session state for selected formula if it doesn't exist
if "selected_formula" not in st.session_state:
st.session_state.selected_formula = None
# Initialize session state for search and filter options
if "search_term" not in st.session_state:
st.session_state.search_term = ""
if "selected_category" not in st.session_state:
st.session_state.selected_category = "All Categories"
if "selected_difficulty" not in st.session_state:
st.session_state.selected_difficulty = "All Difficulties"
if "view_mode" not in st.session_state:
st.session_state.view_mode = preferences["view_mode"]
# Create a container for the formula input section
formula_container = st.container()
# If a formula is selected, show its input section
if st.session_state.selected_formula is not None:
with formula_container:
# Display the selected formula's input section
st.markdown("---")
st.markdown(f"# {st.session_state.selected_formula['icon']} {st.session_state.selected_formula['name']}")
# Add a back button
if st.button("← Back to Dashboard", key="back_to_dashboard"):
# Clear the selected formula from session state
st.session_state.selected_formula = None
st.rerun()
# Call the input section function for the selected formula
if st.session_state.selected_formula["function"]:
st.session_state.selected_formula["function"]()
else:
st.error(f"The {st.session_state.selected_formula['name']} module is not available.")
else:
# Create a container for the dashboard
dashboard_container = st.container()
with dashboard_container:
# Display the dashboard
# Header
st.markdown("""
✍️ AI Copywriting Tools
Choose the perfect copywriting formula for your marketing needs
""", unsafe_allow_html=True)
# Create tabs for different sections
tab1, tab2, tab3, tab4 = st.tabs(["All Formulas", "Recent & Favorites", "Compare Formulas", "Help & Guide"])
with tab1:
# Search and filter options
col1, col2, col3, col4 = st.columns([3, 2, 2, 1])
with col1:
search_term = st.text_input("🔍 Search formulas", value=st.session_state.search_term)
if search_term != st.session_state.search_term:
st.session_state.search_term = search_term
with col2:
categories = ["All Categories"] + list(formula_categories.keys())
selected_category = st.selectbox("Category", categories, index=categories.index(st.session_state.selected_category))
if selected_category != st.session_state.selected_category:
st.session_state.selected_category = selected_category
with col3:
difficulties = ["All Difficulties", "Beginner", "Intermediate", "Advanced"]
selected_difficulty = st.selectbox("Difficulty", difficulties, index=difficulties.index(st.session_state.selected_difficulty))
if selected_difficulty != st.session_state.selected_difficulty:
st.session_state.selected_difficulty = selected_difficulty
with col4:
view_options = {"Grid": "grid", "List": "list"}
view_mode = st.selectbox("View", list(view_options.keys()), index=list(view_options.values()).index(st.session_state.view_mode))
st.session_state.view_mode = view_options[view_mode]
preferences["view_mode"] = st.session_state.view_mode
save_user_preferences(preferences)
# Filter formulas based on search and filter options
filtered_formulas = filter_formulas(
copywriter_modules,
st.session_state.search_term,
st.session_state.selected_category,
st.session_state.selected_difficulty
)
if not filtered_formulas:
st.info("No formulas match your search criteria. Try adjusting your filters.")
else:
# Display the formula cards
if st.session_state.view_mode == "grid":
# Create a 3-column layout for the formula cards
col1, col2, col3 = st.columns(3)
# Display the formula cards
for i, module_name in enumerate(filtered_formulas):
# Determine which column to use
col = col1 if i % 3 == 0 else col2 if i % 3 == 1 else col3
with col:
render_formula_card(module_name, i, st.session_state.view_mode)
else: # list view
for i, module_name in enumerate(filtered_formulas):
render_formula_card(module_name, i, st.session_state.view_mode)
with tab2:
# Recent formulas
st.subheader("Recently Used Formulas")
recent_formulas = preferences["recent_formulas"]
if not recent_formulas:
st.info("You haven't used any formulas yet. Start by selecting a formula from the 'All Formulas' tab.")
else:
# Create a 3-column layout for the recent formula cards
col1, col2, col3 = st.columns(3)
# Display the recent formula cards
for i, module_name in enumerate(recent_formulas):
# Determine which column to use
col = col1 if i % 3 == 0 else col2 if i % 3 == 1 else col3
with col:
render_formula_card(module_name, i + 100, "grid") # Use a different index to avoid key conflicts
# Favorite formulas
st.subheader("Favorite Formulas")
favorite_formulas = preferences["favorite_formulas"]
if not favorite_formulas:
st.info("You haven't added any formulas to your favorites yet. Click the star icon on a formula card to add it to your favorites.")
else:
# Create a 3-column layout for the favorite formula cards
col1, col2, col3 = st.columns(3)
# Display the favorite formula cards
for i, module_name in enumerate(favorite_formulas):
# Determine which column to use
col = col1 if i % 3 == 0 else col2 if i % 3 == 1 else col3
with col:
render_formula_card(module_name, i + 200, "grid") # Use a different index to avoid key conflicts
with tab3:
# Formula comparison
render_formula_comparison()
with tab4:
# Help and guide
st.subheader("Copywriting Formula Guide")
st.write("""
This dashboard provides access to a variety of copywriting formulas, each designed for specific marketing needs.
Here's how to make the most of these powerful tools:
""")
st.markdown("""
#### How to Use This Dashboard
1. **Browse Formulas**: Explore the available copywriting formulas in the "All Formulas" tab
2. **Search & Filter**: Use the search box and filters to find the perfect formula for your needs
3. **Compare Formulas**: Add up to 3 formulas to the comparison tab to see them side by side
4. **Save Favorites**: Click the star icon to save formulas you use frequently
5. **Access Recent**: Quickly access your recently used formulas in the "Recent & Favorites" tab
#### Choosing the Right Formula
Different formulas work best for different marketing goals:
- **Emotional Appeal**: Use when you want to connect with your audience on an emotional level
- **Structured Framework**: Great for organizing complex information in a compelling way
- **Sales Funnel**: Designed to guide prospects through the buying journey
- **Problem-Solution**: Effective for highlighting pain points and positioning your solution
- **Feature-Benefit**: Perfect for product descriptions and technical offerings
- **Messaging Framework**: Helps create clear, consistent messaging across channels
#### Formula Difficulty Levels
- **Beginner**: Easy to use with minimal copywriting experience
- **Intermediate**: Requires some understanding of copywriting principles
- **Advanced**: Most effective when used by experienced copywriters
""")
# Add a section about how to use the generated copy
st.subheader("Using Your Generated Copy")
st.write("""
After generating copy with your chosen formula:
1. **Review & Edit**: Always review and personalize the generated content
2. **Test Different Versions**: Try multiple formulas for the same product/service
3. **A/B Test**: Use different versions in your marketing to see which performs best
4. **Adapt for Channels**: Modify the copy as needed for different marketing channels
""")
# Add a feedback section
st.subheader("Feedback & Suggestions")
st.write("We're constantly improving our copywriting tools. If you have feedback or suggestions, please let us know!")
feedback = st.text_area("Your feedback", placeholder="Share your thoughts, suggestions, or report any issues...")
if st.button("Submit Feedback"):
if feedback:
st.success("Thank you for your feedback! We'll use it to improve our tools.")
# In a real implementation, you would save this feedback somewhere
else:
st.warning("Please enter your feedback before submitting.")
# For standalone execution
if __name__ == "__main__":
st.set_page_config(
page_title="AI Copywriting Tools",
page_icon="✍️",
layout="wide",
initial_sidebar_state="expanded"
)
copywriter_dashboard()