A backend service that generates SEO-optimized articles using an intelligent agent. The system analyzes search results, extracts topics and keywords, builds a structured outline, and produces publish-ready content with proper heading hierarchy, SEO metadata, and linking suggestions.
flowchart TB
Client[Client] <--> FastAPI[FastAPI Server]
FastAPI <--> JobManager[Job Manager]
JobManager <--> SQLite[(SQLite DB)]
JobManager --> Worker[Background Worker]
Worker --> SERP[SERP Service]
Worker --> Analyzer[Analyzer Service]
Worker --> OutlineGen[Outline Generator]
Worker --> ContentGen[Content Generator]
Worker --> QualityScorer[Quality Scorer]
The Job Manager creates and tracks jobs, persisting state to SQLite. A background worker processes pending jobs step-by-step (SERP fetch → analysis → outline → content → scoring), updating the job after each step. If the process crashes, the worker resumes incomplete jobs from the last completed step.
- Python 3.10+
# Create and activate a virtual environment
python -m venv venv
# Windows (PowerShell)
.\venv\Scripts\Activate.ps1
# macOS/Linux
source venv/bin/activate
# Install dependencies
pip install -r requirements.txtuvicorn app.main:app --reload --host 0.0.0.0 --port 8000The API will be available at http://localhost:8000. Interactive API docs are at http://localhost:8000/docs.
{
"topic": "best productivity tools for remote teams",
"target_word_count": 1500,
"language": "en"
}Response
{
"job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "pending"
}Request (GET /status/{job_id})
GET /status/a1b2c3d4-e5f6-7890-abcd-ef1234567890
Response (when completed)
{
"job_id": "65f5a44f-5b1a-4bf6-999b-eef7fe941cd1",
"status": "completed",
"article": {
"content": "<h1>Best Productivity Tools For Remote Teams</h1><p>Are you looking for the best best productivity tools for remote teams? In this comprehensive guide, we explore the top best solutions that can transform your workflow. Whether you need remote, productivity, top, guide, help, we've got you covered.</p><h2>Guide</h2><p>Key point about guide. Here we discuss relevant aspects and include the keyword 'best' naturally.</p><h3>Subpoint 1 for guide</h3><p>Details about Subpoint 1 for guide that incorporate secondary keywords.</p><h3>Subpoint 2 for guide</h3><p>Details about Subpoint 2 for guide that incorporate secondary keywords.</p><h2>Tools</h2><p>Key point about tools. Here we discuss relevant aspects and include the keyword 'best' naturally.</p><h3>Subpoint 1 for tools</h3><p>Details about Subpoint 1 for tools that incorporate secondary keywords.</p><h3>Subpoint 2 for tools</h3><p>Details about Subpoint 2 for tools that incorporate secondary keywords.</p><h2>How To</h2><p>Key point about how to. Here we discuss relevant aspects and include the keyword 'best' naturally.</p><h3>Subpoint 1 for how to</h3><p>Details about Subpoint 1 for how to that incorporate secondary keywords.</p><h3>Subpoint 2 for how to</h3><p>Details about Subpoint 2 for how to that incorporate secondary keywords.</p><h2>Best Practices</h2><p>Key point about best practices. Here we discuss relevant aspects and include the keyword 'best' naturally.</p><h3>Subpoint 1 for best practices</h3><p>Details about Subpoint 1 for best practices that incorporate secondary keywords.</p><h3>Subpoint 2 for best practices</h3><p>Details about Subpoint 2 for best practices that incorporate secondary keywords.</p><h2>Conclusion</h2><p>Choosing the right best productivity tools for remote teams depends on your specific needs. We hope this guide helped you understand the landscape and make an informed decision.</p>",
"outline": {
"h1": "Best Productivity Tools For Remote Teams",
"sections": [
{
"heading": "Guide",
"subheadings": [
"Subpoint 1 for guide",
"Subpoint 2 for guide"
],
"key_points": [
"Key point about guide"
]
},
{
"heading": "Tools",
"subheadings": [
"Subpoint 1 for tools",
"Subpoint 2 for tools"
],
"key_points": [
"Key point about tools"
]
},
{
"heading": "How To",
"subheadings": [
"Subpoint 1 for how to",
"Subpoint 2 for how to"
],
"key_points": [
"Key point about how to"
]
},
{
"heading": "Best Practices",
"subheadings": [
"Subpoint 1 for best practices",
"Subpoint 2 for best practices"
],
"key_points": [
"Key point about best practices"
]
}
],
"faq_questions": []
},
"seo_data": {
"title_tag": "best productivity tools for remote teams: The Ultimate Guide for 2025",
"meta_description": "Discover the best best productivity tools for remote teams tools and strategies. Our expert guide covers remote, productivity, top, guide, help.",
"primary_keyword": "best",
"secondary_keywords": [
"remote",
"productivity",
"top",
"guide",
"help"
]
},
"internal_links": [
{
"anchor_text": "keyword research tools",
"target_topic": "SEO keyword research tools",
"suggested_url": null
},
{
"anchor_text": "content optimization checklist",
"target_topic": "content optimization checklist",
"suggested_url": null
},
{
"anchor_text": "remote team collaboration",
"target_topic": "remote team best practices",
"suggested_url": null
}
],
"external_links": [
{
"url": "https://www.forbes.com/...",
"title": "Forbes: Future of Remote Work",
"placement_context": "introduction when discussing trends"
},
{
"url": "https://www.gartner.com/...",
"title": "Gartner Report on Productivity",
"placement_context": "benefits section"
}
],
"faq": []
},
"error": null
}# Create a job
curl -X POST http://localhost:8000/generate \
-H "Content-Type: application/json" \
-d '{"topic": "best productivity tools", "target_word_count": 1500}'
# Check status (replace JOB_ID with the returned job_id)
curl http://localhost:8000/status/JOB_ID| Area | Decision | Rationale |
|---|---|---|
| Modular services | SERP, Analyzer, Outline, Content, and Quality each live in their own stateless class | Single responsibility, easy to swap (e.g. real SERP API) or add (e.g. LLM) without touching the pipeline. |
| Job-based architecture | Async worker processes jobs step-by-step, persisting after each step | Supports durability and resume: if the process crashes, the worker re-queues incomplete jobs and resumes from the last completed step. |
| SQLite + JSON columns | Job state stored in SQLite; serp_data, outline, article as JSON |
Simple setup and storage for a demo, while keeping structured data. Production would use PostgreSQL and a task queue (e.g. Celery). |
| Mocked SERP and content | SERP returns mock results; content is template-based | No external API keys, runs offline. Replacing these with SerpAPI/DataForSEO and an LLM is straightforward. |
| Quality scorer + revision loop | Draft scored for SEO; low scores trigger up to 2 regeneration attempts | Ensures basic SEO constraints (primary keyword in intro, H1, H2 count, word count) before marking the job completed. |
Unit and integration tests validate the pipeline and SEO rules.
# Activate venv first, then:
python -m pytest tests/ -v| Test File | Coverage |
|---|---|
test_analyzer.py |
Keyword and topic extraction from SERP data |
test_serp.py |
Mock SERP returns 10 results and varies by topic |
test_outline.py |
Outline structure (h1, sections, FAQ) and fallback topics |
test_content.py |
Article structure (H1, H2s, SEO metadata, internal/external links) |
test_quality_scorer.py |
Scoring logic for primary keyword, H1, H2 count, and word count |
test_integration.py |
Full flow: create job → poll until completed → assert article structure |
$ python -m pytest tests/ -v
tests/test_analyzer.py::test_analyzer_service PASSED [ 10%]
tests/test_content.py::test_content_has_h1_and_h2s PASSED [ 20%]
tests/test_integration.py::test_generate_and_poll PASSED [ 30%]
tests/test_outline.py::test_outline_has_structure PASSED [ 40%]
tests/test_outline.py::test_outline_fallback_topics PASSED [ 50%]
tests/test_quality_scorer.py::test_quality_scorer_high_score PASSED [ 60%]
tests/test_quality_scorer.py::test_quality_scorer_missing_keyword PASSED [ 70%]
tests/test_quality_scorer.py::test_quality_scorer_missing_h1 PASSED [ 80%]
tests/test_serp.py::test_serp_returns_10_results PASSED [ 90%]
tests/test_serp.py::test_serp_varies_by_topic PASSED [100%]

