seo-forge
Use when the user wants an AI agent to research, generate, score, optimize, or publish SEO blog content for a company, product, or industry. Covers keyword discovery, SERP and competitor analysis, brand-knowledge constraints, outline and draft generation, 8 article templates, E-E-A-T and reference-quality checks, technical SEO/schema validation, editorial review gates, image support, and GitHub/Vercel publishing or verification. Also use when installing, exporting, or adapting SEO Forge as a portable skill for Codex, Claude Code, OpenCode, or another agent runtime. Requires trustworthy web search/fetch evidence; do not use for generic copywriting that does not need SEO research, quality gates, or publishing workflow.
SEO Forge — Universal Autonomous Blog Engine
Turn any company or industry into a blog content machine. The pipeline discovers trending keywords, generates SEO-optimized articles, scores quality on a 4-axis rubric, iterates until the quality council awards 100/100, then pushes to GitHub / Vercel.
Core Principles
- Universal: Works for any company, any industry, any language
- E-E-A-T First: Every article meets Google's Experience, Expertise, Authoritativeness, Trustworthiness standards
- Evidence-Based: All claims backed by real data, no fabricated quotes or URLs
- Template Diversity: 8 rotating templates prevent content similarity
- Auto-Push: Finished articles deploy to GitHub + Vercel automatically
Portable Agent Contract
SEO Forge should run on any capable agent runtime. Treat the tool names in the frontmatter as defaults, not as hard requirements.
Required capabilities:
file_readandfile_writefor configs, drafts, reports, and target-site contentshellforpython scripts/seo_forge.py ..., tests, builds, and git commandsweb_searchfor keyword discovery, trend checks, SERP research, and competitor discoveryweb_fetchfor reading competitor pages and verifying reference URLs
Optional capabilities:
repo_readfor remote repository inspection when the target site is not already localpull_requestfor publishing via GitHub or another code hostdeployment_checksfor monitoring GitHub Actions, Vercel, or equivalent deploymentsimage_generationfor creating article visuals when requested
Tool aliases:
web_search: GLMweb_search_prime, Tavily search, Exa search, Brave Search, or native web searchweb_fetch: GLMwebReader, Tavily Extract, Fetch MCP, browser automation, or native fetchrepo_read: GLMzread, GitHub MCP,ghCLI, orgit clonepull_request: GitHub MCP,gh pr create, or host-agent PR tools
If an exact MCP tool is unavailable, map the capability to the closest native equivalent. If no trustworthy web_search and web_fetch capability exists, stop and ask for those inputs instead of inventing SEO evidence.
Deployment helpers:
python scripts/seo_forge.py doctor
python scripts/seo_forge.py install-skill --target <agent-skills-dir>
python scripts/seo_forge.py export-skill --output seo-forge-skill.zip
See skill.json, templates/agent-capabilities.json, and docs/agent-deployment.md for machine-readable deployment details.
Configuration
Before first use, create a blog config in your project root:
{
"company_name": "Your Company",
"industry": "your-industry",
"site_url": "https://yourcompany.com",
"blog_path": "/blog",
"competitors": ["competitor1.com", "competitor2.com"],
"target_keywords": ["keyword1", "keyword2"],
"language": "en",
"cta_url": "https://yourcompany.com/signup",
"author_bio": "Written by the Your Company team.",
"brand_voice": "Professional but approachable. Evidence-based. Honest about limitations.",
"trusted_reference_domains": [
"wikipedia.org", "reuters.com", "bloomberg.com",
"techcrunch.com", "wired.com", "hbr.org"
]
}
Save as seo-forge.config.json in your project root. The skill auto-detects it.
Autonomous Pipeline: 11 Phases
BRAND_KNOWLEDGE → CONFIG → TREND → KEYWORD → OUTLINE → DRAFT
│
score < 100│
▼
GAP_FILL ← RESCORE ← EDIT ← SCORE ← OPTIMIZE
│
│ score = 100 + all checks pass
▼
PUBLISH (GitHub commit + Vercel deploy)
Phase 0: BRAND_KNOWLEDGE
Goal: Establish the brand knowledge base that constrains all content generation. Promotional claims must not exceed what the knowledge base documents as factual.
Steps:
- Initialize brand knowledge file:
python scripts/seo_forge.py brand-knowledge --action init --root <root> --company "<company>" - Populate knowledge categories from web research:
- facts: Verified brand facts (product names, features, pricing, specifications)
- claims: Approved marketing claims with evidence backing
- limitations: Known product limitations that must be disclosed
- competitors: Verified competitor comparison data
- forbidden_claims: Claims that are explicitly forbidden (unverified, exaggerated)
- Use web search to verify facts and find authoritative sources
- Validate the knowledge base:
python scripts/seo_forge.py brand-knowledge --action validate --root <root>
Key Constraint: All article content must stay within the boundaries of the brand knowledge base. If a claim is not in facts or claims, it cannot be stated as truth. If a claim is in forbidden_claims, it must be removed. Promotional language must not exceed factual content by more than a 1:3 ratio.
Output: brand-knowledge.json with verified facts, approved claims, limitations, competitor data, and forbidden claims
Transition: → CONFIG
Phase 1: CONFIG
Goal: Parse user input, load or create blog configuration.
Steps:
- Parse the argument:
<company-or-industry> - Look for existing
seo-forge.config.jsonin the current directory - If not found, generate one interactively:
- Use web search to identify the company's industry, competitors, and positioning
- Infer target keywords from industry analysis
- Write the config file
- Validate all required fields are present
Output: seo-forge.config.json with complete company/industry profile
Transition: → TREND
Phase 2: TREND
Goal: Auto-discover trending keywords and hot topics in the industry.
Steps:
- Use
mcp__web-search-prime__web_search_primeto search for:"[industry] trends [current_year]""[industry] blog topics trending""[industry] keywords high volume""what is trending in [industry] this month"
- Read top results with
mcp__web_reader__webReader - Extract keyword candidates:
- Search volume indicators (mention frequency, Google Trends hints)
- Intent classification (informational, commercial, transactional, navigational)
- Competition level (SERP analysis signals)
- Cross-reference with company's target keywords from config
- Score and rank keyword candidates:
Score = (0.30 × TrendSignal) + (0.25 × Relevance) + (0.25 × LowCompetition) + (0.20 × IntentMatch)
Agent: Use keyword-hunter agent profile for structured discovery
Output: Ranked keyword list with scores, intent, and suggested angles
Transition: → KEYWORD
Phase 3: KEYWORD
Goal: Deep-evaluate top keyword candidates with SERP analysis.
Steps:
- For top 10-15 candidates from Phase 2:
- Search for each keyword on Google via web search tools
- Analyze top 10 results: domain authority, content type, freshness
- Identify content gaps (missing perspectives, outdated content)
- Calculate opportunity score with circuit breaker logic
- Grade each keyword:
- S+: Final Score ≥ 25, WinProbability ≥ 50, ROIPotential ≥ 55
- S: Final Score ≥ 20, WinProbability ≥ 50, ROIPotential ≥ 55
- A+: Final Score ≥ 15, WinProbability ≥ 50, ROIPotential ≥ 55
- A: Final Score ≥ 10, WinProbability ≥ 40
- B: Final Score ≥ 5
- C: Final Score < 5 (deprioritize)
- Select top N keywords (default: 5) based on
--countflag
Scoring Formula:
Final Score = (0.30 × Potential) + (0.20 × Validation) - (0.50 × RealDifficulty) + OpportunityWindow
Agent: Use keyword-hunter agent for SERP analysis
Output: Final keyword selection with opportunity analysis
Transition: → OUTLINE
Phase 4: OUTLINE
Goal: Generate article outlines for each selected keyword.
Steps:
- Select blog template (see
references/blog-templates.md):- Smart selection based on keyword intent and content type
- Rotate templates to avoid similarity across articles
- 8 templates available: Reviewer, Tutorial, Analyst, Problem-Solver, Beginner's Guide, Storyteller, Comparison, Case Study
- Generate outline following template structure:
- H2 section order per template
- Writing voice and opening style per template
- Comparison targets (company vs competitors from config)
- Plan keyword distribution:
- Main keyword in title (H1), 2+ H2 headings, 1+ H3 heading, meta description (first 60 chars)
- Secondary keywords woven into body text
- Long-tail keywords in FAQ questions and subheadings
Agent: Use content-architect agent for outline generation
Output: Article outline with template assignment and keyword placement map
Transition: → DRAFT
Phase 5: DRAFT
Goal: Generate the full blog article from the outline.
Steps:
- Generate article following the outline and template:
- Follow E-E-A-T framework (see
references/eeat-framework.md) - Use first-person perspective (15-20+ occurrences of I/my/we/our)
- Include specific testing/experience timeline
- Provide balanced pros (3-5) and cons (2-3)
- Include technical specifications relevant to the industry
- Add comparison section vs named competitors from config
- Brand knowledge constraint: Only state claims that are in
brand-knowledge.jsonfacts or claims. Do NOT use language fromforbidden_claims. Promotional content must not exceed factual information by more than a 1:3 ratio.
- Follow E-E-A-T framework (see
- Generate supporting elements:
- SEO-optimized title (contains main keyword)
- Meta description (120-160 characters, keyword in first 60 chars)
- URL slug (≤6 words, keyword-rich)
- Image alt text for cover image
- Authority references: Include 4-6 external links to authoritative domains from
trusted_reference_domains
- Structure requirements:
- NO H1 in body (title is separate)
- Paragraph length: 150-300 words each
- At least 6 FAQ questions with natural phrasing
- References section with 4-6 authoritative sources (real URLs,
<a href>format) - Maximum 3 CTA buttons total
- Readability requirements (see "Blog Readability Standards" section):
- Every H2 and H3 gets a slugified
idattribute for TOC linking - Tables use proper
<thead>/<tbody>structure with header styling - For CJK languages (
--lang zh|ja|ko), paragraphs are wrapped in<p>tags suitable for CSStext-indent - Articles > 2000 words include a TOC data structure (array of heading items with id, text, level)
- Every H2 and H3 gets a slugified
Agent: Use content-architect agent for content generation
Output: Complete HTML blog article with title, meta, slug, and content
- Image planning and acquisition:
a. Use
image-architectagent to plan images (1 cover + 1-2 inline) b. For each image, decide mode (generate/search/unsplash) based on the decision framework inagents/image-architect.mdc. Execute image acquisition:- GENERATE:
python scripts/seo_forge.py comfyui-check→python scripts/seo_forge.py comfyui-generate --prompt "..." --width 1024 --height 1024 --output-dir ./seo-forge-data/images - SEARCH: web search for images → download candidates →
python scripts/seo_forge.py glm-ocr-verify --image-path CANDIDATE --expected-subject "..."→ select best match - UNSPLASH: search Unsplash, insert URL directly
d. Register all images:
python scripts/seo_forge.py image-register --article-id ID --slot cover --source generate --path ... --alt "..."e. Insert image references into article HTML: - Cover:
COVER_IMAGE_URL: [local path or Unsplash URL]andALT: [descriptive alt text] - Inline:
<figure><img src="[path]" alt="[alt text]" width="800" height="450" loading="lazy" /><figcaption>[caption]</figcaption></figure>
- GENERATE:
Transition: → SCORE
Phase 6: SCORE
Goal: Score the article on 4 quality axes (0-25 each, total 0-100).
Axes:
| Axis | Measures | Target |
|---|---|---|
| SEO Quality (0-25) | Keyword density, heading optimization, meta tags, slug quality | 22+ |
| E-E-A-T Compliance (0-25) | First-person usage, experience evidence, balanced perspective, transparency | 20+ |
| Content Depth (0-25) | Word count, FAQ coverage, technical detail, comparison depth | 20+ |
| Reference Authority (0-25) | Source count, URL validity, domain credibility, format correctness, relevance | 20+ |
Steps:
- Score each axis independently:
- SEO Quality: Check keyword density (1-2% target), heading keyword presence, meta optimization
- E-E-A-T Compliance: Count first-person usage, verify experience claims, check pros/cons balance
- Content Depth: Verify word count increase, FAQ count, technical detail presence
- Reference Authority: Verify reference count ≥4, URL validity (HEAD request), domain credibility,
<a href>format
- Compute total score (sum of 4 axes)
- Generate detailed scoring report per axis with specific improvement suggestions
Agent: Use quality-scorer agent for objective scoring
Output: scoring_report.json with per-axis scores, total, and improvement suggestions
Transition:
- Total = 100 → PUBLISH
- Total < 100 → OPTIMIZE
Phase 7: OPTIMIZE
Goal: Fix specific quality issues identified by scoring.
Steps:
- Read the scoring report
- For each axis below target:
- SEO Quality: Adjust keyword density, add keywords to headings, fix meta
- E-E-A-T: Add more first-person language, include experience evidence, balance pros/cons
- Content Depth: Expand thin sections, add FAQ questions, include technical details
- Reference Authority: Add authoritative sources, verify URLs, fix reference format, improve domain credibility
- Apply targeted fixes (not full rewrite — surgical edits only)
- Validate URL references:
- HEAD request verification for all reference URLs
- Remove broken URLs, replace with alternatives
- Ensure at least 2 references have verified URLs
Agent: Use seo-optimizer agent for targeted optimization
Output: Optimized article with specific fixes applied
Transition: → SCORE (re-score after optimization)
Phase 8: EDIT
Goal: Final polish and quality gate.
Steps:
- Run final checks:
- Content completeness (not truncated)
- HTML structure validity
- No self-referential company links in References
- CTA buttons preserved and functional
- All image slots filled (cover + inline images)
- Image sources recorded in article metadata (
imagesarray) - Generated images exist on disk (verify paths)
- Web-searched images passed OCR verification
- No AI-detection red flags (natural language, varied sentence structure)
- Exaggeration control: Superlatives < 5, dramatic patterns < 3, no unsubstantiated claims, promotional-to-factual ratio ≤ 1:3
- Brand knowledge gate: Article claims must not exceed brand knowledge facts. Forbidden claims must be removed. Claims not in
brand-knowledge.jsonmust be removed or verified. - Authority references: At least 2 external links from trusted reference domains
- Readability check: All H2/H3 headings have
idattributes, tables have<thead>/<tbody>structure, paragraphs are properly spaced - TOC check: Articles > 2000 words have a generated Table of Contents
- Table check: All data tables use proper header styling (not plain unstyled tables)
- Run post-optimization fixes:
- Keyword density fine-tuning (target exactly 1-2%)
- Meta description length enforcement (strictly 120-160 chars)
- Reference URL normalization
- Remove any claims found in
brand-knowledge.jsonforbidden_claims
- Generate final optimization report
Agent: Use quality-scorer agent for final review
Output: Final polished article ready for publication
Transition: → RESCORE
Phase 9: RESCORE
Goal: Final scoring pass to confirm quality threshold.
Steps:
- Re-run all 4-axis scoring on the edited article
- If total ≥ 90 (practical threshold for publication):
- Generate publication-ready report
- → PUBLISH
- If total < 90:
- Identify remaining gaps
- → OPTIMIZE (max 3 iterations total)
- After 3 iterations without convergence:
- Publish best version with quality report
- Flag for manual review
Output: Final scoring report and publication decision
Transition: → PUBLISH (or manual review)
Phase 10: PUBLISH
Goal: Push finished blog to GitHub and deploy via Vercel.
Steps:
- Format the article for the target platform:
- Markdown format (with frontmatter for static site generators)
- Or HTML format (for CMS integration)
- Commit to GitHub:
git checkout -b seo-forge/<keyword-slug> git add <blog_file> git commit -m "feat(seo-forge): add blog '<title>' SEO Score: <score>/100 Keyword: <keyword> Template: <template_name> Word Count: <count>" git push -u origin seo-forge/<keyword-slug> - Create Pull Request:
gh pr create --title "SEO Blog: <title>" --body "<scoring_report>" - If Vercel is configured, the PR auto-triggers a preview deployment
- Merge the PR to trigger production deployment
Agent: Use publisher agent for deployment
Output: GitHub PR URL + Vercel preview URL
Transition: Terminal (pipeline complete)
Single Article Mode (Quick)
For generating a single article without the full pipeline:
Invoke skill with: "write blog about [topic] for [company]"
The skill will:
- Load/create config
- Generate keyword analysis (quick mode)
- Select template → Generate outline → Draft
- Score → Optimize → Publish
Batch Mode
For generating multiple articles:
Invoke skill with: "generate 5 blogs for [company] on [industry]"
The skill will:
- Run Phase 2 (TREND) to discover 15-20 keyword candidates
- Run Phase 3 (KEYWORD) to evaluate and select top N
- For each selected keyword, run Phases 4-10
- Rotate templates across articles to ensure diversity
- Publish all articles as separate PRs
Convergence Criteria
The pipeline terminates when ALL conditions are met:
- Total SEO quality score ≥ 90/100
- All reference URLs return 200 (verified)
- Keyword density within target range (1-2%)
- E-E-A-T compliance score ≥ 20/25
- No content truncation or HTML structure errors
Loop Parameters
| Parameter | Default | Description |
|---|---|---|
--count | 1 | Number of articles to generate |
--site | (from config) | Company website URL |
--keywords | (auto-discovered) | Override keyword list |
--auto-push | false | Auto-commit and push to GitHub |
--lang | en | Output language for articles |
--template | auto | Force specific template ID |
--max-iterations | 3 | Max optimize-rescore cycles |
State Persistence
Pipeline state stored in seo-forge-state.json:
- Current phase, iteration count, score history
- Selected keywords, assigned templates
- Generated articles and their scores
- Build failures and optimization history
Each iteration reads state at start, writes at end.
Search Tools
Use MCP tools for web research:
mcp__web-search-prime__web_search_prime— keyword discovery and trend analysismcp__web_reader__webReader— read competitor articles and reference sourcesmcp__zread__read_file— read GitHub repo files for configmcp__zread__get_repo_structure— explore existing blog structure
Image Tools
Three image acquisition modes, controlled by image_mode in config (auto/generate/search/unsplash):
ERNIE-Image-Turbo (ComfyUI)
Local AI image generation via ComfyUI API. See references/image-pipeline.md for setup.
# Health check
python scripts/seo_forge.py comfyui-check
# Generate image
python scripts/seo_forge.py comfyui-generate --prompt "..." --width 1024 --height 1024 --output-dir ./seo-forge-data/images
# Generate without prompt enhancement (for precise control)
python scripts/seo_forge.py comfyui-generate --prompt "..." --no-enhance
GLM-OCR (Image Verification)
Verify web-searched images match article context. See references/image-pipeline.md for setup.
# Health check
python scripts/seo_forge.py glm-ocr-check
# Verify image content
python scripts/seo_forge.py glm-ocr-verify --image-path ./img.jpg --expected-subject "modern office"
Unsplash (Fallback)
When ComfyUI is unavailable or search fails, use Unsplash URL patterns:
https://images.unsplash.com/photo-{id}?w=1200&h=630&fit=crop
Image Decision Logic (in auto mode)
- Generate: abstract/conceptual topics, brand-specific visuals, style control needed
- Search: specific products/people/places/logos, public documentation screenshots
- Unsplash: ComfyUI unavailable, search fails, OCR rejects all candidates
Blog Readability Standards
Content quality is not only about SEO scores and keyword density — visual readability directly impacts bounce rate, time-on-page, and user satisfaction. Every article generated by this pipeline MUST meet the following readability standards before publication.
Paragraph Formatting
- Text Indentation (CJK): For Chinese, Japanese, and Korean articles, every
<p>paragraph MUST havetext-indent: 2emvia CSS. First paragraphs after headings, lists, tables, or blockquotes are exempt (zero indent). - Paragraph Length: 150-300 words each. No wall-of-text paragraphs.
- Spacing: Adequate margin between paragraphs (1em bottom margin minimum).
Heading Hierarchy
- Structural: H2 for major sections, H3 for subsections. Never skip levels (no H2 → H4).
- ID Anchors: Every H2 and H3 MUST have an
idattribute for Table of Contents linking. Use slugified text (lowercase, hyphens, strip HTML tags, handle CJK characters). - Visual Distinction: H2 and H3 must be visually distinct:
- H2: Larger font, bottom border, with a short primary-color accent bar
- H3: Left border in primary color, slightly indented
- SEO Requirement: Main keyword appears in at least 2 H2 headings and 1 H3 heading.
Table of Contents
- Required for articles > 2000 words: Generate a TOC from all H2/H3 headings.
- Desktop: Sticky sidebar TOC on large screens (hidden on mobile or collapsed accordion).
- Mobile: Inline collapsible TOC below article metadata.
- Links: Each TOC item links to the heading's
idanchor.
Table Visualization
Raw HTML tables with plain text are visually unappealing and hurt readability. Every data table MUST follow these standards:
- Header Styling: Table header row uses primary brand color background with white/light text. Uppercase, smaller font, letter-spacing.
- Alternating Rows: Even rows use a subtle muted background for scanability.
- Hover Effects: Row highlights on hover for interactive feel.
- Responsive: Tables wrapped in
overflow-x: autocontainer for mobile scroll. - First Column Bold: Parameter/label column uses font-weight 500+ for emphasis.
- Border Radius: Rounded corners on table container (0.75rem).
- Row Borders: Subtle bottom borders between rows; no heavy grid lines.
- For Data-Heavy Tables: Consider supplementing tables with CSS-based inline bar indicators or summary cards above the table highlighting key comparisons.
CSS Requirements for Blog Content
Every project using seo-forge MUST include these CSS classes (adapt colors to brand):
/* Paragraph indentation for CJK */
.blog-content p { text-indent: 2em; margin-bottom: 1em; }
.blog-content p:first-child,
.blog-content h2 + p, .blog-content h3 + p,
.blog-content ul + p, .blog-content ol + p,
.blog-content table + p, .blog-content blockquote + p { text-indent: 0; }
/* Heading hierarchy */
.blog-content h2 {
font-size: 1.625rem; font-weight: 700;
margin-top: 2.5rem; margin-bottom: 1rem;
padding-bottom: 0.5rem; border-bottom: 2px solid var(--border);
position: relative;
}
.blog-content h2::before {
content: ""; position: absolute; left: 0; bottom: -2px;
width: 60px; height: 2px; background: var(--primary);
}
.blog-content h3 {
font-size: 1.25rem; font-weight: 600;
margin-top: 1.75rem; margin-bottom: 0.75rem;
padding-left: 0.75rem; border-left: 3px solid var(--primary);
}
/* Table visualization */
.blog-content table {
width: 100%; border-collapse: separate; border-spacing: 0;
margin: 1.5rem 0; font-size: 0.875rem;
border-radius: 0.75rem; overflow: hidden;
border: 1px solid var(--border);
display: block; overflow-x: auto;
}
.blog-content table thead { background: var(--primary); }
.blog-content table thead th {
color: var(--primary-foreground); font-weight: 600;
padding: 0.75rem 1rem; text-align: left;
text-transform: uppercase; letter-spacing: 0.025em;
}
.blog-content table tbody tr { border-bottom: 1px solid var(--border); }
.blog-content table tbody tr:hover { background: var(--muted); }
.blog-content table tbody tr:nth-child(even) { background: var(--muted); }
.blog-content table tbody td { padding: 0.625rem 1rem; }
.blog-content table tbody td:first-child { font-weight: 500; }
Safety and Quality
- All reference URLs must be verified before inclusion
- Never fabricate quotes, statistics, or URLs
- All competitor comparisons must be against real named competitors
- Never compare against "traditional methods" or "manual processes" — only against real competing products/services
- Disclose affiliations transparently
- Limit marketing superlatives — the exaggeration control gate catches 30+ words/phrases including "revolutionary", "game-changing", "incredible", "amazing", "groundbreaking", "unprecedented", "world-class", "cutting-edge", "state-of-the-art", "best-in-class", "industry-leading", "unmatched", "perfect", "flawless", "ultimate" (see
SUPERLATIVE_WORDSin seo_forge.py) - Dramatic patterns like "you won't believe", "studies show that" (without attribution), and "the only solution" are detected and flagged
- Promotional content must not exceed factual content by more than a 1:3 ratio (promotional-to-factual claim ratio)
- All claims must be within brand knowledge boundaries — if not in
factsorclaims, they cannot be stated as truth - Forbidden claims in
brand-knowledge.jsonmust be removed before publication - Articles must include at least 2 external authority links from trusted reference domains
- Expert knowledge is an analysis lens, not primary evidence