mroccuper commited on
Commit
9f57a55
Β·
verified Β·
1 Parent(s): 534ba4f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +435 -105
app.py CHANGED
@@ -1,14 +1,17 @@
1
  # -*- coding: utf-8 -*-
2
  """
3
- SEO Blog Generator with Gemini 1.5 Pro API β€” Full Feature Version
4
- Includes: Schema, Title Variations, Readability, HTML/MD Export, Meta Tags, Social Snippets, Alt Text Suggestions
 
5
  """
6
 
 
 
7
  import gradio as gr
8
  import requests
 
 
9
  import re
10
- import json
11
- import textstat
12
  from datetime import datetime
13
 
14
  class BlogGenerator:
@@ -17,112 +20,439 @@ class BlogGenerator:
17
  return re.sub(r'```html|```', '', content).strip()
18
 
19
  @staticmethod
20
- def build_prompt(topic, tone, length, goal):
21
- return f"""
22
- Write a detailed SEO-optimized blog post about "{topic}" in HTML.
23
- Use the tone: {tone}. Target length: {length} words.
24
- Include:
25
- - Metadata (title, description)
26
- - Internal links & extra keywords
27
- - Title variations (5)
28
- - Readability analysis
29
- - Alt text suggestions
30
- - Social media snippets (OpenGraph, Twitter)
31
- - FAQ and HowTo schema if user opts in
32
- """
33
 
34
  @staticmethod
35
- def call_gemini(prompt, api_key):
36
- try:
37
- response = requests.post(
38
- f"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent?key={api_key}",
39
- json={"contents": [{"parts": [{"text": prompt}]}]},
40
- headers={"Content-Type": "application/json"}
41
- )
42
- response.raise_for_status()
43
- return BlogGenerator.clean_output(response.json()["candidates"][0]["content"]["parts"][0]["text"])
44
- except Exception as e:
45
- return f"Error generating content: {e}"
46
-
47
- @staticmethod
48
- def add_schema(html, add_faq, add_howto):
49
- schemas = []
50
- if add_faq:
51
- schemas.append({
52
- "@context": "https://schema.org",
53
- "@type": "FAQPage",
54
- "mainEntity": [
55
- {
56
- "@type": "Question",
57
- "name": "What is fermented garlic?",
58
- "acceptedAnswer": {
59
- "@type": "Answer",
60
- "text": "Fermented garlic is regular garlic that has been aged in a controlled environment..."
61
- }
62
- }
63
- ]
64
- })
65
- if add_howto:
66
- schemas.append({
67
- "@context": "https://schema.org",
68
- "@type": "HowTo",
69
- "name": "How to Ferment Garlic",
70
- "step": [
71
- {"@type": "HowToStep", "name": "Step 1", "text": "Peel the garlic and place in jar."},
72
- {"@type": "HowToStep", "name": "Step 2", "text": "Add saltwater brine and seal."}
73
- ]
74
- })
75
- if schemas:
76
- return html + f"\n<script type='application/ld+json'>{json.dumps(schemas, indent=2)}</script>"
77
- return html
78
-
79
- @staticmethod
80
- def readability_score(html):
81
- text = re.sub('<[^<]+?>', '', html)
82
- score = textstat.flesch_reading_ease(text)
83
- return f"Flesch Reading Ease: {score:.1f}" if score else "N/A"
84
-
85
- @staticmethod
86
- def download_html(content):
87
- filename = f"blog_{datetime.now().strftime('%Y%m%d%H%M%S')}.html"
88
- with open(filename, "w", encoding="utf-8") as f:
89
- f.write(content)
90
- return filename
91
-
92
- # Gradio UI
93
- with gr.Blocks() as app:
94
- gr.Markdown("# πŸ§ͺ SEO Blog Generator (Fermentation Niche, Gemini 1.5 Pro)")
95
 
96
- with gr.Row():
97
- topic = gr.Textbox(label="Blog Topic", placeholder="e.g., How to Ferment Kefir")
98
- api_key = gr.Textbox(label="Gemini API Key", type="password")
99
 
100
- with gr.Row():
101
- tone = gr.Dropdown(["Informative", "Friendly", "Professional", "Playful"], label="Tone", value="Friendly")
102
- length = gr.Slider(300, 3000, step=100, label="Length (words)", value=1200)
103
- goal = gr.Dropdown(["default", "faq", "howto"], label="Goal", value="default")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
  with gr.Row():
106
- add_faq = gr.Checkbox(label="Add FAQ Schema")
107
- add_howto = gr.Checkbox(label="Add HowTo Schema")
108
-
109
- output_html = gr.HTML(label="Generated Blog HTML")
110
- seo_score = gr.Label(label="SEO Score & Readability")
111
- download_file = gr.File(label="Download HTML File")
112
-
113
- def generate_blog(topic, api_key, tone, length, goal, add_faq, add_howto):
114
- prompt = BlogGenerator.build_prompt(topic, tone, int(length), goal)
115
- content = BlogGenerator.call_gemini(prompt, api_key)
116
- full_html = BlogGenerator.add_schema(content, add_faq, add_howto)
117
- score = BlogGenerator.readability_score(full_html)
118
- filename = BlogGenerator.download_html(full_html)
119
- return full_html, f"βœ… SEO Quality OK β€” {score}", filename
120
-
121
- generate_btn = gr.Button("Generate Blog")
122
- generate_btn.click(
123
- fn=generate_blog,
124
- inputs=[topic, api_key, tone, length, goal, add_faq, add_howto],
125
- outputs=[output_html, seo_score, download_file]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  )
127
 
128
- app.launch()
 
1
  # -*- coding: utf-8 -*-
2
  """
3
+ SEO Blog Generator with Gemini 1.5 Pro API
4
+ Enhanced: Internal Links + Extra Keywords + HTML File Download + WordPress Optimization
5
+ New Features: SEO Score, Title Variations, Readability Analysis, Social Media Snippets, Citations, Uniqueness Check
6
  """
7
 
8
+ #pip install -r requirements.txt
9
+
10
  import gradio as gr
11
  import requests
12
+ import markdown2
13
+ import os
14
  import re
 
 
15
  from datetime import datetime
16
 
17
  class BlogGenerator:
 
20
  return re.sub(r'```html|```', '', content).strip()
21
 
22
  @staticmethod
23
+ def call_gemini(prompt, api_key):
24
+ response = requests.post(
25
+ f"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent?key={api_key}",
26
+ json={"contents": [{"parts": [{"text": prompt}]}]},
27
+ headers={"Content-Type": "application/json"}
28
+ )
29
+ return BlogGenerator.clean_output(response.json()["candidates"][0]["content"]["parts"][0]["text"])
 
 
 
 
 
 
30
 
31
  @staticmethod
32
+ def inject_emotional_tone(content, keyword, tone, api_key):
33
+ prompt = f"""
34
+ Enhance the following blog content with contextual emotional tones to make it more engaging for readers:
35
+ - Ensure the emotional tone aligns with the {tone} of the blog.
36
+ - Use emotionally charged language where appropriate to create empathy, excitement, or curiosity.
37
+ - Keep the content natural and easy to read.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
+ Content: {content}
40
+ """
41
+ return BlogGenerator.call_gemini(prompt, api_key)
42
 
43
+ @staticmethod
44
+ def generate_meta(keyword, transcript, api_key):
45
+ prompt = f"""
46
+ Create an SEO-friendly meta title (max 60 chars) and meta description (max 160 chars) for a blog about {keyword}.
47
+ Use this content as reference: {transcript}
48
+ Format:
49
+ Title: ...
50
+ Description: ...
51
+ """
52
+ return BlogGenerator.call_gemini(prompt, api_key)
53
+
54
+ @staticmethod
55
+ def generate_slug_tags(keyword, api_key):
56
+ prompt = f"""
57
+ Suggest a URL-friendly slug and 3-5 relevant blog tags for the topic: {keyword}.
58
+ Format:
59
+ Slug: ...
60
+ Tags: tag1, tag2, tag3...
61
+ """
62
+ return BlogGenerator.call_gemini(prompt, api_key)
63
+
64
+ @staticmethod
65
+ def generate_schema(keyword, api_key):
66
+ prompt = f"""
67
+ Create JSON-LD structured data for an article about {keyword}, including FAQPage and HowTo if applicable.
68
+ """
69
+ return BlogGenerator.call_gemini(prompt, api_key)
70
+
71
+ @staticmethod
72
+ def generate_faq(keyword, api_key):
73
+ prompt = f"""
74
+ Create 3-5 beginner-friendly FAQ questions and answers about {keyword}.
75
+ Requirements:
76
+ - Use question format "Q: [question]"
77
+ - Answer in 2-3 simple sentences
78
+ - Include the keyword naturally
79
+ - Format as HTML with <div class='faq-item'>
80
+ """
81
+ return BlogGenerator.call_gemini(prompt, api_key)
82
+
83
+ @staticmethod
84
+ def generate_step_by_step(keyword, api_key):
85
+ prompt = f"""
86
+ Create a simple step-by-step guide about {keyword} for beginners.
87
+ Format:
88
+ <h2>{keyword}: A Simple Step-by-Step Guide</h2>
89
+ <ul><li>Item 1</li><li>Item 2</li></ul>
90
+ <ol><li><strong>Step 1:</strong> Start by...</li></ol>
91
+ """
92
+ return BlogGenerator.call_gemini(prompt, api_key)
93
+
94
+ @staticmethod
95
+ def generate_blog(transcript, keyword, pov, tone, length, internal_links, extra_keywords, api_key):
96
+ word_count = {
97
+ "Short": "800",
98
+ "Standard": "1500-1700",
99
+ "Long": "2000+"
100
+ }[length]
101
+
102
+ links_formatted = ""
103
+ if internal_links:
104
+ links = internal_links.split("\n")
105
+ links_formatted = "\n".join([f"- <a href='{link.strip()}'>{link.strip()}</a>" for link in links if link.strip()])
106
+
107
+ extra_keywords_list = ""
108
+ if extra_keywords:
109
+ keywords = extra_keywords.split("\n")
110
+ extra_keywords_list = ", ".join([kw.strip() for kw in keywords if kw.strip()])
111
+
112
+ prompt = f"""
113
+ Create an SEO-optimized beginner-friendly blog post about: {keyword}
114
+ Transcript: {transcript}
115
+ Requirements:
116
+ - POV: {pov}, Tone: {tone}
117
+ - Word Count: {word_count} words
118
+ - Structure:
119
+ - Engaging title with keyword
120
+ - First sentence as SEO meta description (max 160 chars)
121
+ - Short intro (~100 words)
122
+ - 3-5 H2 sections with bullet points and practical advice
123
+ - Short paragraphs (2-3 sentences)
124
+ - Keyword density ~1-2%
125
+ - HTML format only with WordPress Gutenberg compatibility
126
+ {f"- Naturally include these internal links: {links_formatted}" if links_formatted else ""}
127
+ {f"- Sprinkle naturally these extra keywords: {extra_keywords_list}" if extra_keywords_list else ""}
128
+ """
129
+ return BlogGenerator.call_gemini(prompt, api_key)
130
+
131
+ @staticmethod
132
+ def generate_image_alt_text(content, api_key):
133
+ prompt = f"""
134
+ Analyze the following blog content and suggest alt text for any images. The alt text should be descriptive, relevant to the content, and SEO-optimized.
135
+
136
+ Content: {content}
137
+ """
138
+ return BlogGenerator.call_gemini(prompt, api_key)
139
+
140
+ # New Feature: Content Optimization Score
141
+ @staticmethod
142
+ def analyze_seo_score(content, keyword, api_key):
143
+ prompt = f"""
144
+ Analyze this blog content for SEO quality and provide a score from 0-100:
145
+ Keyword: {keyword}
146
+ Content: {content}
147
+ Provide a breakdown with these components:
148
+ - Keyword density score (0-20)
149
+ - Readability score (0-20)
150
+ - Structure score (0-20)
151
+ - Meta data score (0-20)
152
+ - Internal linking score (0-20)
153
+ Format:
154
+ Overall Score: XX/100
155
+ Keyword Density: XX/20 (explanation)
156
+ Readability: XX/20 (explanation)
157
+ Structure: XX/20 (explanation)
158
+ Meta Data: XX/20 (explanation)
159
+ Internal Linking: XX/20 (explanation)
160
+ Top 3 Improvement Suggestions:
161
+ 1. ...
162
+ 2. ...
163
+ 3. ...
164
+ """
165
+ return BlogGenerator.call_gemini(prompt, api_key)
166
+
167
+ # New Feature: Title Variations
168
+ @staticmethod
169
+ def generate_title_variations(keyword, transcript, api_key):
170
+ prompt = f"""
171
+ Generate 5 engaging and SEO-friendly title variations for a blog post about "{keyword}".
172
+ Use this content as reference: {transcript[:500]}
173
+ Requirements:
174
+ - Include the keyword naturally
175
+ - Keep each title under 60 characters
176
+ - Use a mix of question, how-to, and list-based titles
177
+ - Add emotional triggers where appropriate
178
+ - Ensure WordPress compatibility
179
+ Format:
180
+ 1. [Title 1]
181
+ 2. [Title 2]
182
+ 3. [Title 3]
183
+ 4. [Title 4]
184
+ 5. [Title 5]
185
+ """
186
+ return BlogGenerator.call_gemini(prompt, api_key)
187
+
188
+ # New Feature: Readability Analysis
189
+ @staticmethod
190
+ def analyze_readability(content, api_key):
191
+ prompt = f"""
192
+ Analyze the readability of this blog content:
193
+ {content[:2000]}...
194
+ Provide:
195
+ 1. Estimated Flesch-Kincaid reading level
196
+ 2. Average words per sentence
197
+ 3. Percentage of complex words
198
+ 4. Passive voice percentage
199
+ 5. Overall readability score (0-100)
200
+ Specific suggestions to improve:
201
+ - 3 sentences that could be simplified
202
+ - Words that could be replaced with simpler alternatives
203
+ - Structure improvements for WordPress readability
204
+ """
205
+ return BlogGenerator.call_gemini(prompt, api_key)
206
+
207
+ # New Feature: Social Media Snippets
208
+ @staticmethod
209
+ def generate_social_snippets(content, keyword, api_key):
210
+ prompt = f"""
211
+ Create social media post snippets promoting a blog about "{keyword}" for:
212
+ 1. Twitter/X (max 280 chars, include hashtags)
213
+ 2. Facebook (100-250 words with call to action)
214
+ 3. LinkedIn (professional tone, 150-250 words)
215
+ 4. Instagram (caption with relevant hashtags)
216
+ 5. Pinterest (short description with SEO keywords)
217
+ Reference content:
218
+ {content[:1000]}...
219
+ Format each snippet ready for copy-paste into WordPress social sharing plugins.
220
+ Include emojis where appropriate.
221
+ """
222
+ return BlogGenerator.call_gemini(prompt, api_key)
223
+
224
+ # New Feature: Citation Generator
225
+ @staticmethod
226
+ def generate_citations(keyword, api_key):
227
+ prompt = f"""
228
+ Generate 5 relevant citation sources for a blog about "{keyword}".
229
+ For each source provide:
230
+ 1. Author name(s)
231
+ 2. Publication title
232
+ 3. Publication date (within last 2 years)
233
+ 4. URL
234
+ 5. Brief description of why this source is valuable
235
+ 6. A formatted citation in APA style
236
+ Focus on authoritative sources like:
237
+ - Peer-reviewed journals
238
+ - Government publications
239
+ - Industry reports
240
+ - Expert blogs with high domain authority
241
+ Format in HTML ready for WordPress insertion.
242
+ """
243
+ return BlogGenerator.call_gemini(prompt, api_key)
244
+
245
+ # New Feature: Content Uniqueness Check
246
+ @staticmethod
247
+ def check_uniqueness(content, api_key):
248
+ prompt = f"""
249
+ Analyze this content for potential plagiarism or duplicate content issues:
250
+ {content[:3000]}...
251
+ Provide:
252
+ 1. Uniqueness score (estimated percentage of original content)
253
+ 2. Highlight 3-5 phrases that might be common or potentially duplicative
254
+ 3. Suggestions to make the content more unique
255
+ 4. WordPress-specific recommendations for avoiding duplicate content penalties
256
+ Note: This is an AI-based estimation and not a replacement for professional plagiarism detection tools.
257
+ """
258
+ return BlogGenerator.call_gemini(prompt, api_key)
259
+
260
+ # New Feature: WordPress Optimization # #5. Add Yoast SEO compatible meta tags 2. Add <!-- wp:paragraph --> tags where appropriate 6. Add jump links for table of contents
261
+
262
+ @staticmethod
263
+ def format_for_wordpress(content, keyword, api_key):
264
+ prompt = f"""
265
+ Optimize this HTML content for WordPress:
266
+ {content}
267
+ Make these WordPress-specific adjustments:
268
+ 1. Format headings with proper Gutenberg compatibility
269
+ 2. Optimize image placeholders with WordPress figure blocks
270
+ 3. Format lists for proper WordPress display
271
+ 4. Ensure responsive design elements
272
+ Keep the keyword "{keyword}" optimized throughout.
273
+ """
274
+ return BlogGenerator.call_gemini(prompt, api_key)
275
+
276
+ def process_input(transcript, keyword, pov, tone, length, internal_links, extra_keywords, api_key,
277
+ enable_wp_format, enable_title_variations, enable_seo_score, enable_readability,
278
+ enable_social_snippets, enable_citations, enable_uniqueness, enable_emotional_tone):
279
+ if not api_key:
280
+ return "⚠️ Please enter your Gemini API key", "", None
281
+
282
+ results = {}
283
+
284
+ # Generate main blog content
285
+ main_blog = BlogGenerator.generate_blog(transcript, keyword, pov, tone, length, internal_links, extra_keywords, api_key)
286
+
287
+ # Inject emotional tone if enabled
288
+ if enable_emotional_tone:
289
+ main_blog = BlogGenerator.inject_emotional_tone(main_blog, keyword, tone, api_key)
290
+
291
+ results["main_blog"] = main_blog
292
+
293
+ # Generate standard components
294
+ results["faq_section"] = BlogGenerator.generate_faq(keyword, api_key)
295
+ results["steps_section"] = BlogGenerator.generate_step_by_step(keyword, api_key)
296
+ results["meta_data"] = BlogGenerator.generate_meta(keyword, transcript, api_key)
297
+ results["slug_tags"] = BlogGenerator.generate_slug_tags(keyword, api_key)
298
+
299
+ # Generate optional components based on user selection
300
+ if enable_wp_format:
301
+ results["wp_formatted"] = BlogGenerator.format_for_wordpress(main_blog, keyword, api_key)
302
+
303
+ if enable_title_variations:
304
+ results["title_variations"] = BlogGenerator.generate_title_variations(keyword, transcript, api_key)
305
+
306
+ if enable_seo_score:
307
+ results["seo_score"] = BlogGenerator.analyze_seo_score(main_blog, keyword, api_key)
308
+
309
+ if enable_readability:
310
+ results["readability"] = BlogGenerator.analyze_readability(main_blog, api_key)
311
+
312
+ if enable_social_snippets:
313
+ results["social_snippets"] = BlogGenerator.generate_social_snippets(main_blog, keyword, api_key)
314
+
315
+ if enable_citations:
316
+ results["citations"] = BlogGenerator.generate_citations(keyword, api_key)
317
+
318
+ if enable_uniqueness:
319
+ results["uniqueness"] = BlogGenerator.check_uniqueness(main_blog, api_key)
320
+
321
+ # Generate image alt text suggestions
322
+ image_alt_text = BlogGenerator.generate_image_alt_text(main_blog, api_key)
323
+ results["image_alt_text"] = image_alt_text
324
+
325
+ # Compile the final output
326
+ final_output = f"""
327
+ {results.get('wp_formatted', results['main_blog'])}
328
+ {results['steps_section']}
329
+ <h2>Common Questions About {keyword}</h2>
330
+ {results['faq_section']}
331
+ <hr>
332
+ <h2>πŸ”Ž SEO Metadata</h2>
333
+ <pre>{results['meta_data']}</pre>
334
+ <h2>πŸ”— URL Slug & Tags</h2>
335
+ <pre>{results['slug_tags']}</pre>
336
+ """
337
+
338
+ # Add optional components to output
339
+ if enable_title_variations:
340
+ final_output += f"""
341
+ <h2>πŸ“ Title Variations</h2>
342
+ <pre>{results['title_variations']}</pre>
343
+ """
344
+
345
+ if enable_seo_score:
346
+ final_output += f"""
347
+ <h2>πŸ“Š SEO Score Analysis</h2>
348
+ <pre>{results['seo_score']}</pre>
349
+ """
350
+
351
+ if enable_readability:
352
+ final_output += f"""
353
+ <h2>πŸ“– Readability Analysis</h2>
354
+ <pre>{results['readability']}</pre>
355
+ """
356
+
357
+ if enable_social_snippets:
358
+ final_output += f"""
359
+ <h2>πŸ“± Social Media Snippets</h2>
360
+ <div class="social-snippets">
361
+ {results['social_snippets']}
362
+ </div>
363
+ """
364
+
365
+ if enable_citations:
366
+ final_output += f"""
367
+ <h2>πŸ“š Citations & References</h2>
368
+ <div class="citations">
369
+ {results['citations']}
370
+ </div>
371
+ """
372
+
373
+ if enable_uniqueness:
374
+ final_output += f"""
375
+ <h2>πŸ” Content Uniqueness Analysis</h2>
376
+ <pre>{results['uniqueness']}</pre>
377
+ """
378
+
379
+ final_output += f"""
380
+ <h2>πŸ–ΌοΈ Image Alt Text Suggestions</h2>
381
+ <pre>{results['image_alt_text']}</pre>
382
+ """
383
+
384
+ # Generate file
385
+ filename = f"{keyword.replace(' ', '_')}_{datetime.now().strftime('%Y%m%d%H%M%S')}.html"
386
+ filepath = os.path.join("/tmp", filename)
387
+ with open(filepath, "w", encoding="utf-8") as f:
388
+ f.write(final_output)
389
+
390
+ return final_output, markdown2.markdown(final_output), filepath
391
+
392
+ # UI Implementation with new features
393
+ with gr.Blocks(theme=gr.themes.Soft(), title="Enhanced SEO Blog Generator for WordPress") as app:
394
+ gr.Markdown("""
395
+ # πŸš€ Enhanced SEO Blog Generator for WordPress
396
+ Generate SEO-optimized content with advanced features including WordPress compatibility!
397
+ """)
398
 
399
  with gr.Row():
400
+ with gr.Column():
401
+ api_key = gr.Textbox(label="Gemini API Key", type="password", placeholder="Enter your API key")
402
+ keyword = gr.Textbox(label="Primary Keyword", placeholder="e.g., 'sourdough bread'")
403
+ pov = gr.Radio(label="Point of View", choices=["First Person", "Second Person", "Third Person"], value="Second Person")
404
+ tone = gr.Dropdown(
405
+ label="Blog Tone",
406
+ choices=["Neutral", "Engaging", "Professional", "Informative", "News", "Promotional", "Conversational", "Storytelling", "Educational", "How-to", "Review", "Humorous", "Casual", "Inspirational"],
407
+ value="Engaging"
408
+ )
409
+ length = gr.Radio(label="Content Length", choices=["Short", "Standard", "Long"], value="Standard")
410
+ transcript = gr.Textbox(label="Transcript/Notes", lines=6, placeholder="Paste your reference content...")
411
+ internal_links = gr.Textbox(label="Internal Links (one URL per line)", lines=4, placeholder="https://yourblog.com/article1\nhttps://yourblog.com/article2")
412
+ extra_keywords = gr.Textbox(label="Extra Keywords (one per line)", lines=4, placeholder="kefir health benefits\nhomemade kefir tips")
413
+
414
+ gr.Markdown("### πŸ†• Advanced Features")
415
+ with gr.Row():
416
+ with gr.Column():
417
+ enable_wp_format = gr.Checkbox(label="WordPress Formatting", value=True)
418
+ enable_title_variations = gr.Checkbox(label="Title Variations", value=True)
419
+ enable_seo_score = gr.Checkbox(label="SEO Score Analysis", value=True)
420
+ enable_readability = gr.Checkbox(label="Readability Analysis", value=True)
421
+ with gr.Column():
422
+ enable_social_snippets = gr.Checkbox(label="Social Media Snippets", value=True)
423
+ enable_citations = gr.Checkbox(label="Citations & References", value=True)
424
+ enable_uniqueness = gr.Checkbox(label="Content Uniqueness Check", value=True)
425
+ enable_emotional_tone = gr.Checkbox(label="Emotional Tone Injection", value=True)
426
+
427
+ btn = gr.Button("Generate WordPress-Ready Blog", variant="primary")
428
+
429
+ with gr.Column():
430
+ tabs = gr.Tabs()
431
+ with tabs:
432
+ with gr.TabItem("Preview"):
433
+ html_output = gr.HTML(label="Full SEO Article Preview")
434
+ with gr.TabItem("Markdown"):
435
+ md_output = gr.Code(label="Markdown Version", language="markdown")
436
+ with gr.TabItem("Download"):
437
+ file_output = gr.File(label="⬇️ Download HTML File")
438
+ gr.Markdown("""
439
+ ### WordPress Import Instructions
440
+ 1. Download the HTML file
441
+ 2. In WordPress, create a new post
442
+ 3. Click the three dots in the top-right and select "Code Editor"
443
+ 4. Paste the HTML content
444
+ 5. Switch back to "Visual Editor" to make any final adjustments
445
+ 6. Update your meta data using Yoast or other SEO plugins
446
+ """)
447
+
448
+ btn.click(
449
+ fn=process_input,
450
+ inputs=[
451
+ transcript, keyword, pov, tone, length, internal_links, extra_keywords, api_key,
452
+ enable_wp_format, enable_title_variations, enable_seo_score, enable_readability,
453
+ enable_social_snippets, enable_citations, enable_uniqueness, enable_emotional_tone
454
+ ],
455
+ outputs=[html_output, md_output, file_output]
456
  )
457
 
458
+ app.launch(share=True)