Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -7,11 +7,12 @@ import json
|
|
| 7 |
import markdown
|
| 8 |
import base64
|
| 9 |
from datetime import datetime
|
|
|
|
| 10 |
|
| 11 |
# Load environment variables from .env file if it exists
|
| 12 |
load_dotenv()
|
| 13 |
|
| 14 |
-
#
|
| 15 |
DEFAULT_TEMPLATES = {
|
| 16 |
"fermentation": """
|
| 17 |
Act as an elite-level SEO strategist and content creator with deep expertise in food blogs, particularly fermentation. I run a blog about fermentation, and my primary goal is to increase organic traffic, educate beginners, and establish thought leadership. My target audience is beginners curious about home fermentation and health-conscious individuals.
|
|
@@ -54,6 +55,12 @@ I require the following, formatted in clean markdown:
|
|
| 54 |
|
| 55 |
7. **E-E-A-T Enhancements:**
|
| 56 |
* 1-2 ways to show experience, trust, and authority in the content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
""",
|
| 58 |
"baking": """
|
| 59 |
Act as an elite-level SEO strategist and content creator with deep expertise in food blogs, particularly baking and pastry. I run a blog about baking, and my primary goal is to increase organic traffic, help home bakers improve their skills, and showcase unique recipes. My target audience is home bakers of all skill levels looking for reliable recipes and techniques.
|
|
@@ -100,6 +107,12 @@ I require the following, formatted in clean markdown:
|
|
| 100 |
* Recipe testing notes to include
|
| 101 |
* Personal experience elements to highlight
|
| 102 |
* Scientific explanation opportunities
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
""",
|
| 104 |
"plant_based": """
|
| 105 |
Act as an elite-level SEO strategist and content creator with deep expertise in plant-based and vegan food blogs. I run a blog about plant-based cooking, and my primary goal is to increase organic traffic, help people transition to more plant-based eating, and provide delicious alternatives to animal products. My target audience includes vegans, vegetarians, flexitarians, and the plant-curious.
|
|
@@ -147,30 +160,210 @@ I require the following, formatted in clean markdown:
|
|
| 147 |
* Nutritional expertise to highlight
|
| 148 |
* Personal experience with plant-based eating
|
| 149 |
* Scientific/research citations to include
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
"""
|
| 151 |
}
|
| 152 |
|
| 153 |
-
#
|
| 154 |
LANGUAGE_SETTINGS = {
|
| 155 |
"English": {
|
| 156 |
"search_engines": ["Google", "Bing", "DuckDuckGo"],
|
| 157 |
"localization_tips": "Focus on English-speaking markets (US, UK, Canada, Australia)",
|
| 158 |
-
"keyword_examples": ["recipe", "how to", "benefits of", "best", "easy", "homemade"]
|
|
|
|
|
|
|
| 159 |
},
|
| 160 |
"Spanish": {
|
| 161 |
"search_engines": ["Google", "Bing", "Yahoo"],
|
| 162 |
"localization_tips": "Target Spain and Latin American markets with regional variants",
|
| 163 |
-
"keyword_examples": ["receta", "cΓ³mo hacer", "beneficios de", "mejor", "fΓ‘cil", "casero"]
|
|
|
|
|
|
|
| 164 |
},
|
| 165 |
"French": {
|
| 166 |
"search_engines": ["Google", "Qwant", "Bing"],
|
| 167 |
"localization_tips": "Focus on France, Belgium, Canada (Quebec), Switzerland",
|
| 168 |
-
"keyword_examples": ["recette", "comment faire", "avantages de", "meilleur", "facile", "fait maison"]
|
|
|
|
|
|
|
| 169 |
},
|
| 170 |
"German": {
|
| 171 |
"search_engines": ["Google", "Bing", "Yahoo"],
|
| 172 |
"localization_tips": "Target Germany, Austria, Switzerland with appropriate dialect considerations",
|
| 173 |
-
"keyword_examples": ["rezept", "wie man", "vorteile von", "beste", "einfach", "hausgemacht"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
}
|
| 175 |
}
|
| 176 |
|
|
@@ -206,10 +399,10 @@ def load_templates():
|
|
| 206 |
# Initialize templates
|
| 207 |
TEMPLATES, LANGUAGES = load_templates()
|
| 208 |
|
| 209 |
-
#
|
| 210 |
-
def generate_html_export(content, title):
|
| 211 |
html_template = f"""<!DOCTYPE html>
|
| 212 |
-
<html lang="
|
| 213 |
<head>
|
| 214 |
<meta charset="UTF-8">
|
| 215 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
@@ -219,126 +412,258 @@ def generate_html_export(content, title):
|
|
| 219 |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 220 |
line-height: 1.6;
|
| 221 |
color: #333;
|
| 222 |
-
max-width:
|
| 223 |
margin: 0 auto;
|
| 224 |
padding: 20px;
|
| 225 |
-
background
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
}}
|
|
|
|
| 227 |
header {{
|
| 228 |
-
background
|
| 229 |
color: white;
|
| 230 |
-
padding:
|
| 231 |
text-align: center;
|
| 232 |
-
border-radius: 8px;
|
| 233 |
-
margin-bottom: 30px;
|
| 234 |
}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
h1 {{
|
| 236 |
margin: 0;
|
| 237 |
-
font-size: 2em;
|
|
|
|
| 238 |
}}
|
|
|
|
| 239 |
h2 {{
|
| 240 |
-
border-bottom:
|
| 241 |
padding-bottom: 10px;
|
| 242 |
-
color: #
|
|
|
|
| 243 |
}}
|
|
|
|
| 244 |
h3 {{
|
| 245 |
-
color: #
|
|
|
|
| 246 |
}}
|
|
|
|
| 247 |
.content {{
|
| 248 |
-
|
| 249 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 250 |
border-radius: 8px;
|
| 251 |
-
|
|
|
|
| 252 |
}}
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
|
|
|
| 258 |
}}
|
|
|
|
| 259 |
ul {{
|
| 260 |
margin-left: 20px;
|
| 261 |
}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 262 |
code {{
|
| 263 |
-
background-color: #
|
| 264 |
-
padding:
|
| 265 |
-
border-radius:
|
| 266 |
-
font-family: monospace;
|
|
|
|
| 267 |
}}
|
|
|
|
| 268 |
blockquote {{
|
| 269 |
-
border-left: 4px solid #
|
| 270 |
margin-left: 0;
|
| 271 |
-
padding-left:
|
| 272 |
-
color: #
|
|
|
|
|
|
|
|
|
|
|
|
|
| 273 |
}}
|
| 274 |
-
|
| 275 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 276 |
}}
|
| 277 |
</style>
|
| 278 |
</head>
|
| 279 |
<body>
|
| 280 |
-
<
|
| 281 |
-
<
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 286 |
</div>
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 290 |
</body>
|
| 291 |
</html>
|
| 292 |
"""
|
| 293 |
return html_template
|
| 294 |
|
| 295 |
# Export the SEO plan as HTML and create download link
|
| 296 |
-
def export_html(content, topic):
|
| 297 |
if not content or content.startswith("β οΈ") or content.startswith("π"):
|
| 298 |
-
return "Please generate an SEO plan first."
|
| 299 |
|
| 300 |
title = topic.strip().title()
|
| 301 |
-
html_content = generate_html_export(content, title)
|
| 302 |
|
| 303 |
# Create a safe filename
|
| 304 |
safe_filename = "".join([c if c.isalnum() or c in " -_" else "_" for c in title])
|
| 305 |
-
safe_filename = safe_filename.replace(" ", "_")
|
| 306 |
|
| 307 |
# Write to file
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 312 |
|
| 313 |
-
#
|
| 314 |
def save_custom_template(template_name, template_content):
|
| 315 |
if not template_name or not template_content:
|
| 316 |
return "β οΈ Please provide both a template name and content."
|
| 317 |
|
| 318 |
# Add to templates
|
| 319 |
-
TEMPLATES[template_name.lower()] = template_content
|
| 320 |
|
| 321 |
# Save to file
|
| 322 |
save_templates()
|
| 323 |
|
| 324 |
return f"β
Template '{template_name}' saved successfully!"
|
| 325 |
|
| 326 |
-
|
| 327 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 328 |
if not language_name:
|
| 329 |
return "β οΈ Please provide a language name."
|
| 330 |
|
| 331 |
-
# Process
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
| 336 |
|
| 337 |
# Add to languages
|
| 338 |
LANGUAGES[language_name] = {
|
| 339 |
-
"search_engines":
|
| 340 |
"localization_tips": localization_tips,
|
| 341 |
-
"keyword_examples":
|
|
|
|
|
|
|
| 342 |
}
|
| 343 |
|
| 344 |
# Save to file
|
|
@@ -346,14 +671,8 @@ def save_language_settings(language_name, search_engines, localization_tips, key
|
|
| 346 |
|
| 347 |
return f"β
Language settings for '{language_name}' saved successfully!"
|
| 348 |
|
| 349 |
-
#
|
| 350 |
-
def
|
| 351 |
-
if template_name in TEMPLATES:
|
| 352 |
-
return TEMPLATES[template_name]
|
| 353 |
-
return ""
|
| 354 |
-
|
| 355 |
-
# Function to build prompt with language optimization
|
| 356 |
-
def build_prompt(topic, template_key="fermentation", language="English"):
|
| 357 |
# Get base template
|
| 358 |
if template_key in TEMPLATES:
|
| 359 |
template = TEMPLATES[template_key]
|
|
@@ -365,71 +684,117 @@ def build_prompt(topic, template_key="fermentation", language="English"):
|
|
| 365 |
|
| 366 |
# Add language-specific instructions
|
| 367 |
language_instructions = f"""
|
| 368 |
-
|
| 369 |
|
| 370 |
1. **Target Search Engines:** {', '.join(lang_settings['search_engines'])}
|
| 371 |
-
2. **Localization
|
| 372 |
-
3. **Keyword Patterns:**
|
| 373 |
-
4. **
|
|
|
|
|
|
|
| 374 |
"""
|
| 375 |
|
| 376 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 377 |
if language != "English":
|
| 378 |
-
full_template = template + language_instructions
|
| 379 |
else:
|
| 380 |
-
full_template = template
|
| 381 |
|
| 382 |
# Format with the topic
|
| 383 |
return full_template.format(topic=topic)
|
| 384 |
|
| 385 |
-
#
|
| 386 |
-
def generate_seo_plan(topic, api_key, template_key="fermentation", language="English", temperature=0.7, max_tokens=
|
| 387 |
# Input validation
|
| 388 |
if not topic.strip():
|
| 389 |
-
return "β οΈ Please enter a
|
| 390 |
|
| 391 |
if not api_key.strip():
|
| 392 |
return "β οΈ Please provide your Gemini API key."
|
| 393 |
|
| 394 |
# Show that processing has started
|
| 395 |
-
yield "π Initializing
|
| 396 |
|
| 397 |
try:
|
| 398 |
# Configure Gemini with the provided API key
|
| 399 |
genai.configure(api_key=api_key)
|
| 400 |
|
| 401 |
-
# Initialize the model
|
| 402 |
model = genai.GenerativeModel(
|
| 403 |
"gemini-1.5-pro",
|
| 404 |
generation_config={
|
| 405 |
"temperature": float(temperature),
|
| 406 |
"max_output_tokens": max_tokens,
|
| 407 |
-
"top_p": 0.95
|
|
|
|
| 408 |
}
|
| 409 |
)
|
| 410 |
|
| 411 |
# Update status
|
| 412 |
-
yield f"π§ Building SEO prompt for
|
| 413 |
|
| 414 |
-
# Build the prompt
|
| 415 |
-
prompt = build_prompt(topic, template_key, language)
|
| 416 |
|
| 417 |
# Update status
|
| 418 |
-
yield "π Generating SEO plan with Gemini 1.5 Pro..."
|
| 419 |
|
| 420 |
-
# Generate response
|
| 421 |
-
response = model.generate_content(prompt)
|
| 422 |
|
| 423 |
-
#
|
| 424 |
-
|
| 425 |
-
|
|
|
|
|
|
|
|
|
|
| 426 |
|
| 427 |
-
#
|
| 428 |
-
yield
|
|
|
|
|
|
|
|
|
|
|
|
|
| 429 |
|
| 430 |
except Exception as e:
|
| 431 |
error_message = str(e)
|
| 432 |
-
print(f"Error generating SEO plan: {error_message}")
|
| 433 |
if "API key not valid" in error_message or "authentication" in error_message.lower():
|
| 434 |
yield "β οΈ API Key Error: The provided Gemini API key appears to be invalid. Please check your key and try again."
|
| 435 |
elif "quota" in error_message.lower():
|
|
@@ -437,9 +802,113 @@ def generate_seo_plan(topic, api_key, template_key="fermentation", language="Eng
|
|
| 437 |
else:
|
| 438 |
yield f"β οΈ Error: {error_message}"
|
| 439 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 440 |
# Function to clear outputs
|
| 441 |
def clear_outputs():
|
| 442 |
-
return "", gr.update(value="")
|
| 443 |
|
| 444 |
# Save API key to user's preferences
|
| 445 |
def save_api_key(api_key):
|
|
@@ -449,168 +918,398 @@ def save_api_key(api_key):
|
|
| 449 |
return "β
API key saved successfully!"
|
| 450 |
return "οΏ½οΏ½οΏ½οΈ Please enter an API key to save"
|
| 451 |
|
| 452 |
-
#
|
| 453 |
custom_theme = gr.themes.Soft(
|
| 454 |
-
primary_hue="
|
| 455 |
-
secondary_hue="
|
| 456 |
).set(
|
| 457 |
-
body_text_color="#
|
| 458 |
block_title_text_weight="600",
|
| 459 |
-
button_primary_background_fill="linear-gradient(90deg, #
|
| 460 |
-
button_primary_background_fill_hover="linear-gradient(90deg, #
|
| 461 |
button_primary_text_color="white",
|
| 462 |
block_label_text_size="0.9rem",
|
| 463 |
block_title_text_size="1.2rem"
|
| 464 |
)
|
| 465 |
|
| 466 |
-
# Main Gradio app
|
| 467 |
-
with gr.Blocks(title="
|
| 468 |
-
|
| 469 |
-
|
| 470 |
-
|
| 471 |
-
|
| 472 |
-
|
| 473 |
-
|
| 474 |
-
|
| 475 |
-
|
| 476 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 477 |
}
|
| 478 |
|
| 479 |
-
|
| 480 |
-
border
|
| 481 |
-
|
|
|
|
|
|
|
|
|
|
| 482 |
}
|
| 483 |
|
| 484 |
-
.
|
| 485 |
-
|
| 486 |
-
|
| 487 |
-
|
| 488 |
-
border:
|
| 489 |
-
|
| 490 |
-
|
| 491 |
-
|
|
|
|
| 492 |
}
|
| 493 |
|
| 494 |
-
|
| 495 |
-
|
|
|
|
|
|
|
|
|
|
| 496 |
}
|
| 497 |
""") as app:
|
|
|
|
| 498 |
# Header
|
| 499 |
gr.Markdown("""
|
| 500 |
-
#
|
|
|
|
| 501 |
|
| 502 |
-
Generate comprehensive SEO plans
|
| 503 |
""")
|
| 504 |
|
| 505 |
-
# API
|
| 506 |
-
with gr.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 507 |
with gr.Row():
|
| 508 |
-
|
| 509 |
-
|
| 510 |
-
|
| 511 |
-
|
| 512 |
-
|
| 513 |
-
|
| 514 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 515 |
|
| 516 |
with gr.Row():
|
| 517 |
-
|
| 518 |
-
|
| 519 |
-
|
| 520 |
-
|
| 521 |
-
|
| 522 |
-
|
| 523 |
-
|
| 524 |
-
|
| 525 |
-
|
| 526 |
-
|
| 527 |
-
|
| 528 |
-
|
| 529 |
-
|
| 530 |
-
|
| 531 |
-
|
| 532 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 533 |
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
| 538 |
-
|
| 539 |
-
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 545 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 546 |
with gr.Row():
|
| 547 |
-
|
| 548 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 549 |
|
| 550 |
-
|
| 551 |
-
|
| 552 |
-
|
| 553 |
-
|
| 554 |
-
|
| 555 |
-
|
| 556 |
-
|
| 557 |
-
|
| 558 |
-
|
| 559 |
-
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
|
| 568 |
-
|
| 569 |
-
|
| 570 |
-
|
| 571 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 572 |
generate_btn.click(
|
| 573 |
fn=generate_seo_plan,
|
| 574 |
-
inputs=[topic_input, api_key_input, temperature, max_tokens],
|
| 575 |
outputs=seo_output,
|
| 576 |
-
|
| 577 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 578 |
)
|
| 579 |
|
|
|
|
| 580 |
clear_btn.click(
|
| 581 |
fn=clear_outputs,
|
| 582 |
-
|
| 583 |
-
outputs=[topic_input, seo_output]
|
| 584 |
)
|
| 585 |
|
| 586 |
# Footer
|
| 587 |
gr.Markdown("""
|
| 588 |
---
|
| 589 |
-
|
| 590 |
-
|
| 591 |
-
|
| 592 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 593 |
|
| 594 |
-
###
|
| 595 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 596 |
""")
|
| 597 |
|
| 598 |
-
# Launch
|
| 599 |
if __name__ == "__main__":
|
| 600 |
-
|
| 601 |
-
print("
|
| 602 |
-
print("
|
| 603 |
-
print("
|
| 604 |
-
print("
|
| 605 |
-
print("
|
| 606 |
-
print("
|
| 607 |
-
|
| 608 |
-
|
|
|
|
| 609 |
app.launch(
|
| 610 |
share=True,
|
| 611 |
debug=True,
|
| 612 |
show_error=True,
|
| 613 |
-
server_name="0.0.0.0",
|
| 614 |
server_port=7860,
|
| 615 |
-
quiet=False
|
| 616 |
)
|
|
|
|
| 7 |
import markdown
|
| 8 |
import base64
|
| 9 |
from datetime import datetime
|
| 10 |
+
import re
|
| 11 |
|
| 12 |
# Load environment variables from .env file if it exists
|
| 13 |
load_dotenv()
|
| 14 |
|
| 15 |
+
# Enhanced templates for different food niches
|
| 16 |
DEFAULT_TEMPLATES = {
|
| 17 |
"fermentation": """
|
| 18 |
Act as an elite-level SEO strategist and content creator with deep expertise in food blogs, particularly fermentation. I run a blog about fermentation, and my primary goal is to increase organic traffic, educate beginners, and establish thought leadership. My target audience is beginners curious about home fermentation and health-conscious individuals.
|
|
|
|
| 55 |
|
| 56 |
7. **E-E-A-T Enhancements:**
|
| 57 |
* 1-2 ways to show experience, trust, and authority in the content
|
| 58 |
+
|
| 59 |
+
8. **SEO Performance Metrics:**
|
| 60 |
+
* Expected keyword difficulty (1-100)
|
| 61 |
+
* Estimated monthly search volume
|
| 62 |
+
* Content length recommendation
|
| 63 |
+
* Target reading time
|
| 64 |
""",
|
| 65 |
"baking": """
|
| 66 |
Act as an elite-level SEO strategist and content creator with deep expertise in food blogs, particularly baking and pastry. I run a blog about baking, and my primary goal is to increase organic traffic, help home bakers improve their skills, and showcase unique recipes. My target audience is home bakers of all skill levels looking for reliable recipes and techniques.
|
|
|
|
| 107 |
* Recipe testing notes to include
|
| 108 |
* Personal experience elements to highlight
|
| 109 |
* Scientific explanation opportunities
|
| 110 |
+
|
| 111 |
+
8. **SEO Performance Metrics:**
|
| 112 |
+
* Expected keyword difficulty (1-100)
|
| 113 |
+
* Estimated monthly search volume
|
| 114 |
+
* Content length recommendation
|
| 115 |
+
* Recipe card optimization tips
|
| 116 |
""",
|
| 117 |
"plant_based": """
|
| 118 |
Act as an elite-level SEO strategist and content creator with deep expertise in plant-based and vegan food blogs. I run a blog about plant-based cooking, and my primary goal is to increase organic traffic, help people transition to more plant-based eating, and provide delicious alternatives to animal products. My target audience includes vegans, vegetarians, flexitarians, and the plant-curious.
|
|
|
|
| 160 |
* Nutritional expertise to highlight
|
| 161 |
* Personal experience with plant-based eating
|
| 162 |
* Scientific/research citations to include
|
| 163 |
+
|
| 164 |
+
8. **SEO Performance Metrics:**
|
| 165 |
+
* Expected keyword difficulty (1-100)
|
| 166 |
+
* Estimated monthly search volume
|
| 167 |
+
* Nutritional content optimization
|
| 168 |
+
* Health claim compliance
|
| 169 |
+
""",
|
| 170 |
+
"keto": """
|
| 171 |
+
Act as an elite-level SEO strategist and content creator with deep expertise in keto and low-carb food blogs. I run a blog about ketogenic recipes and lifestyle, and my primary goal is to increase organic traffic, help people succeed on keto, and provide delicious low-carb alternatives. My target audience includes keto beginners, experienced keto dieters, and low-carb enthusiasts.
|
| 172 |
+
|
| 173 |
+
For the specific topic: '{topic}'
|
| 174 |
+
|
| 175 |
+
Analyze and generate a comprehensive SEO content plan designed to rank highly on Google and provide exceptional user value. Ensure all outputs adhere to E-E-A-T principles.
|
| 176 |
+
|
| 177 |
+
I require the following, formatted in clean markdown:
|
| 178 |
+
|
| 179 |
+
1. **Strategic Keyword Analysis:**
|
| 180 |
+
* **Primary Target Keyword:**
|
| 181 |
+
* **Secondary Keywords:** 2-3 closely related, high-intent keywords.
|
| 182 |
+
* **Long-Tail Keywords & User Questions:** 5-7 specific user-searched phrases.
|
| 183 |
+
* **Keto-Specific Keywords:** (net carbs, macros, ketosis, etc.)
|
| 184 |
+
* **Search Intent Analysis:** (Recipe-seeking, Macro information, Keto compliance, etc.)
|
| 185 |
+
|
| 186 |
+
2. **Competitive Landscape Overview (Top 3-5 Competitors):**
|
| 187 |
+
* For each:
|
| 188 |
+
* URL
|
| 189 |
+
* Macro accuracy and presentation
|
| 190 |
+
* Keto compliance verification
|
| 191 |
+
* User engagement factors
|
| 192 |
+
|
| 193 |
+
3. **Keto Value Proposition:**
|
| 194 |
+
* Net carb calculations
|
| 195 |
+
* Macro breakdown (fat/protein/carb ratios)
|
| 196 |
+
* Ketone production potential
|
| 197 |
+
* Satiety and weight loss benefits
|
| 198 |
+
|
| 199 |
+
4. **Optimized Blog Post Outline:**
|
| 200 |
+
* **H1 Title:**
|
| 201 |
+
* **Meta Description:** (under 160 characters)
|
| 202 |
+
* **Full H2/H3 outline** (including "Why This Recipe is Keto", "Ingredients & Net Carbs", "Step-by-Step Instructions", "Macro Information")
|
| 203 |
+
* **Recipe Schema Markup Elements:**
|
| 204 |
+
* **Required Macro Charts/Tables:**
|
| 205 |
+
|
| 206 |
+
5. **User-Focused FAQ Section:** 3β5 related to '{topic}' (focusing on keto compliance questions)
|
| 207 |
+
|
| 208 |
+
6. **Internal & External Linking Plan:**
|
| 209 |
+
* **Internal:** 2-3 relevant keto recipes with anchor suggestions
|
| 210 |
+
* **External:** 1-2 reputable sources for nutritional/keto information
|
| 211 |
+
|
| 212 |
+
7. **E-E-A-T Enhancements:**
|
| 213 |
+
* Nutritional expertise to highlight
|
| 214 |
+
* Personal keto experience elements
|
| 215 |
+
* Scientific/research citations for keto benefits
|
| 216 |
+
|
| 217 |
+
8. **SEO Performance Metrics:**
|
| 218 |
+
* Expected keyword difficulty (1-100)
|
| 219 |
+
* Estimated monthly search volume
|
| 220 |
+
* Macro accuracy requirements
|
| 221 |
+
* Keto community engagement potential
|
| 222 |
+
""",
|
| 223 |
+
"mediterranean": """
|
| 224 |
+
Act as an elite-level SEO strategist and content creator with deep expertise in Mediterranean cuisine and healthy food blogs. I run a blog about Mediterranean cooking and lifestyle, and my primary goal is to increase organic traffic, promote healthy eating habits, and share authentic Mediterranean recipes. My target audience includes health-conscious individuals, Mediterranean diet followers, and those interested in longevity and wellness.
|
| 225 |
+
|
| 226 |
+
For the specific topic: '{topic}'
|
| 227 |
+
|
| 228 |
+
Analyze and generate a comprehensive SEO content plan designed to rank highly on Google and provide exceptional user value. Ensure all outputs adhere to E-E-A-T principles.
|
| 229 |
+
|
| 230 |
+
I require the following, formatted in clean markdown:
|
| 231 |
+
|
| 232 |
+
1. **Strategic Keyword Analysis:**
|
| 233 |
+
* **Primary Target Keyword:**
|
| 234 |
+
* **Secondary Keywords:** 2-3 closely related, high-intent keywords.
|
| 235 |
+
* **Long-Tail Keywords & User Questions:** 5-7 specific user-searched phrases.
|
| 236 |
+
* **Health-Focused Keywords:** (heart-healthy, anti-inflammatory, longevity, etc.)
|
| 237 |
+
* **Search Intent Analysis:** (Recipe-seeking, Health information, Cultural learning, etc.)
|
| 238 |
+
|
| 239 |
+
2. **Competitive Landscape Overview (Top 3-5 Competitors):**
|
| 240 |
+
* For each:
|
| 241 |
+
* URL
|
| 242 |
+
* Authenticity approach
|
| 243 |
+
* Health benefit emphasis
|
| 244 |
+
* Cultural storytelling elements
|
| 245 |
+
|
| 246 |
+
3. **Mediterranean Value Proposition:**
|
| 247 |
+
* Health benefits (heart health, longevity, etc.)
|
| 248 |
+
* Cultural authenticity and traditions
|
| 249 |
+
* Ingredient quality and sourcing
|
| 250 |
+
* Lifestyle integration aspects
|
| 251 |
+
|
| 252 |
+
4. **Optimized Blog Post Outline:**
|
| 253 |
+
* **H1 Title:**
|
| 254 |
+
* **Meta Description:** (under 160 characters)
|
| 255 |
+
* **Full H2/H3 outline** (including "Mediterranean Diet Benefits", "Authentic Ingredients", "Step-by-Step Instructions", "Cultural Context")
|
| 256 |
+
* **Recipe Schema Markup Elements:**
|
| 257 |
+
* **Required Cultural/Historical Context:**
|
| 258 |
+
|
| 259 |
+
5. **User-Focused FAQ Section:** 3β5 related to '{topic}' (focusing on health and authenticity questions)
|
| 260 |
+
|
| 261 |
+
6. **Internal & External Linking Plan:**
|
| 262 |
+
* **Internal:** 2-3 relevant Mediterranean recipes with anchor suggestions
|
| 263 |
+
* **External:** 1-2 reputable sources for health research or cultural information
|
| 264 |
+
|
| 265 |
+
7. **E-E-A-T Enhancements:**
|
| 266 |
+
* Cultural expertise or travel experience
|
| 267 |
+
* Health research citations
|
| 268 |
+
* Traditional cooking method explanations
|
| 269 |
+
|
| 270 |
+
8. **SEO Performance Metrics:**
|
| 271 |
+
* Expected keyword difficulty (1-100)
|
| 272 |
+
* Estimated monthly search volume
|
| 273 |
+
* Health content optimization
|
| 274 |
+
* Cultural authenticity factors
|
| 275 |
+
""",
|
| 276 |
+
"desserts": """
|
| 277 |
+
Act as an elite-level SEO strategist and content creator with deep expertise in dessert and pastry blogs. I run a blog about desserts and sweet treats, and my primary goal is to increase organic traffic, help home bakers create impressive desserts, and share both classic and innovative sweet recipes. My target audience includes dessert lovers, home bakers, and those looking for special occasion treats.
|
| 278 |
+
|
| 279 |
+
For the specific topic: '{topic}'
|
| 280 |
+
|
| 281 |
+
Analyze and generate a comprehensive SEO content plan designed to rank highly on Google and provide exceptional user value. Ensure all outputs adhere to E-E-A-T principles.
|
| 282 |
+
|
| 283 |
+
I require the following, formatted in clean markdown:
|
| 284 |
+
|
| 285 |
+
1. **Strategic Keyword Analysis:**
|
| 286 |
+
* **Primary Target Keyword:**
|
| 287 |
+
* **Secondary Keywords:** 2-3 closely related, high-intent keywords.
|
| 288 |
+
* **Long-Tail Keywords & User Questions:** 5-7 specific user-searched phrases.
|
| 289 |
+
* **Occasion-Specific Keywords:** (birthday, holiday, celebration, etc.)
|
| 290 |
+
* **Search Intent Analysis:** (Recipe-seeking, Technique learning, Decoration ideas, etc.)
|
| 291 |
+
|
| 292 |
+
2. **Competitive Landscape Overview (Top 3-5 Competitors):**
|
| 293 |
+
* For each:
|
| 294 |
+
* URL
|
| 295 |
+
* Visual presentation quality
|
| 296 |
+
* Technique explanation depth
|
| 297 |
+
* User engagement factors
|
| 298 |
+
|
| 299 |
+
3. **Dessert Value Proposition:**
|
| 300 |
+
* Difficulty level and skill requirements
|
| 301 |
+
* Visual appeal and presentation
|
| 302 |
+
* Flavor profiles and uniqueness
|
| 303 |
+
* Make-ahead and storage options
|
| 304 |
+
|
| 305 |
+
4. **Optimized Blog Post Outline:**
|
| 306 |
+
* **H1 Title:**
|
| 307 |
+
* **Meta Description:** (under 160 characters)
|
| 308 |
+
* **Full H2/H3 outline** (including "Why This Dessert Works", "Ingredients & Substitutions", "Step-by-Step Instructions", "Decoration Tips", "Storage & Serving")
|
| 309 |
+
* **Recipe Schema Markup Elements:**
|
| 310 |
+
* **Required Photo/Video Content:**
|
| 311 |
+
|
| 312 |
+
5. **User-Focused FAQ Section:** 3β5 related to '{topic}' (focusing on technique and troubleshooting questions)
|
| 313 |
+
|
| 314 |
+
6. **Internal & External Linking Plan:**
|
| 315 |
+
* **Internal:** 2-3 relevant dessert recipes with anchor suggestions
|
| 316 |
+
* **External:** 1-2 reputable sources for technique or ingredient information
|
| 317 |
+
|
| 318 |
+
7. **E-E-A-T Enhancements:**
|
| 319 |
+
* Baking expertise and testing notes
|
| 320 |
+
* Personal experience with techniques
|
| 321 |
+
* Scientific explanations for baking chemistry
|
| 322 |
+
|
| 323 |
+
8. **SEO Performance Metrics:**
|
| 324 |
+
* Expected keyword difficulty (1-100)
|
| 325 |
+
* Estimated monthly search volume
|
| 326 |
+
* Visual content requirements
|
| 327 |
+
* Seasonal/occasion optimization
|
| 328 |
"""
|
| 329 |
}
|
| 330 |
|
| 331 |
+
# Enhanced language settings with keyword suggestions
|
| 332 |
LANGUAGE_SETTINGS = {
|
| 333 |
"English": {
|
| 334 |
"search_engines": ["Google", "Bing", "DuckDuckGo"],
|
| 335 |
"localization_tips": "Focus on English-speaking markets (US, UK, Canada, Australia)",
|
| 336 |
+
"keyword_examples": ["recipe", "how to", "benefits of", "best", "easy", "homemade", "healthy", "quick", "simple", "ultimate"],
|
| 337 |
+
"long_tail_patterns": ["how to make", "best way to", "easy recipe for", "homemade", "step by step", "beginner's guide to"],
|
| 338 |
+
"question_keywords": ["what is", "why does", "how long", "can you", "is it safe", "what are the benefits"]
|
| 339 |
},
|
| 340 |
"Spanish": {
|
| 341 |
"search_engines": ["Google", "Bing", "Yahoo"],
|
| 342 |
"localization_tips": "Target Spain and Latin American markets with regional variants",
|
| 343 |
+
"keyword_examples": ["receta", "cΓ³mo hacer", "beneficios de", "mejor", "fΓ‘cil", "casero", "saludable", "rΓ‘pido", "sencillo", "definitivo"],
|
| 344 |
+
"long_tail_patterns": ["cΓ³mo hacer", "mejor manera de", "receta fΓ‘cil de", "casero", "paso a paso", "guΓa para principiantes"],
|
| 345 |
+
"question_keywords": ["quΓ© es", "por quΓ©", "cuΓ‘nto tiempo", "se puede", "es seguro", "cuΓ‘les son los beneficios"]
|
| 346 |
},
|
| 347 |
"French": {
|
| 348 |
"search_engines": ["Google", "Qwant", "Bing"],
|
| 349 |
"localization_tips": "Focus on France, Belgium, Canada (Quebec), Switzerland",
|
| 350 |
+
"keyword_examples": ["recette", "comment faire", "avantages de", "meilleur", "facile", "fait maison", "sain", "rapide", "simple", "ultime"],
|
| 351 |
+
"long_tail_patterns": ["comment faire", "meilleure faΓ§on de", "recette facile de", "fait maison", "Γ©tape par Γ©tape", "guide pour dΓ©butants"],
|
| 352 |
+
"question_keywords": ["qu'est-ce que", "pourquoi", "combien de temps", "peut-on", "est-ce sΓ»r", "quels sont les avantages"]
|
| 353 |
},
|
| 354 |
"German": {
|
| 355 |
"search_engines": ["Google", "Bing", "Yahoo"],
|
| 356 |
"localization_tips": "Target Germany, Austria, Switzerland with appropriate dialect considerations",
|
| 357 |
+
"keyword_examples": ["rezept", "wie man", "vorteile von", "beste", "einfach", "hausgemacht", "gesund", "schnell", "einfach", "ultimativ"],
|
| 358 |
+
"long_tail_patterns": ["wie man macht", "beste Art zu", "einfaches Rezept fΓΌr", "hausgemacht", "Schritt fΓΌr Schritt", "AnfΓ€ngerfΓΌhrer fΓΌr"],
|
| 359 |
+
"question_keywords": ["was ist", "warum", "wie lange", "kann man", "ist es sicher", "was sind die Vorteile"]
|
| 360 |
+
},
|
| 361 |
+
"Italian": {
|
| 362 |
+
"search_engines": ["Google", "Bing", "Yahoo"],
|
| 363 |
+
"localization_tips": "Target Italy with regional food variations and local ingredients",
|
| 364 |
+
"keyword_examples": ["ricetta", "come fare", "benefici di", "migliore", "facile", "fatto in casa", "sano", "veloce", "semplice", "perfetto"],
|
| 365 |
+
"long_tail_patterns": ["come fare", "modo migliore per", "ricetta facile di", "fatto in casa", "passo dopo passo", "guida per principianti"],
|
| 366 |
+
"question_keywords": ["cos'Γ¨", "perchΓ©", "quanto tempo", "si puΓ²", "Γ¨ sicuro", "quali sono i benefici"]
|
| 367 |
}
|
| 368 |
}
|
| 369 |
|
|
|
|
| 399 |
# Initialize templates
|
| 400 |
TEMPLATES, LANGUAGES = load_templates()
|
| 401 |
|
| 402 |
+
# Enhanced HTML export with better styling and SEO metrics
|
| 403 |
+
def generate_html_export(content, title, template_type, language):
|
| 404 |
html_template = f"""<!DOCTYPE html>
|
| 405 |
+
<html lang="{language.lower()[:2]}">
|
| 406 |
<head>
|
| 407 |
<meta charset="UTF-8">
|
| 408 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
| 412 |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 413 |
line-height: 1.6;
|
| 414 |
color: #333;
|
| 415 |
+
max-width: 1000px;
|
| 416 |
margin: 0 auto;
|
| 417 |
padding: 20px;
|
| 418 |
+
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
| 419 |
+
}}
|
| 420 |
+
|
| 421 |
+
.container {{
|
| 422 |
+
background-color: white;
|
| 423 |
+
border-radius: 12px;
|
| 424 |
+
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
| 425 |
+
overflow: hidden;
|
| 426 |
}}
|
| 427 |
+
|
| 428 |
header {{
|
| 429 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 430 |
color: white;
|
| 431 |
+
padding: 30px;
|
| 432 |
text-align: center;
|
|
|
|
|
|
|
| 433 |
}}
|
| 434 |
+
|
| 435 |
+
.header-info {{
|
| 436 |
+
display: flex;
|
| 437 |
+
justify-content: space-between;
|
| 438 |
+
align-items: center;
|
| 439 |
+
margin-top: 20px;
|
| 440 |
+
font-size: 0.9em;
|
| 441 |
+
opacity: 0.9;
|
| 442 |
+
}}
|
| 443 |
+
|
| 444 |
h1 {{
|
| 445 |
margin: 0;
|
| 446 |
+
font-size: 2.2em;
|
| 447 |
+
font-weight: 300;
|
| 448 |
}}
|
| 449 |
+
|
| 450 |
h2 {{
|
| 451 |
+
border-bottom: 3px solid #667eea;
|
| 452 |
padding-bottom: 10px;
|
| 453 |
+
color: #4c51bf;
|
| 454 |
+
margin-top: 30px;
|
| 455 |
}}
|
| 456 |
+
|
| 457 |
h3 {{
|
| 458 |
+
color: #553c9a;
|
| 459 |
+
margin-top: 25px;
|
| 460 |
}}
|
| 461 |
+
|
| 462 |
.content {{
|
| 463 |
+
padding: 40px;
|
| 464 |
+
}}
|
| 465 |
+
|
| 466 |
+
.metrics-box {{
|
| 467 |
+
background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
|
| 468 |
+
padding: 20px;
|
| 469 |
border-radius: 8px;
|
| 470 |
+
margin: 20px 0;
|
| 471 |
+
border-left: 5px solid #f56565;
|
| 472 |
}}
|
| 473 |
+
|
| 474 |
+
.keyword-box {{
|
| 475 |
+
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
|
| 476 |
+
padding: 15px;
|
| 477 |
+
border-radius: 8px;
|
| 478 |
+
margin: 15px 0;
|
| 479 |
}}
|
| 480 |
+
|
| 481 |
ul {{
|
| 482 |
margin-left: 20px;
|
| 483 |
}}
|
| 484 |
+
|
| 485 |
+
li {{
|
| 486 |
+
margin-bottom: 8px;
|
| 487 |
+
padding-left: 5px;
|
| 488 |
+
}}
|
| 489 |
+
|
| 490 |
code {{
|
| 491 |
+
background-color: #f7fafc;
|
| 492 |
+
padding: 3px 6px;
|
| 493 |
+
border-radius: 4px;
|
| 494 |
+
font-family: 'Monaco', 'Consolas', monospace;
|
| 495 |
+
border: 1px solid #e2e8f0;
|
| 496 |
}}
|
| 497 |
+
|
| 498 |
blockquote {{
|
| 499 |
+
border-left: 4px solid #667eea;
|
| 500 |
margin-left: 0;
|
| 501 |
+
padding-left: 20px;
|
| 502 |
+
color: #4a5568;
|
| 503 |
+
font-style: italic;
|
| 504 |
+
background-color: #f7fafc;
|
| 505 |
+
padding: 15px 20px;
|
| 506 |
+
border-radius: 0 8px 8px 0;
|
| 507 |
}}
|
| 508 |
+
|
| 509 |
+
.export-info {{
|
| 510 |
+
background-color: #edf2f7;
|
| 511 |
+
padding: 20px;
|
| 512 |
+
border-radius: 8px;
|
| 513 |
+
margin: 20px 0;
|
| 514 |
+
border: 1px solid #cbd5e0;
|
| 515 |
+
}}
|
| 516 |
+
|
| 517 |
+
footer {{
|
| 518 |
+
background-color: #2d3748;
|
| 519 |
+
color: white;
|
| 520 |
+
padding: 20px;
|
| 521 |
+
text-align: center;
|
| 522 |
+
}}
|
| 523 |
+
|
| 524 |
+
.print-button {{
|
| 525 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 526 |
+
color: white;
|
| 527 |
+
border: none;
|
| 528 |
+
padding: 10px 20px;
|
| 529 |
+
border-radius: 5px;
|
| 530 |
+
cursor: pointer;
|
| 531 |
+
margin: 10px;
|
| 532 |
+
}}
|
| 533 |
+
|
| 534 |
+
@media print {{
|
| 535 |
+
body {{ background: white; }}
|
| 536 |
+
.container {{ box-shadow: none; }}
|
| 537 |
+
.print-button {{ display: none; }}
|
| 538 |
}}
|
| 539 |
</style>
|
| 540 |
</head>
|
| 541 |
<body>
|
| 542 |
+
<div class="container">
|
| 543 |
+
<header>
|
| 544 |
+
<h1>{title} - SEO Content Strategy</h1>
|
| 545 |
+
<div class="header-info">
|
| 546 |
+
<span>π Template: {template_type.title()}</span>
|
| 547 |
+
<span>π Language: {language}</span>
|
| 548 |
+
<span>π
Generated: {datetime.now().strftime("%B %d, %Y at %H:%M")}</span>
|
| 549 |
+
</div>
|
| 550 |
+
</header>
|
| 551 |
+
|
| 552 |
+
<div class="content">
|
| 553 |
+
<div class="export-info">
|
| 554 |
+
<strong>π Export Information:</strong><br>
|
| 555 |
+
This SEO plan was generated using AI analysis and industry best practices.
|
| 556 |
+
Use this as a strategic guide for your content creation process.
|
| 557 |
+
<button class="print-button" onclick="window.print()">π¨οΈ Print/Save as PDF</button>
|
| 558 |
+
</div>
|
| 559 |
+
|
| 560 |
+
{markdown.markdown(content)}
|
| 561 |
+
</div>
|
| 562 |
+
|
| 563 |
+
<footer>
|
| 564 |
+
<p>π Generated using Enhanced SEO Assistant |
|
| 565 |
+
Template: {template_type.title()} |
|
| 566 |
+
Language: {language} |
|
| 567 |
+
AI-Powered Content Strategy</p>
|
| 568 |
+
</footer>
|
| 569 |
</div>
|
| 570 |
+
|
| 571 |
+
<script>
|
| 572 |
+
// Add some interactivity
|
| 573 |
+
document.addEventListener('DOMContentLoaded', function() {{
|
| 574 |
+
// Highlight keywords in content
|
| 575 |
+
const keywords = document.querySelectorAll('code');
|
| 576 |
+
keywords.forEach(keyword => {{
|
| 577 |
+
keyword.style.cursor = 'pointer';
|
| 578 |
+
keyword.addEventListener('click', function() {{
|
| 579 |
+
navigator.clipboard.writeText(this.textContent);
|
| 580 |
+
this.style.backgroundColor = '#48bb78';
|
| 581 |
+
this.style.color = 'white';
|
| 582 |
+
setTimeout(() => {{
|
| 583 |
+
this.style.backgroundColor = '#f7fafc';
|
| 584 |
+
this.style.color = '#2d3748';
|
| 585 |
+
}}, 1000);
|
| 586 |
+
}});
|
| 587 |
+
}});
|
| 588 |
+
}});
|
| 589 |
+
</script>
|
| 590 |
</body>
|
| 591 |
</html>
|
| 592 |
"""
|
| 593 |
return html_template
|
| 594 |
|
| 595 |
# Export the SEO plan as HTML and create download link
|
| 596 |
+
def export_html(content, topic, template_type, language):
|
| 597 |
if not content or content.startswith("β οΈ") or content.startswith("π"):
|
| 598 |
+
return "Please generate an SEO plan first.", None
|
| 599 |
|
| 600 |
title = topic.strip().title()
|
| 601 |
+
html_content = generate_html_export(content, title, template_type, language)
|
| 602 |
|
| 603 |
# Create a safe filename
|
| 604 |
safe_filename = "".join([c if c.isalnum() or c in " -_" else "_" for c in title])
|
| 605 |
+
safe_filename = f"{safe_filename}_{template_type}_{language}_SEO_Plan.html".replace(" ", "_")
|
| 606 |
|
| 607 |
# Write to file
|
| 608 |
+
try:
|
| 609 |
+
with open(safe_filename, "w", encoding="utf-8") as f:
|
| 610 |
+
f.write(html_content)
|
| 611 |
+
|
| 612 |
+
# Return both status message and file path for download
|
| 613 |
+
return f"β
HTML export saved as '{safe_filename}'", safe_filename
|
| 614 |
+
except Exception as e:
|
| 615 |
+
return f"β Error saving file: {str(e)}", None
|
| 616 |
|
| 617 |
+
# Enhanced template management
|
| 618 |
def save_custom_template(template_name, template_content):
|
| 619 |
if not template_name or not template_content:
|
| 620 |
return "β οΈ Please provide both a template name and content."
|
| 621 |
|
| 622 |
# Add to templates
|
| 623 |
+
TEMPLATES[template_name.lower().replace(" ", "_")] = template_content
|
| 624 |
|
| 625 |
# Save to file
|
| 626 |
save_templates()
|
| 627 |
|
| 628 |
return f"β
Template '{template_name}' saved successfully!"
|
| 629 |
|
| 630 |
+
def delete_template(template_name):
|
| 631 |
+
if template_name in TEMPLATES:
|
| 632 |
+
if template_name in DEFAULT_TEMPLATES:
|
| 633 |
+
return "β οΈ Cannot delete default templates."
|
| 634 |
+
|
| 635 |
+
del TEMPLATES[template_name]
|
| 636 |
+
save_templates()
|
| 637 |
+
return f"β
Template '{template_name}' deleted successfully!"
|
| 638 |
+
else:
|
| 639 |
+
return f"β οΈ Template '{template_name}' not found."
|
| 640 |
+
|
| 641 |
+
def load_template_content(template_name):
|
| 642 |
+
if template_name in TEMPLATES:
|
| 643 |
+
return TEMPLATES[template_name]
|
| 644 |
+
return ""
|
| 645 |
+
|
| 646 |
+
def get_template_list():
|
| 647 |
+
return list(TEMPLATES.keys())
|
| 648 |
+
|
| 649 |
+
# Enhanced language settings management
|
| 650 |
+
def save_language_settings(language_name, search_engines, localization_tips, keyword_examples, long_tail_patterns, question_keywords):
|
| 651 |
if not language_name:
|
| 652 |
return "β οΈ Please provide a language name."
|
| 653 |
|
| 654 |
+
# Process inputs
|
| 655 |
+
search_engines_list = [se.strip() for se in search_engines.split(",") if se.strip()]
|
| 656 |
+
keyword_examples_list = [kw.strip() for kw in keyword_examples.split(",") if kw.strip()]
|
| 657 |
+
long_tail_list = [lt.strip() for lt in long_tail_patterns.split(",") if lt.strip()]
|
| 658 |
+
question_list = [q.strip() for q in question_keywords.split(",") if q.strip()]
|
| 659 |
|
| 660 |
# Add to languages
|
| 661 |
LANGUAGES[language_name] = {
|
| 662 |
+
"search_engines": search_engines_list,
|
| 663 |
"localization_tips": localization_tips,
|
| 664 |
+
"keyword_examples": keyword_examples_list,
|
| 665 |
+
"long_tail_patterns": long_tail_list,
|
| 666 |
+
"question_keywords": question_list
|
| 667 |
}
|
| 668 |
|
| 669 |
# Save to file
|
|
|
|
| 671 |
|
| 672 |
return f"β
Language settings for '{language_name}' saved successfully!"
|
| 673 |
|
| 674 |
+
# Enhanced prompt building with advanced features
|
| 675 |
+
def build_prompt(topic, template_key="fermentation", language="English", include_advanced_metrics=True):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 676 |
# Get base template
|
| 677 |
if template_key in TEMPLATES:
|
| 678 |
template = TEMPLATES[template_key]
|
|
|
|
| 684 |
|
| 685 |
# Add language-specific instructions
|
| 686 |
language_instructions = f"""
|
| 687 |
+
LANGUAGE & LOCALIZATION OPTIMIZATION FOR {language.upper()}:
|
| 688 |
|
| 689 |
1. **Target Search Engines:** {', '.join(lang_settings['search_engines'])}
|
| 690 |
+
2. **Localization Strategy:** {lang_settings['localization_tips']}
|
| 691 |
+
3. **Primary Keyword Patterns:** {', '.join(lang_settings['keyword_examples'])}
|
| 692 |
+
4. **Long-tail Keyword Patterns:** {', '.join(lang_settings.get('long_tail_patterns', []))}
|
| 693 |
+
5. **Question-based Keywords:** {', '.join(lang_settings.get('question_keywords', []))}
|
| 694 |
+
|
| 695 |
"""
|
| 696 |
|
| 697 |
+
# Add advanced SEO metrics if requested
|
| 698 |
+
if include_advanced_metrics:
|
| 699 |
+
advanced_metrics = """
|
| 700 |
+
ADVANCED SEO METRICS TO INCLUDE:
|
| 701 |
+
|
| 702 |
+
9. **Content Performance Analysis:**
|
| 703 |
+
* Recommended content length (word count)
|
| 704 |
+
* Target reading time
|
| 705 |
+
* Keyword density recommendations
|
| 706 |
+
* Readability score target (Flesch-Kincaid)
|
| 707 |
+
* Mobile optimization considerations
|
| 708 |
+
|
| 709 |
+
10. **AI-Powered Content Suggestions:**
|
| 710 |
+
* Trending subtopics to include
|
| 711 |
+
* Related questions people are asking
|
| 712 |
+
* Seasonal content opportunities
|
| 713 |
+
* Social media content ideas
|
| 714 |
+
* Email marketing angles
|
| 715 |
+
|
| 716 |
+
11. **Technical SEO Considerations:**
|
| 717 |
+
* Page speed optimization tips
|
| 718 |
+
* Image optimization requirements
|
| 719 |
+
* Schema markup recommendations
|
| 720 |
+
* Internal linking architecture
|
| 721 |
+
* URL structure suggestions
|
| 722 |
+
|
| 723 |
+
12. **Content Distribution Strategy:**
|
| 724 |
+
* Social media promotion angles
|
| 725 |
+
* Email newsletter content ideas
|
| 726 |
+
* Pinterest optimization tips
|
| 727 |
+
* YouTube video content suggestions
|
| 728 |
+
* Podcast episode ideas
|
| 729 |
+
"""
|
| 730 |
+
else:
|
| 731 |
+
advanced_metrics = ""
|
| 732 |
+
|
| 733 |
+
# Combine all elements
|
| 734 |
if language != "English":
|
| 735 |
+
full_template = template + "\n\n" + language_instructions + advanced_metrics
|
| 736 |
else:
|
| 737 |
+
full_template = template + "\n\n" + advanced_metrics
|
| 738 |
|
| 739 |
# Format with the topic
|
| 740 |
return full_template.format(topic=topic)
|
| 741 |
|
| 742 |
+
# Enhanced SEO generation with streaming
|
| 743 |
+
def generate_seo_plan(topic, api_key, template_key="fermentation", language="English", temperature=0.7, max_tokens=6000, include_advanced_metrics=True):
|
| 744 |
# Input validation
|
| 745 |
if not topic.strip():
|
| 746 |
+
return "β οΈ Please enter a topic to generate an SEO plan."
|
| 747 |
|
| 748 |
if not api_key.strip():
|
| 749 |
return "β οΈ Please provide your Gemini API key."
|
| 750 |
|
| 751 |
# Show that processing has started
|
| 752 |
+
yield "π Initializing Enhanced SEO Assistant..."
|
| 753 |
|
| 754 |
try:
|
| 755 |
# Configure Gemini with the provided API key
|
| 756 |
genai.configure(api_key=api_key)
|
| 757 |
|
| 758 |
+
# Initialize the model with enhanced settings
|
| 759 |
model = genai.GenerativeModel(
|
| 760 |
"gemini-1.5-pro",
|
| 761 |
generation_config={
|
| 762 |
"temperature": float(temperature),
|
| 763 |
"max_output_tokens": max_tokens,
|
| 764 |
+
"top_p": 0.95,
|
| 765 |
+
"top_k": 40
|
| 766 |
}
|
| 767 |
)
|
| 768 |
|
| 769 |
# Update status
|
| 770 |
+
yield f"π§ Building enhanced SEO prompt for {template_key} niche in {language}..."
|
| 771 |
|
| 772 |
+
# Build the enhanced prompt
|
| 773 |
+
prompt = build_prompt(topic, template_key, language, include_advanced_metrics)
|
| 774 |
|
| 775 |
# Update status
|
| 776 |
+
yield "π Generating comprehensive SEO plan with Gemini 1.5 Pro..."
|
| 777 |
|
| 778 |
+
# Generate response with streaming
|
| 779 |
+
response = model.generate_content(prompt, stream=True)
|
| 780 |
|
| 781 |
+
# Collect response
|
| 782 |
+
full_response = ""
|
| 783 |
+
for chunk in response:
|
| 784 |
+
if chunk.text:
|
| 785 |
+
full_response += chunk.text
|
| 786 |
+
yield "π " + full_response # Show progress
|
| 787 |
|
| 788 |
+
# Final formatting
|
| 789 |
+
yield "β¨ Finalizing your enhanced SEO plan..."
|
| 790 |
+
time.sleep(0.5)
|
| 791 |
+
|
| 792 |
+
# Return final response
|
| 793 |
+
yield full_response
|
| 794 |
|
| 795 |
except Exception as e:
|
| 796 |
error_message = str(e)
|
| 797 |
+
print(f"Error generating SEO plan: {error_message}")
|
| 798 |
if "API key not valid" in error_message or "authentication" in error_message.lower():
|
| 799 |
yield "β οΈ API Key Error: The provided Gemini API key appears to be invalid. Please check your key and try again."
|
| 800 |
elif "quota" in error_message.lower():
|
|
|
|
| 802 |
else:
|
| 803 |
yield f"β οΈ Error: {error_message}"
|
| 804 |
|
| 805 |
+
# AI-powered content suggestions
|
| 806 |
+
def generate_content_ideas(topic, api_key, template_key="fermentation", language="English"):
|
| 807 |
+
if not topic.strip() or not api_key.strip():
|
| 808 |
+
return "β οΈ Please provide both a topic and API key."
|
| 809 |
+
|
| 810 |
+
try:
|
| 811 |
+
genai.configure(api_key=api_key)
|
| 812 |
+
model = genai.GenerativeModel("gemini-1.5-pro")
|
| 813 |
+
|
| 814 |
+
prompt = f"""
|
| 815 |
+
As an AI content strategist specializing in {template_key} content, generate creative content ideas for the topic: "{topic}"
|
| 816 |
+
|
| 817 |
+
Please provide:
|
| 818 |
+
|
| 819 |
+
1. **5 Related Blog Post Ideas:**
|
| 820 |
+
- Complementary topics that would work well together
|
| 821 |
+
- Different angles on the same subject
|
| 822 |
+
|
| 823 |
+
2. **Social Media Content Ideas:**
|
| 824 |
+
- 3 Instagram post concepts
|
| 825 |
+
- 3 TikTok/Reel ideas
|
| 826 |
+
- 2 Pinterest pin concepts
|
| 827 |
+
|
| 828 |
+
3. **Email Marketing Angles:**
|
| 829 |
+
- Welcome series email ideas
|
| 830 |
+
- Newsletter content suggestions
|
| 831 |
+
|
| 832 |
+
4. **Video Content Opportunities:**
|
| 833 |
+
- YouTube video concepts
|
| 834 |
+
- Short-form video ideas
|
| 835 |
+
|
| 836 |
+
5. **Seasonal Content Calendar:**
|
| 837 |
+
- Monthly content themes
|
| 838 |
+
- Holiday tie-ins
|
| 839 |
+
|
| 840 |
+
6. **User-Generated Content Ideas:**
|
| 841 |
+
- Contest/challenge concepts
|
| 842 |
+
- Community engagement strategies
|
| 843 |
+
|
| 844 |
+
Format in clean markdown with actionable suggestions.
|
| 845 |
+
"""
|
| 846 |
+
|
| 847 |
+
response = model.generate_content(prompt)
|
| 848 |
+
return response.text
|
| 849 |
+
|
| 850 |
+
except Exception as e:
|
| 851 |
+
return f"β οΈ Error generating content ideas: {str(e)}"
|
| 852 |
+
|
| 853 |
+
# Keyword research enhancement
|
| 854 |
+
def generate_keyword_research(topic, api_key, language="English", competition_level="medium"):
|
| 855 |
+
if not topic.strip() or not api_key.strip():
|
| 856 |
+
return "β οΈ Please provide both a topic and API key."
|
| 857 |
+
|
| 858 |
+
try:
|
| 859 |
+
genai.configure(api_key=api_key)
|
| 860 |
+
model = genai.GenerativeModel("gemini-1.5-pro")
|
| 861 |
+
|
| 862 |
+
lang_settings = LANGUAGES.get(language, LANGUAGES["English"])
|
| 863 |
+
|
| 864 |
+
prompt = f"""
|
| 865 |
+
As an SEO keyword research specialist, provide comprehensive keyword analysis for: "{topic}" in {language}
|
| 866 |
+
|
| 867 |
+
Target competition level: {competition_level}
|
| 868 |
+
|
| 869 |
+
Please provide:
|
| 870 |
+
|
| 871 |
+
1. **Primary Keywords (3-5):**
|
| 872 |
+
- High search volume, {competition_level} competition
|
| 873 |
+
- Include estimated monthly searches
|
| 874 |
+
|
| 875 |
+
2. **Long-tail Keywords (10-15):**
|
| 876 |
+
- Lower competition, more specific
|
| 877 |
+
- Question-based keywords using patterns: {', '.join(lang_settings.get('question_keywords', []))}
|
| 878 |
+
|
| 879 |
+
3. **Semantic Keywords (8-10):**
|
| 880 |
+
- Related terms and synonyms
|
| 881 |
+
- LSI keywords for content depth
|
| 882 |
+
|
| 883 |
+
4. **Local SEO Keywords (if applicable):**
|
| 884 |
+
- Location-based variations
|
| 885 |
+
- "Near me" variations
|
| 886 |
+
|
| 887 |
+
5. **Competitor Keywords:**
|
| 888 |
+
- What competitors are likely ranking for
|
| 889 |
+
- Keyword gaps to exploit
|
| 890 |
+
|
| 891 |
+
6. **Trending Keywords:**
|
| 892 |
+
- Seasonal trends
|
| 893 |
+
- Emerging topics in this niche
|
| 894 |
+
|
| 895 |
+
7. **Conversion-Focused Keywords:**
|
| 896 |
+
- Commercial intent keywords
|
| 897 |
+
- Buyer journey keywords
|
| 898 |
+
|
| 899 |
+
Provide keyword difficulty estimates (1-100) and search volume estimates for each category.
|
| 900 |
+
Format in clean markdown with actionable insights.
|
| 901 |
+
"""
|
| 902 |
+
|
| 903 |
+
response = model.generate_content(prompt)
|
| 904 |
+
return response.text
|
| 905 |
+
|
| 906 |
+
except Exception as e:
|
| 907 |
+
return f"β οΈ Error generating keyword research: {str(e)}"
|
| 908 |
+
|
| 909 |
# Function to clear outputs
|
| 910 |
def clear_outputs():
|
| 911 |
+
return "", "", gr.update(value=""), gr.update(value="")
|
| 912 |
|
| 913 |
# Save API key to user's preferences
|
| 914 |
def save_api_key(api_key):
|
|
|
|
| 918 |
return "β
API key saved successfully!"
|
| 919 |
return "οΏ½οΏ½οΏ½οΈ Please enter an API key to save"
|
| 920 |
|
| 921 |
+
# Enhanced theme
|
| 922 |
custom_theme = gr.themes.Soft(
|
| 923 |
+
primary_hue="blue",
|
| 924 |
+
secondary_hue="purple",
|
| 925 |
).set(
|
| 926 |
+
body_text_color="#2d3748",
|
| 927 |
block_title_text_weight="600",
|
| 928 |
+
button_primary_background_fill="linear-gradient(90deg, #667eea 0%, #764ba2 100%)",
|
| 929 |
+
button_primary_background_fill_hover="linear-gradient(90deg, #764ba2 0%, #667eea 100%)",
|
| 930 |
button_primary_text_color="white",
|
| 931 |
block_label_text_size="0.9rem",
|
| 932 |
block_title_text_size="1.2rem"
|
| 933 |
)
|
| 934 |
|
| 935 |
+
# Main Gradio app with 6 organized sections
|
| 936 |
+
with gr.Blocks(title="Enhanced SEO Assistant", theme=custom_theme, css="""
|
| 937 |
+
.main-container {
|
| 938 |
+
max-width: 1200px;
|
| 939 |
+
margin: 0 auto;
|
| 940 |
+
}
|
| 941 |
+
|
| 942 |
+
.section-header {
|
| 943 |
+
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
|
| 944 |
+
color: white;
|
| 945 |
+
padding: 15px;
|
| 946 |
+
border-radius: 8px;
|
| 947 |
+
margin: 20px 0 10px 0;
|
| 948 |
+
text-align: center;
|
| 949 |
+
font-weight: bold;
|
| 950 |
}
|
| 951 |
|
| 952 |
+
.feature-box {
|
| 953 |
+
border: 2px solid #e2e8f0;
|
| 954 |
+
border-radius: 8px;
|
| 955 |
+
padding: 20px;
|
| 956 |
+
margin: 10px 0;
|
| 957 |
+
background: linear-gradient(135deg, #f7fafc 0%, #edf2f7 100%);
|
| 958 |
}
|
| 959 |
|
| 960 |
+
.output-container {
|
| 961 |
+
min-height: 400px;
|
| 962 |
+
max-height: 800px;
|
| 963 |
+
overflow-y: auto;
|
| 964 |
+
border-left: 4px solid #667eea;
|
| 965 |
+
padding: 20px;
|
| 966 |
+
background: linear-gradient(135deg, #f7fafc 0%, #e6fffa 100%);
|
| 967 |
+
border-radius: 8px;
|
| 968 |
+
margin: 10px 0;
|
| 969 |
}
|
| 970 |
|
| 971 |
+
.metrics-display {
|
| 972 |
+
background: linear-gradient(135deg, #fed7d7 0%, #fbb6ce 100%);
|
| 973 |
+
border-radius: 8px;
|
| 974 |
+
padding: 15px;
|
| 975 |
+
margin: 10px 0;
|
| 976 |
}
|
| 977 |
""") as app:
|
| 978 |
+
|
| 979 |
# Header
|
| 980 |
gr.Markdown("""
|
| 981 |
+
# π Enhanced SEO Content Assistant
|
| 982 |
+
### AI-Powered Content Strategy for Food Bloggers & Content Creators
|
| 983 |
|
| 984 |
+
Generate comprehensive SEO plans, keyword research, and content ideas using Google's Gemini 1.5 Pro.
|
| 985 |
""")
|
| 986 |
|
| 987 |
+
# ============== SECTION 1: API Configuration & Settings ==============
|
| 988 |
+
with gr.Group():
|
| 989 |
+
gr.HTML('<div class="section-header">π§ Section 1: API Configuration & Settings</div>')
|
| 990 |
+
|
| 991 |
+
with gr.Row():
|
| 992 |
+
with gr.Column(scale=2):
|
| 993 |
+
api_key_input = gr.Textbox(
|
| 994 |
+
label="π Gemini API Key",
|
| 995 |
+
placeholder="Enter your Google Gemini API key",
|
| 996 |
+
value=os.getenv("GEMINI_API_KEY", ""),
|
| 997 |
+
type="password"
|
| 998 |
+
)
|
| 999 |
+
with gr.Column(scale=1):
|
| 1000 |
+
save_api_btn = gr.Button("πΎ Save Key", variant="secondary")
|
| 1001 |
+
api_status = gr.Textbox(label="Status", interactive=False, max_lines=1)
|
| 1002 |
+
|
| 1003 |
+
with gr.Row():
|
| 1004 |
+
with gr.Column():
|
| 1005 |
+
gr.Markdown("### ποΈ Advanced Settings")
|
| 1006 |
+
temperature = gr.Slider(
|
| 1007 |
+
minimum=0.0,
|
| 1008 |
+
maximum=1.0,
|
| 1009 |
+
value=0.7,
|
| 1010 |
+
step=0.1,
|
| 1011 |
+
label="Temperature (Creativity)",
|
| 1012 |
+
info="Higher = more creative, Lower = more focused"
|
| 1013 |
+
)
|
| 1014 |
+
with gr.Column():
|
| 1015 |
+
max_tokens = gr.Slider(
|
| 1016 |
+
minimum=2000,
|
| 1017 |
+
maximum=8000,
|
| 1018 |
+
value=6000,
|
| 1019 |
+
step=500,
|
| 1020 |
+
label="Max Output Length",
|
| 1021 |
+
info="Maximum response length"
|
| 1022 |
+
)
|
| 1023 |
+
with gr.Column():
|
| 1024 |
+
include_advanced = gr.Checkbox(
|
| 1025 |
+
label="Include Advanced Metrics",
|
| 1026 |
+
value=True,
|
| 1027 |
+
info="Include technical SEO and content distribution strategies"
|
| 1028 |
+
)
|
| 1029 |
+
|
| 1030 |
+
# ============== SECTION 2: Template & Language Selection ==============
|
| 1031 |
+
with gr.Group():
|
| 1032 |
+
gr.HTML('<div class="section-header">π― Section 2: Template & Language Selection</div>')
|
| 1033 |
+
|
| 1034 |
with gr.Row():
|
| 1035 |
+
with gr.Column():
|
| 1036 |
+
template_dropdown = gr.Dropdown(
|
| 1037 |
+
choices=list(TEMPLATES.keys()),
|
| 1038 |
+
value="fermentation",
|
| 1039 |
+
label="π½οΈ Content Template",
|
| 1040 |
+
info="Choose your food niche template"
|
| 1041 |
+
)
|
| 1042 |
+
with gr.Column():
|
| 1043 |
+
language_dropdown = gr.Dropdown(
|
| 1044 |
+
choices=list(LANGUAGES.keys()),
|
| 1045 |
+
value="English",
|
| 1046 |
+
label="π Target Language",
|
| 1047 |
+
info="Optimize for specific language/region"
|
| 1048 |
+
)
|
| 1049 |
+
|
| 1050 |
+
with gr.Accordion("π Template Management", open=False):
|
| 1051 |
+
with gr.Row():
|
| 1052 |
+
with gr.Column():
|
| 1053 |
+
custom_template_name = gr.Textbox(label="Template Name", placeholder="e.g., my_custom_template")
|
| 1054 |
+
custom_template_content = gr.Textbox(
|
| 1055 |
+
label="Template Content",
|
| 1056 |
+
placeholder="Enter your custom template with {topic} placeholder",
|
| 1057 |
+
lines=10
|
| 1058 |
+
)
|
| 1059 |
+
save_template_btn = gr.Button("πΎ Save Custom Template")
|
| 1060 |
+
template_status = gr.Textbox(label="Template Status", interactive=False)
|
| 1061 |
+
|
| 1062 |
+
with gr.Column():
|
| 1063 |
+
template_preview = gr.Textbox(
|
| 1064 |
+
label="Template Preview",
|
| 1065 |
+
placeholder="Select a template to preview",
|
| 1066 |
+
lines=10,
|
| 1067 |
+
interactive=False
|
| 1068 |
+
)
|
| 1069 |
+
load_template_btn = gr.Button("π Preview Selected Template")
|
| 1070 |
+
|
| 1071 |
+
# ============== SECTION 3: Main SEO Plan Generation ==============
|
| 1072 |
+
with gr.Group():
|
| 1073 |
+
gr.HTML('<div class="section-header">β¨ Section 3: SEO Plan Generation</div>')
|
| 1074 |
|
| 1075 |
with gr.Row():
|
| 1076 |
+
with gr.Column(scale=1):
|
| 1077 |
+
topic_input = gr.Textbox(
|
| 1078 |
+
label="π― Your Content Topic",
|
| 1079 |
+
placeholder="e.g., Ultimate Guide to Homemade Kimchi",
|
| 1080 |
+
lines=3
|
| 1081 |
+
)
|
| 1082 |
+
|
| 1083 |
+
with gr.Row():
|
| 1084 |
+
generate_btn = gr.Button("π Generate SEO Plan", variant="primary", size="lg")
|
| 1085 |
+
clear_btn = gr.Button("π Clear All", variant="secondary")
|
| 1086 |
+
|
| 1087 |
+
gr.Examples(
|
| 1088 |
+
examples=[
|
| 1089 |
+
"Beginner's Guide to Fermenting Vegetables at Home",
|
| 1090 |
+
"Perfect Sourdough Starter: Science and Technique",
|
| 1091 |
+
"Keto-Friendly Fermented Foods for Weight Loss",
|
| 1092 |
+
"Mediterranean Diet: Heart-Healthy Fermented Options",
|
| 1093 |
+
"Plant-Based Fermentation: Dairy-Free Alternatives",
|
| 1094 |
+
"Holiday Desserts: Naturally Fermented Sweet Treats"
|
| 1095 |
+
],
|
| 1096 |
+
inputs=topic_input,
|
| 1097 |
+
label="π‘ Example Topics"
|
| 1098 |
+
)
|
| 1099 |
|
| 1100 |
+
with gr.Column(scale=2):
|
| 1101 |
+
seo_output = gr.Markdown(
|
| 1102 |
+
value="Your comprehensive SEO plan will appear here...",
|
| 1103 |
+
elem_classes=["output-container"]
|
| 1104 |
+
)
|
| 1105 |
+
|
| 1106 |
+
# ============== SECTION 4: Export & Download Options ==============
|
| 1107 |
+
with gr.Group():
|
| 1108 |
+
gr.HTML('<div class="section-header">οΏ½οΏ½οΏ½ Section 4: Export & Download Options</div>')
|
| 1109 |
+
|
| 1110 |
+
with gr.Row():
|
| 1111 |
+
with gr.Column():
|
| 1112 |
+
export_html_btn = gr.Button("π Export as HTML", variant="primary")
|
| 1113 |
+
export_status = gr.Textbox(label="Export Status", interactive=False)
|
| 1114 |
+
|
| 1115 |
+
with gr.Column():
|
| 1116 |
+
download_file = gr.File(label="π₯ Download Exported File", interactive=False)
|
| 1117 |
+
|
| 1118 |
+
with gr.Row():
|
| 1119 |
+
gr.Markdown("""
|
| 1120 |
+
### π Export Features:
|
| 1121 |
+
- **Professional HTML Format**: Beautiful, printable SEO plans
|
| 1122 |
+
- **Template Information**: Includes template type and language used
|
| 1123 |
+
- **Print-Friendly**: Optimized for PDF export
|
| 1124 |
+
- **Interactive Elements**: Clickable keywords for easy copying
|
| 1125 |
+
""")
|
| 1126 |
+
|
| 1127 |
+
# ============== SECTION 5: Advanced SEO Tools ==============
|
| 1128 |
+
with gr.Group():
|
| 1129 |
+
gr.HTML('<div class="section-header">π Section 5: Advanced SEO Tools</div>')
|
| 1130 |
+
|
| 1131 |
+
with gr.Tabs():
|
| 1132 |
+
with gr.Tab("π― Keyword Research"):
|
| 1133 |
+
with gr.Row():
|
| 1134 |
+
keyword_topic = gr.Textbox(label="Topic for Keyword Research", placeholder="Enter topic for keyword analysis")
|
| 1135 |
+
competition_level = gr.Dropdown(
|
| 1136 |
+
choices=["low", "medium", "high"],
|
| 1137 |
+
value="medium",
|
| 1138 |
+
label="Competition Level"
|
| 1139 |
+
)
|
| 1140 |
+
|
| 1141 |
+
keyword_research_btn = gr.Button("π Generate Keyword Report")
|
| 1142 |
+
keyword_output = gr.Markdown(elem_classes=["output-container"])
|
| 1143 |
+
|
| 1144 |
+
with gr.Tab("π‘ Content Ideas"):
|
| 1145 |
+
content_ideas_topic = gr.Textbox(label="Topic for Content Ideas", placeholder="Enter topic for content brainstorming")
|
| 1146 |
+
content_ideas_btn = gr.Button("π‘ Generate Content Ideas")
|
| 1147 |
+
content_ideas_output = gr.Markdown(elem_classes=["output-container"])
|
| 1148 |
|
| 1149 |
+
with gr.Tab("π SEO Metrics"):
|
| 1150 |
+
gr.Markdown("""
|
| 1151 |
+
### π SEO Performance Metrics Included:
|
| 1152 |
+
- **Keyword Difficulty Analysis**: Competition assessment (1-100)
|
| 1153 |
+
- **Search Volume Estimates**: Monthly search predictions
|
| 1154 |
+
- **Content Length Recommendations**: Optimal word count
|
| 1155 |
+
- **Readability Targets**: Flesch-Kincaid score goals
|
| 1156 |
+
- **Technical SEO Checklist**: Page speed, schema markup
|
| 1157 |
+
- **Mobile Optimization**: Responsive design considerations
|
| 1158 |
+
""")
|
| 1159 |
+
|
| 1160 |
+
# ============== SECTION 6: Language & Localization Settings ==============
|
| 1161 |
+
with gr.Group():
|
| 1162 |
+
gr.HTML('<div class="section-header">π Section 6: Language & Localization Settings</div>')
|
| 1163 |
+
|
| 1164 |
+
with gr.Accordion("π§ Language Settings Management", open=False):
|
| 1165 |
with gr.Row():
|
| 1166 |
+
with gr.Column():
|
| 1167 |
+
lang_name = gr.Textbox(label="Language Name", placeholder="e.g., Portuguese")
|
| 1168 |
+
search_engines = gr.Textbox(
|
| 1169 |
+
label="Search Engines",
|
| 1170 |
+
placeholder="Google, Bing, Yahoo (comma-separated)"
|
| 1171 |
+
)
|
| 1172 |
+
localization_tips = gr.Textbox(
|
| 1173 |
+
label="Localization Tips",
|
| 1174 |
+
placeholder="Regional considerations and market focus",
|
| 1175 |
+
lines=3
|
| 1176 |
+
)
|
| 1177 |
+
|
| 1178 |
+
with gr.Column():
|
| 1179 |
+
keyword_examples = gr.Textbox(
|
| 1180 |
+
label="Keyword Examples",
|
| 1181 |
+
placeholder="Common keywords in this language (comma-separated)",
|
| 1182 |
+
lines=2
|
| 1183 |
+
)
|
| 1184 |
+
long_tail_patterns = gr.Textbox(
|
| 1185 |
+
label="Long-tail Patterns",
|
| 1186 |
+
placeholder="Common long-tail keyword patterns (comma-separated)",
|
| 1187 |
+
lines=2
|
| 1188 |
+
)
|
| 1189 |
+
question_keywords = gr.Textbox(
|
| 1190 |
+
label="Question Keywords",
|
| 1191 |
+
placeholder="Common question words (comma-separated)",
|
| 1192 |
+
lines=2
|
| 1193 |
+
)
|
| 1194 |
+
|
| 1195 |
+
save_lang_btn = gr.Button("πΎ Save Language Settings")
|
| 1196 |
+
lang_status = gr.Textbox(label="Language Settings Status", interactive=False)
|
| 1197 |
+
|
| 1198 |
+
with gr.Row():
|
| 1199 |
+
gr.Markdown("""
|
| 1200 |
+
### πΊοΈ Current Language Support:
|
| 1201 |
+
- **English**: US, UK, Canada, Australia markets
|
| 1202 |
+
- **Spanish**: Spain and Latin American markets
|
| 1203 |
+
- **French**: France, Belgium, Quebec, Switzerland
|
| 1204 |
+
- **German**: Germany, Austria, Switzerland
|
| 1205 |
+
- **Italian**: Italy with regional variations
|
| 1206 |
|
| 1207 |
+
Add more languages using the settings panel above!
|
| 1208 |
+
""")
|
| 1209 |
+
|
| 1210 |
+
# ============== EVENT HANDLERS ==============
|
| 1211 |
+
|
| 1212 |
+
# API Key Management
|
| 1213 |
+
save_api_btn.click(
|
| 1214 |
+
fn=save_api_key,
|
| 1215 |
+
inputs=api_key_input,
|
| 1216 |
+
outputs=api_status
|
| 1217 |
+
)
|
| 1218 |
+
|
| 1219 |
+
# Template Management
|
| 1220 |
+
save_template_btn.click(
|
| 1221 |
+
fn=save_custom_template,
|
| 1222 |
+
inputs=[custom_template_name, custom_template_content],
|
| 1223 |
+
outputs=template_status
|
| 1224 |
+
)
|
| 1225 |
+
|
| 1226 |
+
load_template_btn.click(
|
| 1227 |
+
fn=load_template_content,
|
| 1228 |
+
inputs=template_dropdown,
|
| 1229 |
+
outputs=template_preview
|
| 1230 |
+
)
|
| 1231 |
+
|
| 1232 |
+
# Main SEO Generation
|
| 1233 |
generate_btn.click(
|
| 1234 |
fn=generate_seo_plan,
|
| 1235 |
+
inputs=[topic_input, api_key_input, template_dropdown, language_dropdown, temperature, max_tokens, include_advanced],
|
| 1236 |
outputs=seo_output,
|
| 1237 |
+
show_progress="full"
|
| 1238 |
+
)
|
| 1239 |
+
|
| 1240 |
+
# Export Functionality
|
| 1241 |
+
export_html_btn.click(
|
| 1242 |
+
fn=export_html,
|
| 1243 |
+
inputs=[seo_output, topic_input, template_dropdown, language_dropdown],
|
| 1244 |
+
outputs=[export_status, download_file]
|
| 1245 |
+
)
|
| 1246 |
+
|
| 1247 |
+
# Advanced SEO Tools
|
| 1248 |
+
keyword_research_btn.click(
|
| 1249 |
+
fn=generate_keyword_research,
|
| 1250 |
+
inputs=[keyword_topic, api_key_input, language_dropdown, competition_level],
|
| 1251 |
+
outputs=keyword_output
|
| 1252 |
+
)
|
| 1253 |
+
|
| 1254 |
+
content_ideas_btn.click(
|
| 1255 |
+
fn=generate_content_ideas,
|
| 1256 |
+
inputs=[content_ideas_topic, api_key_input, template_dropdown, language_dropdown],
|
| 1257 |
+
outputs=content_ideas_output
|
| 1258 |
+
)
|
| 1259 |
+
|
| 1260 |
+
# Language Settings Management
|
| 1261 |
+
save_lang_btn.click(
|
| 1262 |
+
fn=save_language_settings,
|
| 1263 |
+
inputs=[lang_name, search_engines, localization_tips, keyword_examples, long_tail_patterns, question_keywords],
|
| 1264 |
+
outputs=lang_status
|
| 1265 |
)
|
| 1266 |
|
| 1267 |
+
# Clear Functions
|
| 1268 |
clear_btn.click(
|
| 1269 |
fn=clear_outputs,
|
| 1270 |
+
outputs=[topic_input, seo_output, keyword_output, content_ideas_output]
|
|
|
|
| 1271 |
)
|
| 1272 |
|
| 1273 |
# Footer
|
| 1274 |
gr.Markdown("""
|
| 1275 |
---
|
| 1276 |
+
## π Enhanced Features Overview
|
| 1277 |
+
|
| 1278 |
+
### β¨ What's New:
|
| 1279 |
+
- **6 Organized Sections**: Better UX with logical feature grouping
|
| 1280 |
+
- **HTML Export**: Professional, printable SEO plans
|
| 1281 |
+
- **Custom Templates**: Create and manage your own templates
|
| 1282 |
+
- **Multiple Food Niches**: Fermentation, Baking, Plant-Based, Keto, Mediterranean, Desserts
|
| 1283 |
+
- **Advanced SEO Tools**: Keyword research and content idea generation
|
| 1284 |
+
- **Multi-Language Support**: Optimize for different markets and languages
|
| 1285 |
+
- **Enhanced Metrics**: Technical SEO, performance analysis, and content distribution
|
| 1286 |
|
| 1287 |
+
### π Useful Links:
|
| 1288 |
+
- [Get Gemini API Key](https://aistudio.google.com/)
|
| 1289 |
+
- [Gradio Documentation](https://gradio.app/docs/)
|
| 1290 |
+
- [SEO Best Practices](https://developers.google.com/search/docs)
|
| 1291 |
+
|
| 1292 |
+
### π Privacy & Security:
|
| 1293 |
+
Your API key is stored locally and only used for Google AI services. No data is shared with third parties.
|
| 1294 |
""")
|
| 1295 |
|
| 1296 |
+
# Launch configuration
|
| 1297 |
if __name__ == "__main__":
|
| 1298 |
+
print("π Starting Enhanced SEO Assistant...")
|
| 1299 |
+
print("π Features included:")
|
| 1300 |
+
print(" β
6 organized sections for better UX")
|
| 1301 |
+
print(" β
HTML export functionality")
|
| 1302 |
+
print(" β
Custom template management")
|
| 1303 |
+
print(" β
Multiple food niche templates")
|
| 1304 |
+
print(" β
Advanced SEO tools")
|
| 1305 |
+
print(" β
Multi-language support")
|
| 1306 |
+
print(" β
Enhanced metrics and analysis")
|
| 1307 |
+
|
| 1308 |
app.launch(
|
| 1309 |
share=True,
|
| 1310 |
debug=True,
|
| 1311 |
show_error=True,
|
| 1312 |
+
server_name="0.0.0.0",
|
| 1313 |
server_port=7860,
|
| 1314 |
+
quiet=False
|
| 1315 |
)
|