TSE Content Generator
Autonomous SEO content generation system for WordPress — idempotent FSM pipeline, Action Scheduler async orchestration, a Mistral LLM client with multi-key failover, and a fault-tolerant multi-provider image layer.
by Dmitry Duyunov · github.com/dimmer1981/tse-content-generator · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/dimmer1981/tse-content-generator/archive/refs/heads/main.zipReadme
TSE Content Generator
Autonomous SEO content generation system for WordPress, built on an idempotent finite-state-machine pipeline, asynchronous job orchestration, and a fault-tolerant multi-provider AI layer.
TSE Content Generator turns a queue of keywords into fully assembled, illustrated, internally-linked WordPress articles — end to end and unattended. Every article advances through a persisted state machine, every heavy operation runs asynchronously, and every step is idempotent and resume-safe, so the system can survive crashes, timeouts and provider outages without producing duplicates or runaway API spend.
This repository is a portfolio/reference implementation showcasing backend architecture in a real WordPress plugin. API credentials are never stored in code — they are configured in the WordPress admin and resolved at runtime.
Engineering highlights
- Finite-state-machine pipeline. Each task is a row in
wp_tse_taskswhose lifecycle is governed by an explicit state machine with validated transitions — no implicit status changes, no ambiguous in-between states. - Asynchronous, idempotent orchestration. All AI calls, image generation, similarity checks and housekeeping run through Action Scheduler. Jobs are designed to be re-runnable: a retried or duplicated job converges to the same result.
- Deterministic retries. Retry paths contain no randomness. Temperature, back-off and attempt bumps are computed deterministically, so failures are reproducible and debuggable.
- Fault tolerance. The Mistral client implements multi-key failover with an explicit fatal-vs-transient error taxonomy, and the image layer falls back across providers on failure. The infrastructure layer provides reusable resilience primitives — a per-service circuit breaker (closed → open → half-open), a rate limiter, and a named mutex for critical sections shared across concurrent workers.
- Multi-provider AI abstraction. Image generation fans out across 10+ providers behind a single
ImageProviderInterface, with aProviderManagerhandling fallback and aQuotaTrackerenforcing per-provider budgets. - Layered, dependency-light design. A pragmatic DDD-style separation —
Domain,Actions,Infra,Security,Support,Contracts— with PSR-4 autoloading,declare(strict_types=1)everywhere, and no framework beyond WordPress itself. - Security by default. Capability checks and nonces on every privileged entry point, prepared statements for all SQL, output escaping, and authenticated at-rest encryption (libsodium) for stored secrets.
Pipeline
A task moves through six states, each handled by a dedicated, resumable step:
planning ──► chunking ──► assemble ──► image ──► similarity ──► finished
│
└────────────────────► failed / paused ◄────────────────────────
| State | Responsibility |
|---|---|
planning |
Lock the next keyword, derive an outline and per-section image prompts |
chunking |
Generate the article section by section with anti-drift, deterministic prompts |
assemble |
Compose final HTML, insert internal links and structure |
image |
Generate hero + inline images via the multi-provider layer, attach to media |
similarity |
SimHash-based internal de-duplication to keep the site corpus unique |
finished |
Dosed publishing (or scheduled draft) with full audit trail |
Feature set
- Keyword engine — research and expansion (alphabet-soup generation, SERP/suggest APIs, scoring, lemmatization), quarantine of duplicates, and atomic keyword locking to prevent two workers picking the same keyword.
- Content generation — section-wise generation against a Mistral LLM, configurable system prompt, internal linking, and SimHash similarity guarding corpus uniqueness.
- Image generation — featured + inline images, SEO-aware count, optimized prompts, and a provider fan-out (Mistral/Flux, Fal.ai, Cloudflare, Bytez, Stable Horde, Pexels, Pixabay, Unsplash, and more) with an optional Cloudflare Worker proxy.
- Operations — diagnostics page, structured component logs, statistics, auto-purge of stale tasks, and Action Scheduler health checks surfaced as admin notices.
Project structure
src/
├── Actions/ # Action Scheduler entry points & FSM step handlers
│ └── Handlers/ # Outline · Chunking · Image · Generation
├── Admin/ # Admin pages, list tables, notices
├── Contracts/ # Interfaces (Logger, Lock)
├── Database/ # Schema, migrations, keyword storage
├── Domain/
│ ├── Content/ # Generator, PromptBuilder, InternalLinker, SimilarityChecker
│ ├── Images/ # Multi-provider image generation + Providers/
│ ├── Keywords/ # Keyword domain services
│ ├── Orchestrator/ # Pipeline orchestration
│ ├── Publishing/ # Publisher, DraftScheduler
│ ├── Services/ # MediaProcessor, AutoPurge
│ ├── Stats/ # Statistics
│ └── Tasks/ # TaskManager, Planner, TaskStatus (the FSM)
├── Features/
│ └── AutoKeywords/ # Keyword research pipeline
├── Infra/ # Action Scheduler, Mistral client, CircuitBreaker, RateLimiter, Lock, Logger
├── Security/ # Capabilities, Nonces, Crypto (at-rest secret encryption)
└── Support/ # Strings, Time, Arrays, Json utilities
cloudflare-worker/ # Optional edge proxy for image providers
Tech stack
- PHP 8.0+,
strict_types, PSR-4 autoloading via Composer - WordPress 6.2+ plugin APIs, Action Scheduler for async jobs
- Mistral AI as the LLM provider; pluggable image providers
- libsodium for at-rest secret encryption
- Static analysis with PHPStan, coding standards via PHP_CodeSniffer / WPCS
Installation (development)
git clone https://github.com/Dimmer1981/tse-content-generator.git
cd tse-content-generator
composer install
Symlink or copy the directory into wp-content/plugins/, activate it, then configure the API keys and options on the plugin's Settings page. Database tables are created automatically on activation.
Configuration & secrets. All provider credentials (Mistral, image providers) are entered in the WordPress admin and stored as options — they are never committed to the repository.
License
MIT © 2026 Dmitry Duyunov
Author
Dmitry Duyunov — Senior PHP / Backend Engineer LinkedIn · GitHub