OpenBlog
Open-source AI-powered blog generation system — 12-stage pipeline for producing high-quality, AEO-optimized articles.
✨ Features
- 🔄 12-Stage Pipeline — Modular, testable stages from data fetch to HTML output
- 🎯 AEO Optimization — Built-in Answer Engine Optimization scoring (70-85+ scores)
- 🔍 Smart Citations — Automatic source validation and formatting
- 📝 Rich Content — FAQ/PAA extraction, internal links, ToC generation
- 🖼️ Image Generation — AI-powered featured images via OpenRouter
- 🌐 Multi-language — Supports multiple languages with auto-detection
- ⚡ Fast — 60-90 second generation time
📋 Pipeline Stages
Stage 0: Data Fetch & Company Detection
Stage 1: Prompt Construction
Stage 2: AI Content Generation (Gemini + tools)
Stage 3: Structured Data Extraction
Stage 4: Citation Validation ─┐
Stage 5: Internal Links │ (parallel)
Stage 6: Table of Contents │
Stage 7: Metadata │
Stage 8: FAQ/PAA Enhancement │
Stage 9: Image Generation ─┘
Stage 10: Cleanup & Validation
Stage 11: HTML Generation & Storage
🚀 Quick Start
Installation
git clone https://github.com/federicodeponte/openblog.git
cd openblog
pip install -r requirements.txt
Environment Variables
# Required
GEMINI_API_KEY=your_gemini_api_key
# Optional - DataForSEO fallback (when Google Search quota exhausted)
# Cost: $0.50 per 1,000 queries - Standard mode (async task-based)
# Automatically activates when Google Search returns 429/quota errors
DATAFORSEO_LOGIN=your_dataforseo_email
DATAFORSEO_PASSWORD=your_dataforseo_password
# Optional - for Google Drive integration
GOOGLE_SERVICE_ACCOUNT_JSON='{"type":"service_account",...}'
GOOGLE_DELEGATION_SUBJECT=user@domain.com
API Usage
# Start the server
uvicorn service.api:app --reload
# Generate a blog
curl -X POST http://localhost:8000/blog/write \
-H "Content-Type: application/json" \
-d '{
"primary_keyword": "AI in customer service",
"company_url": "https://example.com"
}'
Python Usage
from pipeline.core.workflow_engine import WorkflowEngine
from pipeline.core.execution_context import ExecutionContext
engine = WorkflowEngine()
context = ExecutionContext(
job_id="test-123",
job_config={
"primary_keyword": "AI adoption in customer service",
"company_url": "https://example.com",
},
)
result = await engine.execute(context)
print(result.final_article["Headline"])
🏗️ Project Structure
openblog/
├── pipeline/
│ ├── blog_generation/ # 12 stages (stage_00 to stage_11)
│ ├── core/ # Workflow engine, execution context
│ ├── models/ # Data models, AI clients
│ ├── processors/ # HTML, citations, sitemap
│ ├── prompts/ # Prompt templates
│ └── utils/ # AEO scorer, helpers
├── service/
│ ├── api.py # FastAPI endpoints
│ └── image_generator.py # Image generation
├── tests/ # Test suite
├── docs/ # Documentation
├── modal_deploy.py # Modal deployment
└── requirements.txt
📊 Output Quality
- AEO Score: 70-85+ / 100
- Generation Time: 60-90 seconds
- Citation Validation: Automatic URL checking
- HTML Output: Clean, semantic markup
🔧 Deployment
Modal (Recommended)
pip install modal
modal deploy modal_deploy.py
Docker
docker build -t openblog .
docker run -p 8000:8000 openblog
📖 Documentation
🧪 Testing
pytest tests/ -v
pytest tests/stages/test_stage_00.py -v # Test specific stage
📝 License
MIT License - see LICENSE for details.
🤝 Contributing
Contributions welcome! Please read the contributing guidelines before submitting PRs.
Built with ❤️ by SCAILE
Release files for openblog 3.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| openblog-3.0.1.tar.gz | 494.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| openblog-3.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.0 MB
Release files / openblog-3.0.1.tar.gz
| Download URL | openblog-3.0.1.tar.gz |
|---|---|
| Size | 494.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
14282df32c56484bf73a66c5cd724905c10c1a253b1a09f2d4d117f0fa3f0086
|
|
BLAKE2b-256 checksum How to use checksums |
895e8bd7dfed9ad9da76a2b35ccb0d5dc0c4316edb8a278a44d6906fefddb364
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.13
|
Release files / openblog-3.0.1-py3-none-any.whl
| Download URL | openblog-3.0.1-py3-none-any.whl |
|---|---|
| Size | 534.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9eeb22fac56906548c619b8fdf3cbd79ae1c820a47816e13de65791483ab989a
|
|
BLAKE2b-256 checksum How to use checksums |
04bd172be65a7349ba8d1ffb2ed1b61c6912a2dd14c706f8c622c223ce8200ec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.13
|