Blog Automation Engine

One 86-node pipeline that researches, writes, illustrates and publishes a post for every client site on its own schedule — with a claim gate, a quality gate and a bounded retry.

Client
EpsolDev
Category
Automation Engineering
Completed
2026-08-15
Built with
n8n, Google Vertex AI, REST API, WordPress
Topics
API Development, Automation, CMS
Blog Automation Engine

n8n 86 nodes Multi-tenant Runs every 6 hours

One workflow researches, writes, illustrates and publishes a blog post — for every client site on the platform, on each site's own schedule. It is the content engine behind Custom Blog Management.

The publish half of the pipeline: image generation, media upload, post assembly, publish verification and the run log

Every image on this page is the running instance. Client domains and endpoint URLs are blurred — the architecture is the subject, not whose site it publishes to.


What it replaced

The same automation instance still holds six archived per-site blog workflows. That was the old shape: one client, one copy of the graph. A prompt improvement meant editing it six times, and the sixth copy was always the one that got missed.

This workflow is that graph written once and made tenant-aware. Onboarding a site is a configuration row. There is no seventh copy to drift.

Per-site workflowsThis pipeline
Adding a clientduplicate ~80 nodesone config row
Improving a promptedit every copyedit once
Scheduleone trigger per siteone trigger, per-site due check
A site failingthat copy is brokenthat iteration is logged, the rest continue

How a run flows

Two entry points feed the same body — a 6-hourly schedule for normal operation, and a webhook for "publish this one site now".

Schedule ─┐
          ├─> Config ─> Dispatch ─┬─> one site        (webhook)
Webhook  ─┘                       └─> sites_list      (scheduled)
                                        │
                                        v
                                  Loop Over Sites   due? ─> claim ─> generate ───┘
                                                    publish, log

Every terminal branch — success, duplicate title, quality failure, missing topic, bad credentials — routes back into Loop Over Sites. One site failing can never end the run for the others.


The five decisions that make it survivable

1. A claim gate, because schedules overlap

Before any generation, the run calls back to the platform to claim that site:

CBM Claim Run  ->  Claim Gate  ->  Claim Granted?
                                     │
                        false ───────┴──> back to the loop, silently

A 6-hour schedule and a manual webhook can fire within seconds of each other. Without the claim, both would spend a model call and publish two posts. The claim is a distributed lock held by the platform, not by the automation — so it holds even across a restart.

2. Every model call has two implementations

Research, title generation, body writing, title repair and image generation each sit behind a Use HTTP …? switch:

BranchNodeWhy it exists
falseplatform-native Vertex AI nodeconvenient, credential-managed, typed
trueplain HTTP requestprovider-agnostic — routes to whatever the control plane picks

This is a seam, not indecision The native node binds the graph to one vendor's credential model. The HTTP path lets the same workflow run against a different provider without a rewire — the control plane decides, the graph obeys. Five generative steps, five seams.

3. Duplicate titles loop back with exclusions

A generated title is checked against what the site already published:

  • Pick Title → CBM Dup Check → Dup Gate
  • not a duplicate → carry on to the body
  • duplicate, retries left → Add Exclusions re-enters title generation with the rejected titles attached to the prompt
  • duplicate, retries exhausted → skip this site this cycle

The retry is not the same call again. It is a narrower call — the model is told what not to say.

4. A quality gate with a bounded retry and a logged give-up

Parse Blog -> Quality Gate -> Quality Failed?
                                  │
            true -> Gen Retry Available? -> Mark Gen Retry -> rewrite
                                         └> Mark Gen Failed -> log -> next site

The give-up path is not a dead end: it writes the failure back to the platform (CBM Log Gen Failure) and then restores the loop item so iteration continues cleanly. A short or malformed draft is never published to make the graph look successful.

5. Images are optional at two independent points

A hero image and an in-content image are separately gated. Either can be disabled per site, and either can fail — and the post still publishes:

Image Gate → generate → Have Image? → upload → attach hero Content Image Gate → generate → Have Content Image? → upload → insert

Both gates have an explicit skip node (Mark Image Disabled, Mark Content Image Skipped) that rejoins the publish path. An image service outage degrades the post, it does not stop it.


Publishing and proof

Assemble Post → CBM Publish → Verify Publish → Build Run Log → CBM Run Log

Publication is verified, not assumed — the response is re-read before the run is recorded as successful. Every cycle writes a run log back to the platform, so the answer to "did the Tuesday 06:00 run do anything?" is a row, not a guess.


When it breaks

The shared alert workflow: an error trigger that posts the failure straight back into the platform

Two nodes, and it is the reason nobody watches a dashboard. n8n's error trigger fires on any unhandled failure in a linked workflow, and the handler posts the failure into the platform's own alert log — the same place operational alerts already live.

Handled failures are logged inline by the pipeline itself. This catches everything else.


Stack

n8n Google Vertex AI Imagen JavaScript REST API WordPress

Thirty-four of the 86 nodes are JavaScript Code nodes. The generative steps are model calls; the control — parsing, gating, deduplicating, restoring loop items — is plain code, because a graph that reads cleanly at 3am is worth more than a clever one.

All projects