An AI-powered SEO content engine with a local web UI. Research keywords, generate optimized blog posts with images, update underperforming content using Google Search Console data, and publish directly to your CMS — all from a clean browser interface.
Works with any AI provider and any major CMS platform.
- Local web UI — no SaaS, no subscriptions, runs on your machine
- Multi-platform — WordPress, WooCommerce, Shopify, Wix, MongoDB (blog-poster)
- Any AI provider — Google Gemini, OpenAI, Anthropic Claude, Mistral, DeepSeek
- GSC integration — protect ranking pages, find page-2 opportunities, track performance
- Live pipeline streaming — watch every step in real time, abort anytime, download logs
- Multi-site — manage unlimited sites from one UI, each with its own config
- Posts & Products — browse published content and products with GSC stats on hover
- Pipeline history — every run logged with status, duration, and log preview
- Manual Review Gate — optionally hold generated content in a review queue; edit in the TipTap rich-text editor with AI chat refinement before publishing
- Scheduled Automation — create Daily / Weekly / Monthly / Custom cron schedules per site and mode; runs in-process via APScheduler with per-run log history
Requirements: Python 3.10+, Node.js 18+, Git Bash (Windows) or any Unix shell
git clone https://github.com/Nivnivu/perfect_seo.git
cd perfect_seo
./start.shThe script installs all dependencies, starts the API on port 8000 and the UI on port 5173, and opens your browser automatically.
First time: Go to Sites → Add Site and follow the wizard to configure your first site.
Open http://localhost:5173/sites and click Add Site. The wizard walks you through:
- Choose your CMS platform
- Enter site name, domain, AI provider + API key
- Enter platform credentials
- (Optional) Connect Google Search Console
- Add seed keywords and brand context
- Review and save → creates
config.yoursite.yamlin the project root
Or copy one of the example configs manually:
cp config.example.wordpress.yaml config.mysite.yaml
cp config.example.woocommerce.yaml config.mysite.yaml
cp config.example.shopify.yaml config.mysite.yaml
cp config.example.wix.yaml config.mysite.yaml
cp config.example.mongodb.yaml config.mysite.yaml # blog-poster CMS usersAdd one of these blocks to your config:
gemini:
api_key: "AIza..." # aistudio.google.com/app/apikey
model: "gemini-2.5-flash"
image_model: "imagen-4.0-fast-generate-001"openai:
api_key: "sk-..." # platform.openai.com/api-keys
model: "gpt-4.1"
image_model: "dall-e-3" # optionalanthropic:
api_key: "sk-ant-..." # console.anthropic.com/settings/keys
model: "claude-sonnet-4-6"mistral:
api_key: "..." # console.mistral.ai/api-keys
model: "mistral-large-latest"deepseek:
api_key: "sk-..." # platform.deepseek.com/api_keys
model: "deepseek-chat"Uses the WordPress REST API v2 with an Application Password (no plugins needed).
platform: wordpress
wordpress:
site_url: "https://yourblog.com"
username: "your-wp-username"
app_password: "xxxx xxxx xxxx xxxx xxxx xxxx"How to get an Application Password:
- WordPress Admin → Users → Edit your user
- Scroll to Application Passwords → Enter a name → Add New
- Copy the generated password (shown only once)
platform: woocommerce
woocommerce:
site_url: "https://yourstore.com"
consumer_key: "ck_..."
consumer_secret: "cs_..."How to get API keys:
- WooCommerce → Settings → Advanced → REST API
- Add Key → permissions: Read/Write
- Copy Consumer Key and Consumer Secret
platform: shopify
shopify:
store_domain: "your-store.myshopify.com"
admin_api_token: "shpat_..."How to get an Admin API token:
- Shopify Admin → Settings → Apps → Develop apps
- Enable custom app development → Create an app
- Admin API scopes:
read_content,write_content,read_products,write_products - Install the app → copy the Admin API access token
platform: wix
wix:
api_key: "IST.eyJ..."
site_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"How to get Wix credentials:
- Wix Dev Center → API Keys
- Create a key with Blog and Stores permissions
- Your site ID is in your Wix dashboard URL
For users of the blog-poster open source CMS — a headless blog engine for React, Vue, and Next.js websites.
platform: mongodb
mongodb:
uri: "mongodb+srv://user:pass@cluster.mongodb.net/"
database: "multiBlogDB"
collection: "your_collection"
supabase:
url: "https://xxxx.supabase.co"
key: "your-service-role-key"
bucket: "blog-poster"MongoDB Atlas: Create a free cluster at mongodb.com/atlas → Connect → Drivers → copy the URI.
Supabase: Create a project at supabase.com → Settings → API → copy URL and service_role key. Create a storage bucket named blog-poster (public).
GSC enables: ranking protection, page-2 opportunity detection, CTR optimization, and the Analytics dashboard.
Each user needs their own Google Cloud credentials.
- console.cloud.google.com → New project
- APIs & Services → Library → search Google Search Console API → Enable
- APIs & Services → Credentials → Create Credentials → OAuth 2.0 Client ID
- Application type: Desktop app
- Download the JSON → save to project root as
client_secret_xxx.json
- APIs & Services → OAuth consent screen → User type: External
- Add scope:
https://www.googleapis.com/auth/webmasters.readonly - Add yourself as a Test user
- Keep the app in Testing mode — no Google review needed for personal/team use
search_console:
credentials_file: "client_secret_xxx.json"
token_file: "gsc_token.json"
site_url: "https://yoursite.com/" # must match GSC exactly
protection_thresholds:
min_clicks: 10
min_impressions: 100
max_position: 20.0Open the Analytics tab → click Connect GSC. Sign in with your Google account. The token is saved to gsc_token.json automatically.
| Mode | Description |
|---|---|
new |
Research keywords → generate a new blog post with images |
update |
Find underperforming posts via GSC → rewrite them |
full |
New post + updates + static pages in one run |
static |
Rewrite static pages (homepage, about, etc.) |
images |
Scan all posts, check image quality, generate/replace as needed |
recover |
Restore posts that lost rankings after an update |
diagnose |
Deep SEO audit: indexing, Core Web Vitals, cannibalization |
dedupe |
Detect and fix keyword cannibalization |
impact |
Measure GSC traffic impact of recent updates (before vs after) |
products |
Rewrite WooCommerce/Shopify product pages |
restore_titles |
Restore original URL slugs from update history |
Run from the UI (Pipelines tab) or CLI:
python run.py new --config config.mysite.yaml
python run.py update --config config.mysite.yamlpython run.py new # uses config.yaml (default)
python run.py new --config config.mysite.yaml
python run.py update --config config.mysite.yaml
python run.py full --config config.mysite.yaml# Start everything
docker compose up
# UI still runs locally:
cd ui && npm install && npm run devThe API is available at http://localhost:8000 and the UI at http://localhost:5173.
Config files are mounted from the host — edit them on your machine as normal.
seo-blog-engine/
├── run.py # CLI entry point
├── orchestrator.py # Main pipeline logic (all 11 modes)
├── config.example.*.yaml # Config templates per platform
│
├── api/ # FastAPI backend
│ ├── main.py # lifespan: init_db, load schedules, start APScheduler
│ ├── config_manager.py
│ ├── db.py # SQLite init (pipeline_runs, pending_reviews, schedules, schedule_runs)
│ ├── scheduler.py # APScheduler wrapper
│ └── routes/ # sites, pipelines, gsc, posts, products, history, reviews, schedules
│
├── publishers/ # Platform publisher abstraction
│ ├── base.py # Abstract interface
│ ├── factory.py # get_publisher(config)
│ └── mongodb.py / wordpress.py / woocommerce.py / shopify.py / wix.py
│
├── tools/ # Research & analysis
│ ├── search_console.py # GSC auth, performance, opportunities
│ ├── serp_scraper.py # Google SERP scraping
│ ├── competitor_analyzer.py
│ └── blog_analyzer.py
│
├── generator/ # AI content generation
│ ├── gemini_client.py
│ ├── prompts.py
│ └── refine.py # AI chat refinement for review gate
│
├── publisher/ # MongoDB publishing pipeline (blog-poster)
│ ├── post_publisher.py
│ ├── mongodb_client.py
│ ├── supabase_client.py
│ └── tiptap_converter.py
│
├── ui/ # Vue 3 + Vite frontend
│ └── src/
│ ├── views/ # Dashboard, Sites, Pipelines, Analytics, Posts, Products, History,
│ │ # Schedules, PostReview
│ ├── components/ # AppSidebar, LiveLog, TipTapEditor, AddSiteWizard, wizard/*, ui/*
│ ├── stores/ # Pinia: sites, pipelines, wizard, reviews, schedules
│ └── i18n/ # English + Hebrew translations
│
├── scheduled/ # Gitignored — schedule logs and user bat/sh files
│ └── logs/ # {site}-{mode}.log per schedule run
│
├── Dockerfile
├── docker-compose.yml
└── start.sh # One-command local startup
| Layer | Technology |
|---|---|
| Frontend | Vue 3 + TypeScript + Vite + TailwindCSS |
| UI style | shadcn/ui pattern (CSS variables, orange primary) |
| Rich text editor | TipTap (@tiptap/vue-3, starter-kit, extensions) |
| Charts | Chart.js + vue-chartjs |
| State | Pinia |
| i18n | vue-i18n (English + Hebrew) |
| Backend | FastAPI + uvicorn |
| Streaming | Server-Sent Events (SSE) |
| Scheduling | APScheduler (apscheduler>=3.10.0) |
| Pipeline history | SQLite |
| Config | YAML files per site (gitignored) |
| AI text | Gemini / OpenAI / Claude / Mistral / DeepSeek |
| AI images | Imagen 4 / DALL-E 3 |
| GSC | Google Search Console API v1 (OAuth2 Desktop) |
| Content DB | MongoDB Atlas (blog-poster platform) |
| Image storage | Supabase Storage (blog-poster platform) |
After cloning, the start.sh script handles all dependencies automatically. If installing manually:
pip install -r requirements.txt -r api/requirements.txt # includes apscheduler
cd ui && npm install # includes TipTap packagesFull technical documentation for contributors: DOCS.md
See CONTRIBUTING.md for dev environment setup and PR guidelines.
MIT — see LICENSE.