skill-md

Installation

$npx skills add weipanux/seo-geo-blog-writer --skill skill-md

Summary

This skill enables an agent to execute a complete end-to-end blog post creation workflow, detecting whether a user's input requires keyword research (topic expansion) or is already a specific keyword target, then delivering a fully optimized post with internal links, schema markup, and validation checks. Invoke when a user requests blog content creation for ranking or citation purposes.

SKILL.MD

SEO-GEO Blog Writer

Purpose

Create high-performing blog posts optimized for both traditional search engines (SEO) and generative AI citations (GEO) through a structured four-phase workflow: Research → Outline → Draft → Optimize.

When to Use This Skill

Activate when user requests blog content creation. Two modes supported:

Mode A - Keyword-Driven:

  • "Write a blog post targeting 'best CRM for small business'"
  • "Create an article optimized for 'React hooks tutorial'"
  • "I need a post ranking for 'email marketing automation tools'"

Mode B - Topic Expansion:

  • "Write a blog post about email marketing"
  • "Create an article on React development"
  • "I need content about CRM systems"

Both modes follow the same four-phase workflow after keyword selection.

Workflow Overview

Execute in seven phases:

  1. Research: Gather requirements, conduct keyword research, analyze search intent, identify citation-worthy sources
  2. Outline: Select content pattern, create structured outline with SEO-optimized headers and GEO-friendly sections
  3. Draft: Write comprehensive content following E-E-A-T principles with proper keyword placement
  4. Optimize: Initial content optimization and refinement
  5. Auto Internal Linking (NEW v2.2): Discover and insert high-confidence internal links from Sanity/local content
  6. Image Generation (Coming Week 3): Auto-generate and insert images using AI
  7. Final Validation: Iterative validation with auto-fix for FAQ, author bio, schema, title

Example Usage

Example 1: Mode B (Topic Expansion with Keyword Research)

User Request: "Write a blog post about empath boundaries"

Execution Flow:

  1. Detect Mode B (general topic, no specific keyword)
  2. Execute keyword research:
    python scripts/keyword_research.py "empath boundaries" --limit 5 --format markdown
    
  3. Present options to user:
    Top keywords researched:
    1. healthy boundaries for empaths (Vol: 2,400, Diff: 45, Score: 95)
    2. how to set boundaries as an empath (Vol: 3,100, Diff: 52, Score: 92)
    3. empath boundary setting tips (Vol: 1,200, Diff: 38, Score: 88)
    
    Which would you like to target? (or 'auto' for best match)
    
  4. User selects: "Let's use #1" → Keyword confirmed: "healthy boundaries for empaths"
  5. Gather remaining requirements: audience, author details, word count (2,000 words recommended for Diff: 45)
  6. Load references/content-patterns.md → Select "How-To Guide" pattern
  7. Create outline with keyword optimization
  8. Write draft following E-E-A-T guidelines
  9. Execute validation and deliver complete package

Output: 2,000-word how-to guide optimized for "healthy boundaries for empaths" with FAQ schema, validation report, and meta tags

Example 2: Mode A (Keyword-Driven)

User Request: "Write a blog post about best email marketing tools for Shopify stores"

Execution Flow:

  1. Detect Mode A (specific long-tail keyword provided)
  2. Confirm keyword: "I'll optimize for 'best email marketing tools for Shopify stores'. Confirm?"
  3. Gather requirements: audience (Shopify store owners), word count (2,500), author details
  4. Load references/content-patterns.md → Select "Comparison Article" pattern
  5. Load references/seo-checklist.md → Extract keyword strategy
  6. Generate outline using assets/blog-template.md structure
  7. Write draft following E-E-A-T guidelines from references/eeat-guidelines.md
  8. Execute scripts/validate_structure.py on draft
  9. Generate schema markup using assets/structured-data-examples.json
  10. Deliver: blog post + schema markup + SEO checklist

Output: 2,500-word comparison article with FAQ schema, meta tags, and validation report

Implementation Instructions

Phase 1: Gather Requirements & Keyword Research

This skill supports two modes based on user input:

Mode A: Keyword-Driven (User provides specific target keyword) Mode B: Topic Expansion (User provides general topic, needs keyword research)

Step 1: Detect Mode

Analyze user request to determine mode:

IF request contains specific keyword phrase in quotes → Mode A
   Example: "Write post targeting 'healthy boundaries for empaths'"
   
ELSE IF request mentions specific long-tail keyword → Mode A
   Example: "Write about best email marketing tools for Shopify stores"
   
ELSE IF request is general topic → Mode B
   Example: "Write post about empath boundaries"
   Example: "Create article on email marketing"

Step 2: Execute Mode-Specific Workflow

MODE A: Keyword-Driven Workflow

User has already identified target keyword. Proceed directly to validation:

  1. Confirm keyword with user: "I'll optimize this post for '[keyword]'. Confirm?"
  2. Collect remaining requirements:
    • Target Audience
    • Content Goal
    • Author Details (name, credentials, bio, photo URL - critical for E-E-A-T)
    • Word Count Target (1,500-3,000 words)
  3. Continue to Phase 2 (Research & Pattern Selection)

MODE B: Topic Expansion Workflow

User needs keyword research assistance. Execute keyword research:

  1. Run keyword research script (with credential handling):

    The script automatically tries multiple credential methods in order:

    1. Command line argument (--api-key)
    2. Environment variable (DATAFORSEO_API_KEY)
    3. Config file (~/.dataforseo-skill/config.json)
    4. Fallback to heuristic mode (no API needed)

    IMPORTANT FOR CLAUDE CODE ENVIRONMENT:

    Option A: Ask user for API key (if they want real data):

    Claude: "Would you like to use the DataForSEO API for real keyword data?
            If yes, please provide your API key in format: login:password
            If no, I'll use fallback mode with intelligent estimates."
    
    IF user provides key:
      python scripts/keyword_research.py "user topic" --limit 5 --format markdown --api-key "user_provided_key"
    ELSE:
      python scripts/keyword_research.py "user topic" --limit 5 --format markdown
    

    Option B: Use fallback mode directly (faster, no credentials needed):

    # Fallback mode works without any credentials
    python scripts/keyword_research.py "user topic" --limit 5 --format markdown
    

    DO NOT use --interactive flag - it doesn't work in Claude Code's non-TTY environment.

    Note: The script automatically falls back to heuristic mode if:

    • No credentials found
    • API call fails (invalid credentials, rate limit, etc.)
    • Script provides intelligent keyword suggestions without API
  2. Present options to user:

    Display top 3-5 keywords with metrics:

    • Search volume (monthly searches)
    • Keyword difficulty (0-100, lower = easier to rank)
    • Relevance score (0-100, higher = better match)

    Example output:

    I've researched keywords for "empath boundaries". Top options:
    
    1. healthy boundaries for empaths (Vol: 2,400, Diff: 45, Score: 95)
    2. empath boundary setting tips (Vol: 1,200, Diff: 38, Score: 88)  
    3. how to set boundaries as an empath (Vol: 3,100, Diff: 52, Score: 92)
    
    Which keyword would you like to target? (or type 'auto' for best match)
    
  3. Handle user selection:

    Option 1: User selects specific keyword

    User: "Let's use #2"
    → Proceed with selected keyword
    

    Option 2: User requests auto-selection

    User: "auto" or "pick the best one"
    → Select highest relevance score
    → Inform user: "Auto-selected: [keyword] (best relevance score)"
    
  4. Collect remaining requirements (same as Mode A)

  5. Continue to Phase 2

Step 3: Validation & Optimization Notes

For Mode B keywords (researched via script):

  • Note search volume in outline planning (high volume = more comprehensive content needed)
  • Adjust word count based on keyword difficulty:
    • Difficulty 0-30: 1,500-2,000 words sufficient
    • Difficulty 31-60: 2,000-2,500 words recommended
    • Difficulty 61-100: 2,500-3,000+ words required

Fallback Handling

If scripts/keyword_research.py fails or is unavailable:

  1. Inform user: "Keyword research tool unavailable. Using heuristic analysis."
  2. Generate 3-5 variations manually using common patterns:
    • "best [topic]"
    • "how to [topic]"
    • "[topic] guide"
    • "[topic] tips"
    • "[topic] for beginners"
  3. Present options with estimated competitiveness
  4. Continue workflow normally

Phase 2: Research and Pattern Selection

Research Steps:

  1. Identify search intent: Informational, commercial, transactional, or navigational
  2. Load references/seo-checklist.md → Extract keyword strategy and meta optimization tactics
  3. Analyze top-ranking content patterns
  4. Gather citation-worthy sources: statistics, studies, expert quotes

Pattern Selection: Load references/content-patterns.md and select appropriate structure:

  • Ultimate Guide: Comprehensive topics (2,000+ words)
  • How-To Guide: Process-oriented content (1,500-2,500 words)
  • Comparison/Review: Product comparisons (2,000-3,000 words)
  • Listicle: Roundups and curated lists (1,000-2,500 words)
  • Data-Driven Research: Original research posts (2,000-4,000 words)

Phase 3: Create Outline

Generate structure including:

  • SEO-optimized title (primary keyword within first 60 characters)
  • Introduction with hook and primary keyword in first 100 words
  • 4-8 H2 sections with keyword variations
  • FAQ section (4-8 questions minimum)
  • Conclusion with clear CTA
  • Author bio section

Use assets/blog-template.md as structural reference.

Phase 4: Write Draft

Load references/eeat-guidelines.md and apply E-E-A-T principles:

Experience signals:

  • Include first-hand experiences, testing results, or case studies
  • Use specific examples and real scenarios
  • Add screenshots, data, or proof when applicable

Expertise signals:

  • Cite authoritative sources with proper attribution
  • Include expert quotes or interviews
  • Reference recent studies and statistics (with dates)
  • Use precise, accurate terminology

Authoritativeness signals:

  • Link to authoritative external sources (2-4 per article)
  • Build topical clusters with internal links (3-5 per article)
  • Demonstrate comprehensive topic coverage

Trustworthiness signals:

  • Add author bio with credentials
  • Include last updated date
  • Provide accurate, verifiable information
  • Add disclosures where relevant (affiliate links, sponsorships)

GEO Optimization: Load references/geo-optimization.md for AI citation formatting:

  • Start sections with clear, quotable statements
  • Use "According to [Source]" attribution format
  • Include statistics with sources and dates
  • Structure data in easily extractable formats (tables, lists)
  • Provide direct, concise answers in FAQ (40-60 word paragraphs)
  • Include "what, why, how" question variations

Phase 5: Auto Internal Linking (NEW v2.2)

Automated internal link discovery and insertion:

  1. Discover existing content from configured sources:

    # Test content discovery first
    python scripts/content_sources.py \
      --sanity-project-id $SANITY_PROJECT_ID \
      --local-content ./blog-posts
    

    Content source priority:

    1. Sanity CMS API (if SANITY_PROJECT_ID configured)
    2. Local markdown directory (if --local-content provided)
    3. Fallback to empty (no links inserted)
  2. Auto-insert internal links into draft:

    python scripts/auto_internal_linking.py /tmp/blog_draft.md \
      --sanity-project-id $SANITY_PROJECT_ID \
      --min-confidence 90 \
      --max-links 5 \
      --output /tmp/blog_draft_linked.md
    
  3. Link insertion process: The script automatically:

    • Discovers existing blog posts from configured sources
    • Analyzes relevance between draft and existing content
    • Identifies high-confidence linking opportunities (≥90 relevance)
    • Inserts markdown links for first keyword occurrence
    • Avoids over-linking (max 5 links by default)

    Example output:

    ✓ Found 50 existing pages for internal linking
    ✓ Found 8 total suggestions
      → 5 high-confidence (≥90)
    
    ✓ Successfully inserted 5 links:
    
    1. Email marketing → /blog/email-marketing-guide (95)
    2. Marketing automation → /blog/automation-best-practices (92)
    3. Customer segmentation → /blog/segmentation-strategies (91)
    4. Email campaigns → /blog/campaign-optimization (90)
    5. ROI tracking → /blog/marketing-metrics (90)
    
  4. Configuration options:

    Via command line:

    # Sanity CMS (recommended)
    python scripts/auto_internal_linking.py draft.md \
      --sanity-project-id your-project-id \
      --sanity-dataset production
    
    # Local markdown files
    python scripts/auto_internal_linking.py draft.md \
      --local-content ./blog-posts
    
    # Adjust confidence threshold
    python scripts/auto_internal_linking.py draft.md \
      --local-content ./posts \
      --min-confidence 85  # Lower threshold for more links
    

    Via environment variables:

    export SANITY_PROJECT_ID=your-project-id
    export SANITY_DATASET=production
    python scripts/auto_internal_linking.py draft.md
    

    Via config file: .seo-geo-config.json

    {
      "sanity": {
        "project_id": "your-project-id",
        "dataset": "production"
      },
      "internal_linking": {
        "min_confidence_auto_insert": 90,
        "max_links_per_post": 5
      }
    }
    
  5. Continue to Phase 6 (Image Generation) or Phase 7 (Final Validation)

Phase 6: Image Generation (NEW v2.2)

Automated image generation and insertion using AI APIs:

Generate professional blog post images automatically using Google Imagen or OpenAI DALL-E 3. The system extracts image placeholders, classifies image types, generates appropriate images, and inserts them into your draft.

1. Add image placeholders to your draft (optional):

During Phase 4 (drafting), add placeholders where you want images:

![Email marketing dashboard showing analytics](placeholder)
![Workflow diagram showing email automation steps](placeholder)

Note: Featured/hero image is auto-generated if not present.

2. Generate images:

Option A - OpenAI DALL-E 3 (easiest setup):

export OPENAI_API_KEY=sk-...

python scripts/image_generation.py /tmp/blog_draft.md \
  --output /tmp/blog_draft_with_images.md \
  --max-images 5

Option B - Google Imagen (requires Google Cloud):

export GOOGLE_API_KEY=...
export GOOGLE_PROJECT_ID=my-project

python scripts/image_generation.py /tmp/blog_draft.md \
  --output /tmp/blog_draft_with_images.md \
  --max-images 5

Option C - Use configuration file:

# Configure in .seo-geo-config.json:
{
  "image_generation": {
    "enabled": true,
    "google_api_key": "...",
    "google_project_id": "...",
    "openai_api_key": "sk-...",
    "max_images_per_post": 5,
    "output_dir": "./generated_images"
  }
}

python scripts/image_generation.py /tmp/blog_draft.md \
  --output /tmp/blog_draft_with_images.md

3. Test extraction without API keys (dry-run):

python scripts/image_generation.py /tmp/blog_draft.md --dry-run

# Output shows:
# - Number of images that would be generated
# - Image type and style classification
# - Alt text and context for each image

How it works:

  1. Extract Image Needs:

    • Finds all ![alt text](placeholder) patterns
    • Auto-adds featured/hero image if none exists
    • Classifies image type (featured, section, diagram)
    • Determines appropriate style (photorealistic, illustration, diagram)
  2. Generate Images:

    • Priority 1: Google Imagen ($0.02/image, $2000 startup credit)
    • Priority 2: OpenAI DALL-E 3 ($0.04-$0.08/image, Microsoft credits)
    • Optimized prompts for each style and image type
    • Downloads and saves images locally
  3. Insert Into Draft:

    • Replaces (placeholder) with actual image paths
    • Updates alt text for SEO
    • Preserves markdown formatting

Image Classification:

  • Featured/Hero Images: Photorealistic style, 1792x1024px

    • Trigger: First image or auto-generated from title
    • Example: "Professional email marketing dashboard"
  • Section Images: Illustration style, 1024x1024px

    • Trigger: Images within content sections
    • Example: "Email list building strategy"
  • Diagrams/Infographics: Technical diagram style, 1024x1024px

    • Trigger: Keywords like "diagram", "flowchart", "workflow", "infographic"
    • Example: "Email automation workflow diagram"

Cost tracking: The script shows total generation cost and per-image pricing for budget management.

Generated output structure:

/tmp/blog_draft_with_images.md    ← Updated draft with images
./generated_images/                ← Image directory
  ├── image_abc123.png             ← Featured image
  ├── image_def456.png             ← Section image 1
  └── image_ghi789.png             ← Diagram

Phase 7: Final Validation and Auto-Fix

Validation Protocol (ALWAYS EXECUTE):

  1. Write draft to temporary file:

    # Save draft to /tmp/blog_draft.md
    
  2. Execute iterative validation with auto-fix:

    python scripts/iterative_validation.py /tmp/blog_draft.md \
      --max-iterations 3 \
      --target-score 80 \
      --output /tmp/blog_draft_final.md
    
  3. Iterative validation process: The script automatically:

    • Validates current draft state
    • Auto-fixes common issues (FAQ, author bio, schema templates, title length)
    • Re-validates after fixes
    • Stops when: score ≥80 OR max 3 iterations OR no more auto-fixable issues

    Auto-fixable items:

    • Missing FAQ section → Generates 4-6 questions from H2 headings
    • Missing author bio → Adds template (user fills details later)
    • Short title (<50 chars) → Expands with year or descriptive phrases
    • Missing schema → Adds BlogPosting and FAQPage templates

    Non-auto-fixable items (require manual attention):

    • Low word count → Note thin sections for expansion
    • Missing internal/external links → Needs content research
    • Missing images → Needs image sourcing or generation
    • Low readability score → Needs content restructuring
  4. Interpret results:

    Final Score: 88/100
    
    Fixes Applied (4):
      ✓ Added FAQ section with 6 questions
      ✓ Added author bio template (requires user completion)
      ✓ Expanded title: 'Tips' → 'Complete Tips Guide 2025'
      ✓ Added schema markup templates (requires completion)
    
    ✓ PASSED (8 checks): Title optimal, Word count good, FAQ present...
    ⚠ WARNINGS (3 items): Internal links low, Images needed...
    
    • Score ≥80: Excellent, proceed to delivery
    • Score 60-79: Review warnings, address critical ones
    • Score <60: Fix FAILED checks manually, re-run validation
  5. Complete placeholders in auto-generated content:

    • Author bio: Replace [Author Name], [job title], [X years] with real details
    • Schema markup: Fill in [YYYY-MM-DD], [Meta description], [Featured image URL]
    • FAQ answers: Expand auto-generated summaries if needed
  6. Handle script failure: If script unavailable, use manual validation with references/seo-checklist.md:

    • Primary keyword in title, H1, first 100 words, URL slug, meta description
    • 2-3 H2 headings with keyword variations
    • Internal links (3-5) and external authority links (2-4)
    • Images with optimized alt text
    • FAQ section with schema markup
    • Author bio with credentials
    • Meta title (50-60 chars) and description (145-155 chars)
  7. Deliver final package:

    • Complete blog post with auto-fixes applied (/tmp/blog_draft_final.md)
    • Validation report showing score and fixes applied
    • Schema markup code blocks (with placeholders to complete)
    • SEO checklist with verification status
    • Image suggestions with alt text
    • Internal linking recommendations

Resource Loading Strategy

When to Load Each Reference

Requirements Phase (Load if needed):

  • Execute scripts/keyword_research.py → When Mode B detected (topic expansion needs keyword research)

Planning Phase (Always load):

  • Read references/content-patterns.md → Select appropriate pattern based on topic and search intent

Research Phase (Load if needed):

  • Read references/seo-checklist.md → When conducting keyword research or meta optimization
  • Read references/geo-optimization.md → When planning citation-worthy formatting

Draft Phase (Load selectively):

  • Read references/eeat-guidelines.md → When writing sections requiring credibility signals
  • Use assets/blog-template.md → As structural reference for section organization

Validation Phase (Always execute):

  • Execute scripts/validate_structure.py → After completing draft
  • Read assets/structured-data-examples.json → When generating schema markup

Token Efficiency for Large Files

references/content-patterns.md is 758 lines. For targeted reading:

# Read only specific pattern instead of entire file
grep -A 100 "## Pattern 2: How-To Guide" references/content-patterns.md

This approach: ~400 tokens vs ~3,000 tokens for full file.

Output Deliverables

Provide complete package:

  1. Blog post in markdown (using assets/blog-template.md structure)
  2. SEO checklist with verification status for each item
  3. Schema markup code blocks (BlogPosting + FAQPage)
  4. Image suggestions with optimized alt text
  5. Internal linking recommendations with anchor text
  6. Validation report from script execution

Critical Requirements (What NOT to Do)

Avoid these quality-damaging practices:

  • Thin content (<1,000 words for competitive topics)
  • Keyword stuffing (maintain natural readability)
  • Unverifiable claims or missing citations
  • Missing author credibility (E-E-A-T critical for rankings)
  • Poor mobile readability (short paragraphs required)
  • Clickbait tactics (damages trustworthiness signals)
  • Copying competitor content (use as pattern inspiration only)
  • Skipping FAQ section (critical for GEO optimization)
  • Missing schema markup (required for rich results)
  • No author bio (damages E-E-A-T scoring)

Quality Targets

Target these metrics for optimal performance:

  • Readability score: 60-70 (Flesch Reading Ease)
  • Keyword density: 1-2% for primary keyword
  • Heading hierarchy: Proper H1 → H2 → H3 structure
  • FAQ section: 4-8 questions with schema markup
  • Internal links: 3-5 with descriptive anchor text
  • External links: 2-4 to authoritative sources
  • Images: 5-8 with optimized alt text
  • Word count: 1,500-3,000 (adjust for competition)
  • E-E-A-T signals: Author bio, citations, first-hand experience
  • Schema markup: BlogPosting + FAQPage minimum

Optimization Factors for Best Results

Input Quality:

  • Specific topic details improve output precision
  • Real author credentials significantly improve E-E-A-T scoring
  • Existing case studies or data enhance content quality
  • Clear target audience definition enables better targeting

Process Optimization:

  • Request outline approval before full draft to ensure direction alignment
  • Execute validation script to catch structural issues early
  • Plan content refresh every 6-12 months for freshness signals

Related Skills

  • blog-optimizer: Improve existing posts (different workflow from creation)
  • content-repurposer: Convert blog posts to other formats (separate use case)