SEO Publish
Publication worker: takes a validated article file and posts it to the client's site. This is the ONLY skill allowed to make content public; everything upstream is drafts in the workdir.
Preconditions (hard gate : refuse if any is missing)
- Client validation documented: the kanban card (or the request) shows an explicit client approval of THIS article.
- QA verdict: a Content-quality-evaluator scorecard with PASS (or CONDITIONAL + editor override documented).
- CMS credentials available for this client.
If any is missing: do NOT publish; report exactly what is missing (and on a kanban card: kanban_block with the reason).
CMS resolution
From seo/clients/<slug>/client.json → cms block:
"cms": { "type": "wordpress" | "wix" | "none", "base_url": "...", "auth_ref": "env:CLIENT_<SLUG>_CMS_TOKEN" }
auth_ref is a reference to an environment variable, never a secret in clear text.
type: wordpress
REST API POST {base_url}/wp-json/wp/v2/posts with an Application Password (Basic auth from the referenced env var).
- Payload:
title,slug,content(markdown converted to HTML),status: "draft"first. - Verify the draft renders (GET the preview), then update
status: "publish". - Set meta description via the SEO plugin's REST field if exposed (Yoast/RankMath); otherwise report that meta must be set manually.
type: wix
Wix Blog REST API (https://www.wixapis.com/blog/v3/draft-posts), auth via API key + site ID from the referenced env vars. Create as draft, then publish. If the client's Wix plan/API access is not configured: block with "Wix API access to configure", do not attempt workarounds.
type: none
No CMS connected: deliver instead of publishing. Deposit the final article + a short integration note in seo/clients/<slug>/outputs/content/<date>/to-publish/ and notify the owner. The card is NOT marked published.
Publication steps
- Resolve CMS + credentials. Check preconditions.
- Convert the article markdown: strip frontmatter, convert to the CMS format, keep internal links as site-relative URLs, keep visual placeholders as clearly marked TODO blocks ONLY if the card says visuals are pending; otherwise refuse (an article with raw placeholders must not go live).
- Create as draft on the CMS. Fetch/preview it once: title, headings, links intact.
- Publish. Fetch the live URL, verify HTTP 200 and that the H1 matches.
- Report: live URL, publication timestamp, any manual follow-ups (meta description, visuals). On a kanban card: comment all of this, then hand back to the orchestrator.
Failure behavior
Any API error: stop, report the exact error, never retry more than twice, never mark published on failure. Rollback: if publish succeeded but verification failed, revert the post to draft and report.