seo-blog
Skill0 starsChanged 53 days agoMITView on GitHub
Research, write and publish an SEO-optimized blog article end-to-end: topic selection, SERP/competitor research, outline, HTML article, AI-generated and vision-reviewed hero/inline/OG images, and draft-first publishing to the configured blog. Use when the user asks to "write a blog post", "write an SEO article", "publish to my blog", "add a post to the blog", or runs /seoblog:write. Also holds the setup interview for /seoblog:setup and the config/state file schemas.
- Reads credentials
1 other project uses a version of this.
Adopted by
Most recently taken up by
- freema/ai-skillstheir own version, first seen Oct 13, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- freema/ai-skills★ 5same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository10 other files it gives its agents.
- blog-imagesSkill
- blog-publishSkill
- humanizeSkill
- seoblog-humanizeSkill
- seoblog-publishSkill
- seoblog-setupSkill
- seoblog-statusSkill
- seo-researchSkill
- seo-writingSkill
- social-articleSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 3 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 13
Read runtime instructions before running scripts.
- Distinctive: line 24
Run the blog preflight from the runtime instructions before analyzing content.
- Distinctive: line 97
If research reveals the topic is too thin for a good article, say so and pick another — quality over quantity.
- Very specific: line 154
Use AskUserQuestion to collect, then write config.json (Write/Edit is fine — it holds no secrets):
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Read runtime instructions before running scripts.
SEO blog writing — the orchestrator
You write exactly ONE article per invocation, walking these phases in order:
analyze → select topic → research → outline → write → humanize
→ images → publish draft → reportRun the blog preflight from the runtime instructions before analyzing content. Honor "no images" by skipping generation and stripping image placeholders.
This flow is fully autonomous — it runs unattended (e.g. scheduled off-hours), so it must complete without ever asking the user anything.
Per-phase craft lives in five sibling skills — load them as you reach each phase:
- seo-research — topic selection, SERP analysis, competitor deep-dives, LSI keywords
- seo-writing — outline + article craft: HTML rules, keyword placement, length targets
- humanize — AI-tell review and rewrite of the text before images are briefed
- blog-images — image counts/cost, prompt craft, vision review + edit/regenerate fix loop
- blog-publish — script mechanics: create/update/upload via
cms.mjs, placeholder swap
Files you read and edit directly
There is no state server — you own these files with Read/Edit/Write:
Config ~/.config/seoblog/config.json (non-secret; secrets NEVER go here):
{ "defaultSite": "plugmyplugin",
"sites": { "plugmyplugin": {
"baseUrl": "https://plugmyplugin.com",
"cmsType": "articles-api", // articles-api | wordpress | shopify
"author": "Mark Rieck",
"niche": "Claude Code plugins and AI dev tooling",
"toneGuide": "Professional and approachable",
"voiceSamples": [], // optional: 1–3 paragraphs of the author's own writing (inline text or an absolute file path each); the humanize pass matches their rhythm, word choice and dash usage
"directions": "", // standing house rules, appended to every run
"articleLength": "medium", // short | medium | long
"imageReviewRounds": 2, // 0–3 paid fix rounds per image after vision review (default 2)
"product": null, // or {productUrl, productName, tagline, shortDesc, longDesc?, productTags?}
"shopifyBlogId": null } },
"socialCue": { // optional — only /seoblog:socialcue uses it
"dir": "/abs/path/.socialdiscovery", // the SocialCue store to write to (else $SOCIALCUE_DIR / cwd walk-up)
"cliPath": null, // override for SocialCue's lib/cli.js (else newest plugin cache copy)
"brandBySite": { "plugmyplugin": "PlugMyPlugin" } } } // site → SocialCue brand hintsState ~/.config/seoblog/state/<siteId>.json — memory across runs:
{ "articleHistory": [{ "id": "12", "slug": "…", "title": "…", "keywords": ["…"],
"status": "draft", "wordCount": 1200, "createdAt": "<iso>" }],
"keywordQueue": [{ "keyword": "…", "status": "pending|in-progress|completed",
"articleId": null }],
"lastRunAt": "<iso>",
"socialPosts": [{ "contentItemId": "…", "title": "…", "brandName": "…", "platform": "indiehackers",
"hostSite": "plugmyplugin", "assetHolderId": "42", "createdAt": "<iso>" }] }socialPosts is written by /seoblog:socialcue (the social-article skill);
the blog flows leave it untouched.
API keys are NEVER written by you or any script — the user stores them in their
own terminal (Keychain service seoblog). See Setup below.
Phase order in detail
- ANALYZE — read the state file, then
node "${SEOBLOG_PLUGIN_ROOT}/scripts/cms.mjs" list --site <id> --exclude-assets(the key is sent on GET, so drafts come back too;--exclude-assetshides the SocialCue image-holder drafts, which are not content). Build a map of covered topics, gaps, and topical clusters. Dedup rule: if the topic/keyword is in the article history OR similar content exists on the site in ANY status, skip it and pick another.status: "archived"means the site owner rejected that draft: the topic AND nearby angles are off the table, never rewrite them. - SELECT TOPIC — keyword mode (user gave keywords: first = primary, rest = secondary/LSI, ONE article for all of them; mark them in-progress in the state file) or auto-discover (no keywords: drain the state keywordQueue first; if empty, research trending topics/gaps — see seo-research). Stay on the site's declared niche.
- RESEARCH — per seo-research. WebSearch SERPs, WebFetch 2–3 competitors,
find the angle. If the site has a
product, WebFetch the product URL too. If research reveals the topic is too thin for a good article, say so and pick another — quality over quantity. - OUTLINE — self-check. Draft the outline: chosen topic + why (including the dedup check result), title (<60 chars, primary keyword), H2/H3 outline, target word count, planned image spots, product angle if any. Validate it yourself — dedup passed, title fits, H2/H3s cover the search intent, word count matches the site's articleLength — fix what fails, then proceed immediately. Never ask the user to approve it.
- WRITE — per seo-writing. Full HTML body with
<!-- IMAGE: … -->placeholders (no<img>yet), meta description, excerpt, 3–7 tags. 5b. HUMANIZE — per the humanize skill. Run its full process (mark the tells, draft, check, final) on the body, title, meta description and excerpt before any image is briefed, so alt text and image prompts are written from the final text. Voice precedence: the site'svoiceSamples, thendirections, thentoneGuide. Keep every fact, link, keyword placement and<!-- IMAGE -->placeholder; never add a detail you do not have (simplify the sentence instead) and never ask. Keep its one report line (humanize: N tells fixed (strongest: …)) for phase 8. - IMAGES — per blog-images. Compute the image count from its table, note
the cost ("N images × $0.15 = $X base, up to R fix rounds each → worst case
$Y via fal.ai") in your progress output for the record, and generate
immediately — no approval step. Then look at every image: Read each
file, give a one-line verdict, and fix real defects (dangling cables, sun in
a night scene, garbled text, wrong subject…) with
--editor a regenerate, up to the site'simageReviewRounds(default 2) per image. Pick the best round per image. If FAL_API_KEY is unset, publish without images and strip the placeholders. - PUBLISH DRAFT — per blog-publish: create with
status:"draft"(ALWAYS draft, never publish directly), upload the chosen image files under their canonical names, swap placeholders, update the state file (record article, mark keywords completed, set lastRunAt). - REPORT. The article stays a draft — that is the terminal state.
Report: draft id, slug, live-URL-to-be (
<baseUrl>/blog/<slug>), the humanize line from phase 5b, per-image review outcome (rounds used, what was fixed), calls made and actual spend vs. worst case, any defects left at the cap. Previewing drafts is the site's job — point the user at whatever their site provides (e.g. plugmyplugin.com shows drafts at the live URL to signed-in admins); never construct a preview-key URL. Note that /seoblog:publish flips it live later. Only flip to published in this same run (cms.mjs update --id Nwith{"status":"published"}) if the user's original prompt explicitly asked to publish — never ask.
Critical rules
- ALWAYS DRAFT first — never create with status published.
- ALWAYS RECORD — update the state file after creating an article.
- NEVER PLAGIARIZE — research is for understanding what exists; write original content.
- ONE ARTICLE PER RUN.
- NEVER ASK QUESTIONS during a write run — no AskUserQuestion, no free-text confirmations ("proceed?", "is this OK?"). Runs are often scheduled and unattended; a question means the run fails. Compute the image count from the table and proceed; run the image fix rounds on your own judgment; end at draft and report.
- Respect the site's
directionsfield as standing house rules on every run.
Setup interview (for /seoblog:setup)
Use AskUserQuestion to collect, then write config.json (Write/Edit is fine — it holds no secrets):
- Site id (short slug), baseUrl, cmsType (articles-api / wordpress / shopify; wordpress uses the same wire contract via the Cue Up WP plugin; shopify needs a Custom App token with write_content and optionally shopifyBlogId).
- Author name and niche (both required).
- Tone guide + default article length (short ~500 / medium ~1200 / long ~2000 words).
Also offer voice samples: 1–3 paragraphs of the author's own writing,
pasted inline or as an absolute path to a text file, saved as
voiceSamples(array of strings). The humanize pass matches their rhythm, word choice and punctuation. Skip silently if the user has none. - Optional product for product-led content (productUrl, productName, tagline, shortDesc).
- Optional standing directions.
- Image review: write
imageReviewRounds: 2(the default — Claude looks at every image and spends up to 2 paid fix rounds on defects). Only ask if the user raised image cost/quality; 0 disables paid fixes, 3 is the max. - SocialCue (optional, only if the user mentions SocialCue / Indie Hackers /
dev.to posting or the doctor found the SocialCue plugin): ask which project
holds their
.socialdiscovery/store and writesocialCue.dir; when the store's brands are known, writesocialCue.brandBySitefor this site. Skip silently otherwise — /seoblog:socialcue also finds the store from cwd.
Then print the exact commands for the user to run in their own terminal (keys must never pass through your tool calls):
security add-generic-password -s seoblog -a FAL_API_KEY -w
security add-generic-password -s seoblog -a "site:<siteId>" -wOn non-macOS systems, provide the environment-variable instructions from the runtime guide instead of Keychain commands.
Finish with node "${SEOBLOG_PLUGIN_ROOT}/scripts/doctor.mjs" --site <id> and fix
anything red. Doctor's connectivity check is free and proves the key works.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

