Claude-skill-registry image-generation

AI image generation using Pollinations.ai with Stable Horde fallback - FREE with no API key required. Use when generating hero images, icons, logos, illustrations, mockups, or any visual assets for websites and apps. Covers product shots, avatars, placeholders, and social media images with professional quality.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/image-generation-anton-abyzov-specweave" ~/.claude/skills/majiayu000-claude-skill-registry-image-generation-3f1753 && rm -rf "$T"
manifest: skills/data/image-generation-anton-abyzov-specweave/SKILL.md
source content

AI Image Generation Skill

Expert in generating professional-quality images using multi-provider resilience: Pollinations.ai (primary) with Stable Horde (fallback) - both FREE, no API keys required.


🛑 STEP 1: RUN THIS BASH COMMAND FIRST (MANDATORY - NO EXCEPTIONS)

YOU MUST EXECUTE THIS BASH COMMAND BEFORE DOING ANYTHING ELSE.

This is not optional. Do not skip. Do not generate URLs first. RUN THIS FIRST:

TEMP=$(mktemp) && curl -s -L -o "$TEMP" --max-time 10 "https://image.pollinations.ai/prompt/test?width=64&height=64&nologo=true" 2>/dev/null && TYPE=$(file -b "$TEMP" | cut -d',' -f1) && rm -f "$TEMP" && if [[ "$TYPE" == "PNG image data" ]] || [[ "$TYPE" == "JPEG image data" ]]; then echo "PROVIDER=pollinations"; else echo "PROVIDER=stablehorde"; echo "REASON=Got $TYPE instead of image"; fi

Based on Output:

OutputWhat To Do
PROVIDER=pollinations
✅ Use Pollinations.ai URLs below
PROVIDER=stablehorde
🔄 SKIP Pollinations entirely → Use Stable Horde API (see fallback section)

If you did NOT run the Bash command first, STOP and run it now.


⚠️ CRITICAL: Health Check First (MANDATORY)

BEFORE generating any image, ALWAYS run this CONTENT-BASED health check:

⚠️ WARNING: HTTP 200 status is NOT sufficient! Pollinations may return 200 but with error text instead of image data. ALWAYS verify the response is actually an image.

# ROBUST health check - verifies actual image content (not just HTTP status)
TEMP_FILE=$(mktemp)
curl -s -L -o "$TEMP_FILE" --max-time 10 "https://image.pollinations.ai/prompt/blue%20square?width=64&height=64&nologo=true"
CONTENT_TYPE=$(file -b "$TEMP_FILE" | head -c 10)

if [[ "$CONTENT_TYPE" == "PNG image" ]] || [[ "$CONTENT_TYPE" == "JPEG image" ]]; then
    echo "✅ HEALTHY - Use Pollinations"
else
    echo "❌ BROKEN - Use Stable Horde (got: $CONTENT_TYPE)"
    cat "$TEMP_FILE"  # Show error message
fi
rm -f "$TEMP_FILE"

Decision Tree Based on CONTENT (Not Just Status)

Content CheckMeaningAction
PNG image data
✅ HealthyUse Pollinations.ai
JPEG image data
✅ HealthyUse Pollinations.ai
ASCII text
❌ Service error (502/503 in body)→ Use Stable Horde
HTML document
❌ Error page→ Use Stable Horde
Empty/timeout❌ Network error→ Use Stable Horde

Automated Provider Selection Script (ROBUST VERSION)

#!/bin/bash
# save as: check-image-api.sh
# IMPORTANT: This checks CONTENT, not just HTTP status!

TEMP_FILE=$(mktemp)
curl -s -L -o "$TEMP_FILE" --max-time 15 \
  "https://image.pollinations.ai/prompt/test%20square?width=64&height=64&nologo=true" 2>/dev/null

CONTENT_TYPE=$(file -b "$TEMP_FILE" 2>/dev/null | cut -d',' -f1)
rm -f "$TEMP_FILE"

if [[ "$CONTENT_TYPE" == "PNG image data" ]] || [[ "$CONTENT_TYPE" == "JPEG image data" ]]; then
    echo "PROVIDER=pollinations"
    echo "STATUS=healthy"
else
    echo "PROVIDER=stablehorde"
    echo "REASON=Pollinations returned '$CONTENT_TYPE' instead of image"
fi

Why HTTP 200 Is Misleading

Pollinations.ai uses Cloudflare CDN. When the origin server is down:

  • Cloudflare returns HTTP 200 (edge responds)
  • But the BODY contains:
    502 Bad Gateway - Unable to reach the origin service
  • This is why content-based checking is mandatory

🚨 NEVER GET STUCK Protocol (Claude Code Behavior)

This section defines how Claude Code should behave to NEVER get stuck on image generation.

Rule 1: Always Set Timeouts

# ALWAYS use --max-time flag (15-30 seconds max)
curl --max-time 15 "https://image.pollinations.ai/prompt/..."

# NEVER use curl without timeout (can hang forever)
curl "https://image.pollinations.ai/prompt/..."  # ❌ WRONG - can hang

Rule 2: Fail Fast, Switch Immediately

If ANY of these occur, immediately switch to Stable Horde:

  • Timeout (>15 seconds)
  • Non-image response (ASCII text, HTML)
  • HTTP 4xx/5xx errors
  • API Error 400 "Could not process image"

DO NOT:

  • ❌ Retry more than once
  • ❌ Wait indefinitely
  • ❌ Keep trying the same failing provider

Rule 3: Check Before Acting

ALWAYS run health check BEFORE attempting image generation:

# Quick pre-flight check (5 second max)
TEMP=$(mktemp)
timeout 5 curl -s -o "$TEMP" "https://image.pollinations.ai/prompt/test?width=64&height=64" 2>/dev/null
if file "$TEMP" | grep -q "image"; then
    echo "Provider ready"
else
    echo "Provider down - use Stable Horde"
fi
rm -f "$TEMP"

Rule 4: Structured Error Handling

When image generation fails, follow this exact flow:

1. Try Pollinations (timeout: 15s)
   ├── Success (image data) → Done ✅
   └── Failure (any error) → Step 2

2. Try Stable Horde (timeout: 120s for full job)
   ├── Success → Done ✅
   └── Failure → Step 3

3. Report failure and STOP
   └── Tell user: "Image generation unavailable. Both Pollinations.ai and Stable Horde are down."
   └── DO NOT keep retrying

Rule 5: Exit Conditions (MANDATORY)

Claude Code MUST exit the image generation attempt when:

ConditionActionMax Attempts
TimeoutSwitch provider1
HTTP 5xxSwitch provider1
"Could not process image"Switch provider1
Non-image responseSwitch provider1
Both providers failSTOP and report0

Example: Non-Blocking Image Generation

async function generateImageNonBlocking(prompt: string): Promise<string | null> {
  const TIMEOUT_MS = 15000;

  // Try Pollinations first
  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);

    const response = await fetch(
      `https://image.pollinations.ai/prompt/${encodeURIComponent(prompt)}?width=512&height=512`,
      { signal: controller.signal }
    );
    clearTimeout(timeoutId);

    const contentType = response.headers.get('content-type');
    if (contentType?.startsWith('image/')) {
      return await response.blob().then(b => URL.createObjectURL(b));
    }
    // Not an image - fall through to Stable Horde
  } catch (e) {
    console.log('Pollinations failed, trying Stable Horde');
  }

  // Try Stable Horde
  try {
    return await generateViaStableHorde(prompt);
  } catch (e) {
    console.error('Both providers failed');
    return null; // STOP - don't keep retrying
  }
}

Claude API "Could Not Process Image" Error

When you see this error:

API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"Could not process image"}}

This means Claude's vision API cannot process the image. Solutions:

  1. The image file may be corrupted or incomplete (502 error in disguise)
  2. The image format is unsupported
  3. The image URL returned an error page, not actual image data

Action: Do NOT retry with Claude's Read tool. Instead:

  1. Download the image with curl first
  2. Verify it's actually an image:
    file downloaded.png
  3. If not an image → use Stable Horde fallback

Quick Reference

Primary: Pollinations.ai (when healthy)

https://image.pollinations.ai/prompt/YOUR_PROMPT_HERE

Fallback: Stable Horde (when Pollinations is down)

POST https://stablehorde.net/api/v2/generate/async
Content-Type: application/json

{"prompt": "YOUR_PROMPT_HERE", "params": {"width": 512, "height": 512}}

Stable Horde Fallback API (FREE, No API Key)

When Pollinations.ai returns 5xx errors, use Stable Horde - a community-powered, 100% free alternative.

Why Stable Horde Works

  • ✅ No API key required (anonymous mode)
  • ✅ No rate limits for reasonable usage
  • ✅ High-quality Stable Diffusion models
  • ✅ Community-powered (crowdsourced GPUs)
  • ⏱️ Generation time: 30-120 seconds (varies by queue)

Step 1: Submit Generation Request

curl -X POST "https://stablehorde.net/api/v2/generate/async" \
  -H "Content-Type: application/json" \
  -H "apikey: 0000000000" \
  -d '{
    "prompt": "a majestic mountain landscape, professional photography, 8k, detailed",
    "params": {
      "width": 512,
      "height": 512,
      "steps": 30,
      "cfg_scale": 7.5,
      "sampler_name": "k_euler_a"
    },
    "nsfw": false,
    "censor_nsfw": true,
    "models": ["stable_diffusion"]
  }'

Response:

{
  "id": "abc123-def456-ghi789",
  "kudos": 10
}

Step 2: Poll for Completion

# Poll every 5 seconds until done
curl -s "https://stablehorde.net/api/v2/generate/check/abc123-def456-ghi789"

Response when processing:

{
  "done": false,
  "wait_time": 45,
  "queue_position": 3,
  "processing": 1
}

Response when complete:

{
  "done": true,
  "generations": [
    {
      "img": "base64_encoded_image_data...",
      "seed": "12345",
      "worker_id": "worker-abc",
      "model": "stable_diffusion"
    }
  ]
}

Step 3: Save the Image

# Extract and save base64 image
curl -s "https://stablehorde.net/api/v2/generate/status/abc123-def456-ghi789" | \
  jq -r '.generations[0].img' | base64 -d > output.png

Complete Node.js Example with Fallback

import https from 'https';
import fs from 'fs';

interface ImageOptions {
  prompt: string;
  width?: number;
  height?: number;
  outputPath: string;
}

// Health check for Pollinations
async function checkPollinationsHealth(): Promise<boolean> {
  return new Promise((resolve) => {
    const req = https.get(
      'https://image.pollinations.ai/prompt/health?width=64&height=64',
      { timeout: 3000 },
      (res) => resolve(res.statusCode === 200)
    );
    req.on('error', () => resolve(false));
    req.on('timeout', () => { req.destroy(); resolve(false); });
  });
}

// Generate via Pollinations (primary)
async function generatePollinations(options: ImageOptions): Promise<string> {
  const { prompt, width = 1024, height = 1024, outputPath } = options;
  const url = `https://image.pollinations.ai/prompt/${encodeURIComponent(prompt)}?width=${width}&height=${height}&nologo=true`;

  return new Promise((resolve, reject) => {
    https.get(url, (res) => {
      if (res.statusCode !== 200) {
        reject(new Error(`Pollinations returned ${res.statusCode}`));
        return;
      }
      const file = fs.createWriteStream(outputPath);
      res.pipe(file);
      file.on('finish', () => { file.close(); resolve(outputPath); });
    }).on('error', reject);
  });
}

// Generate via Stable Horde (fallback)
async function generateStableHorde(options: ImageOptions): Promise<string> {
  const { prompt, width = 512, height = 512, outputPath } = options;

  // Step 1: Submit job
  const jobId = await submitHordeJob(prompt, width, height);
  console.log(`Stable Horde job submitted: ${jobId}`);

  // Step 2: Poll until done
  let done = false;
  let imageData: string | null = null;

  while (!done) {
    await new Promise(r => setTimeout(r, 5000)); // Wait 5s
    const status = await checkHordeStatus(jobId);
    console.log(`Queue position: ${status.queue_position}, Wait: ${status.wait_time}s`);

    if (status.done) {
      done = true;
      imageData = status.generations[0]?.img;
    }
  }

  // Step 3: Save image
  if (imageData) {
    fs.writeFileSync(outputPath, Buffer.from(imageData, 'base64'));
    return outputPath;
  }
  throw new Error('No image generated');
}

// Main function with automatic fallback
async function generateImage(options: ImageOptions): Promise<string> {
  console.log('Checking Pollinations.ai health...');
  const pollinationsHealthy = await checkPollinationsHealth();

  if (pollinationsHealthy) {
    console.log('✅ Pollinations healthy, using primary provider');
    try {
      return await generatePollinations(options);
    } catch (err) {
      console.log('⚠️ Pollinations failed, falling back to Stable Horde');
      return await generateStableHorde(options);
    }
  } else {
    console.log('❌ Pollinations down (502/503), using Stable Horde fallback');
    return await generateStableHorde(options);
  }
}

// Usage
generateImage({
  prompt: 'a futuristic city at sunset, cyberpunk, neon lights, 8k',
  width: 1024,
  height: 1024,
  outputPath: './generated-image.png'
}).then(path => console.log(`Image saved to: ${path}`));

Stable Horde Parameters Reference

ParameterValuesDefaultDescription
width
64-1024 (multiples of 64)512Image width
height
64-1024 (multiples of 64)512Image height
steps
1-15030Diffusion steps
cfg_scale
1-307.5Prompt adherence
sampler_name
k_euler_a, k_dpm_2, etc.k_euler_aSampling method
models
["stable_diffusion", "SDXL 1.0"]autoModel selection

Stable Horde Web UI Alternative

If you prefer a visual interface: ArtBot - free web UI for Stable Horde.


When This Skill Activates

This skill auto-activates when you need images for:

  • Web Development: Hero sections, backgrounds, banners, thumbnails
  • App Design: Splash screens, onboarding, placeholders, icons
  • Marketing: Product mockups, social media, ads, landing pages
  • UI/UX: Illustrations, avatars, empty states, feature graphics
  • Prototyping: Concept visualization, wireframe assets

Pollinations.ai API

Basic URL Structure

https://image.pollinations.ai/prompt/{prompt}?{parameters}

Parameters

ParameterValuesDefaultDescription
width
256-20481024Image width in pixels
height
256-20481024Image height in pixels
model
flux, turbo, flux-realism, flux-anime, flux-3d, flux-cablyaifluxAI model to use
seed
any integerrandomReproducible results
nologo
truefalseRemove watermark
enhance
truefalsePrompt enhancement
safe
truefalseSafety filter

Available Models

ModelBest ForQualitySpeed
flux
General purpose, photorealisticHighestMedium
flux-realism
Ultra-realistic photosVery HighMedium
flux-anime
Anime/illustration styleHighFast
flux-3d
3D renders, product mockupsHighMedium
flux-cablyai
Artistic, creative stylesHighFast
turbo
Quick iterations, draftsMediumFastest

Professional Prompt Engineering

Prompt Formula (CRITICAL for Quality)

[Subject] + [Style/Medium] + [Lighting] + [Composition] + [Quality Modifiers]

Quality Modifiers (ALWAYS Include)

For highest quality output, append these to prompts:

, professional photography, 8k uhd, high resolution, sharp focus, highly detailed

For specific use cases:

Use CaseQuality Modifiers
Website Hero
cinematic lighting, professional photography, 8k, sharp focus, volumetric lighting
Product Shot
studio lighting, white background, commercial photography, product photography, clean
App Icon
minimal, flat design, vector style, clean lines, app icon, centered, simple background
Illustration
digital illustration, vibrant colors, clean lines, professional artwork, detailed
Avatar
portrait, centered, professional headshot, neutral background, high quality
Background
seamless pattern, tileable, abstract, subtle, muted colors, non-distracting

Aspect Ratios for Common Use Cases

Use CaseWidthHeightRatio
Hero Banner1920108016:9
Social Media Post120012001:1
Portrait/Avatar80012002:3
Product Card8006004:3
Mobile Splash108019209:16
App Icon5125121:1
OG Image1200630~1.9:1
Thumbnail4003004:3

Code Examples

React/Next.js Integration

// components/GeneratedImage.tsx
interface GeneratedImageProps {
  prompt: string;
  width?: number;
  height?: number;
  model?: 'flux' | 'flux-realism' | 'flux-anime' | 'flux-3d' | 'turbo';
  className?: string;
  alt: string;
}

export function GeneratedImage({
  prompt,
  width = 1024,
  height = 1024,
  model = 'flux',
  className,
  alt,
}: GeneratedImageProps) {
  const encodedPrompt = encodeURIComponent(prompt);
  const url = `https://image.pollinations.ai/prompt/${encodedPrompt}?width=${width}&height=${height}&model=${model}&nologo=true`;

  return (
    <img
      src={url}
      alt={alt}
      width={width}
      height={height}
      className={className}
      loading="lazy"
    />
  );
}

// Usage
<GeneratedImage
  prompt="Modern tech startup office, glass walls, natural lighting, professional photography, 8k"
  width={1920}
  height={1080}
  alt="Hero background"
  className="w-full h-auto object-cover"
/>

With Next.js Image Optimization

// next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'image.pollinations.ai',
      },
    ],
  },
};

// components/OptimizedGeneratedImage.tsx
import Image from 'next/image';

export function OptimizedGeneratedImage({ prompt, width, height, alt }) {
  const url = `https://image.pollinations.ai/prompt/${encodeURIComponent(prompt)}?width=${width}&height=${height}&model=flux&nologo=true`;

  return (
    <Image
      src={url}
      alt={alt}
      width={width}
      height={height}
      priority={false}
    />
  );
}

HTML Direct Embed

<!-- Hero Image -->
<img
  src="https://image.pollinations.ai/prompt/futuristic%20city%20skyline%20at%20sunset%2C%20cyberpunk%2C%20neon%20lights%2C%20cinematic%2C%208k?width=1920&height=1080&model=flux&nologo=true"
  alt="Hero background"
  loading="lazy"
/>

<!-- Product Mockup -->
<img
  src="https://image.pollinations.ai/prompt/smartphone%20mockup%20on%20marble%20desk%2C%20minimal%2C%20studio%20lighting%2C%20product%20photography?width=800&height=600&model=flux-3d&nologo=true"
  alt="Product mockup"
/>

Markdown (for Documentation)

![Hero Image](https://image.pollinations.ai/prompt/abstract%20geometric%20pattern%2C%20gradient%20blue%20purple%2C%20modern%2C%20clean?width=1200&height=400&nologo=true)

Batch Generation Script (Node.js)

import fs from 'fs';
import https from 'https';

async function generateImage(prompt: string, filename: string, options = {}) {
  const { width = 1024, height = 1024, model = 'flux' } = options;
  const url = `https://image.pollinations.ai/prompt/${encodeURIComponent(prompt)}?width=${width}&height=${height}&model=${model}&nologo=true`;

  return new Promise((resolve, reject) => {
    https.get(url, (response) => {
      const file = fs.createWriteStream(filename);
      response.pipe(file);
      file.on('finish', () => {
        file.close();
        resolve(filename);
      });
    }).on('error', reject);
  });
}

// Generate multiple images
const assets = [
  { prompt: 'hero background, abstract waves, blue gradient', file: 'hero.png', width: 1920, height: 1080 },
  { prompt: 'user avatar placeholder, geometric face', file: 'avatar.png', width: 200, height: 200 },
  { prompt: 'empty state illustration, no results found', file: 'empty.png', width: 400, height: 300 },
];

for (const asset of assets) {
  await generateImage(asset.prompt, asset.file, { width: asset.width, height: asset.height });
  console.log(`Generated: ${asset.file}`);
}

Use Case Recipes

1. Landing Page Hero

https://image.pollinations.ai/prompt/modern%20SaaS%20dashboard%20floating%20in%20space%2C%20dark%20theme%2C%20glowing%20UI%20elements%2C%20professional%203D%20render%2C%20cinematic%20lighting%2C%208k%20uhd?width=1920&height=1080&model=flux&nologo=true

2. Team Member Avatars

https://image.pollinations.ai/prompt/professional%20headshot%2C%20friendly%20smile%2C%20neutral%20gray%20background%2C%20studio%20lighting%2C%20business%20casual?width=400&height=400&model=flux-realism&nologo=true

3. App Empty State

https://image.pollinations.ai/prompt/cute%20illustration%20of%20empty%20box%2C%20minimal%20flat%20design%2C%20soft%20pastel%20colors%2C%20friendly%2C%20vector%20style?width=400&height=300&model=flux-anime&nologo=true

4. Product Mockup

https://image.pollinations.ai/prompt/iPhone%2015%20mockup%20on%20wooden%20desk%2C%20coffee%20cup%2C%20minimal%2C%20lifestyle%20photography%2C%20warm%20lighting%2C%20professional?width=1200&height=800&model=flux-3d&nologo=true

5. Blog Featured Image

https://image.pollinations.ai/prompt/abstract%20visualization%20of%20artificial%20intelligence%2C%20neural%20networks%2C%20blue%20and%20purple%2C%20futuristic%2C%20clean?width=1200&height=630&model=flux&nologo=true

6. App Icon

https://image.pollinations.ai/prompt/minimalist%20app%20icon%2C%20letter%20A%2C%20gradient%20blue%20to%20purple%2C%20rounded%20corners%2C%20flat%20design%2C%20iOS%20style?width=512&height=512&model=flux&nologo=true

7. Background Pattern

https://image.pollinations.ai/prompt/seamless%20geometric%20pattern%2C%20subtle%20gray%20on%20white%2C%20minimalist%2C%20tileable%2C%20modern?width=512&height=512&model=flux&nologo=true

8. Feature Illustration

https://image.pollinations.ai/prompt/isometric%20illustration%20of%20cloud%20computing%2C%20servers%2C%20data%20flow%2C%20blue%20and%20white%2C%20clean%20vector%20style?width=800&height=600&model=flux&nologo=true

Best Practices

DO

  1. Use descriptive prompts - More detail = better results
  2. Include quality modifiers - "8k, professional, detailed"
  3. Specify the style - "photograph", "illustration", "3D render"
  4. Define lighting - "studio lighting", "natural light", "cinematic"
  5. Set appropriate dimensions - Match your actual use case
  6. Use seeds for consistency - Same seed = reproducible results
  7. Cache generated images - Save to CDN for production

DON'T

  1. Don't use generic prompts - "a picture of something"
  2. Don't request copyrighted content - No brand logos, celebrities
  3. Don't use in loops without throttling - Rate limits apply
  4. Don't skip the
    nologo=true
    param
    - Avoids watermarks
  5. Don't generate same image repeatedly - Use seed + cache

Rate Limits & Caching Strategy

Pollinations Rate Limits

TierLimitSignup
Anonymous1 req/15sNone
Seed (free)1 req/5sFree registration
Flower1 req/3sPaid

Production Caching Strategy

// Cache generated images to your CDN
async function getOrGenerateImage(prompt: string, options: ImageOptions) {
  const cacheKey = createHash('md5')
    .update(prompt + JSON.stringify(options))
    .digest('hex');

  // Check CDN cache first
  const cached = await cdn.get(`images/${cacheKey}.png`);
  if (cached) return cached.url;

  // Generate and cache
  const imageUrl = buildPollinationsUrl(prompt, options);
  const imageBuffer = await fetch(imageUrl).then(r => r.buffer());
  const cdnUrl = await cdn.upload(`images/${cacheKey}.png`, imageBuffer);

  return cdnUrl;
}

Troubleshooting

HTTP Error Codes & Solutions

Error CodeProviderMeaningSolution
200
Both✅ SuccessImage generated
400
BothBad RequestFix prompt (invalid characters, too long)
429
PollinationsRate LimitedWait 15s or switch to Stable Horde
500
BothInternal ErrorRetry once, then switch provider
502
PollinationsBad Gateway→ Use Stable Horde immediately
503
BothService Unavailable→ Use Stable Horde immediately
504
PollinationsGateway Timeout→ Use Stable Horde immediately
000
BothNetwork/DNS ErrorCheck internet, try Stable Horde

Common Issues & Fixes

IssueSolution
Claude Code stuckRun health check first, use fallback on 5xx
Slow generationUse
turbo
model (Pollinations) or reduce steps (Horde)
Poor qualityAdd quality modifiers, use
flux
or
flux-realism
Wrong styleSpecify style explicitly: "photograph", "illustration"
Watermark appearsAdd
nologo=true
parameter
Inconsistent resultsUse same
seed
parameter
Rate limitedWait 15s or use Stable Horde (no rate limits)
Image not loadingURL-encode the prompt properly
Stable Horde slowNormal: 30-120s queue time, be patient
Base64 decode failsEnsure you're getting the full
img
field

Quick Diagnostic Script (Content-Based)

#!/bin/bash
# diagnose-image-api.sh - Run this when image generation fails
# IMPORTANT: Uses CONTENT checking, not just HTTP status!

echo "=== Image API Diagnostics (Content-Based) ==="

# Test Pollinations with actual image download
echo -n "1. Pollinations.ai: "
TEMP_FILE=$(mktemp)
curl -s -L -o "$TEMP_FILE" --max-time 15 \
  "https://image.pollinations.ai/prompt/diagnostic%20test?width=64&height=64&nologo=true" 2>/dev/null
P_CONTENT=$(file -b "$TEMP_FILE" 2>/dev/null | cut -d',' -f1)

if [[ "$P_CONTENT" == "PNG image data" ]] || [[ "$P_CONTENT" == "JPEG image data" ]]; then
    echo "✅ HEALTHY (returns actual images)"
    P_HEALTHY=true
elif [[ "$P_CONTENT" == "ASCII text" ]]; then
    echo "❌ BROKEN (returns error text: $(head -c 50 "$TEMP_FILE"))"
    P_HEALTHY=false
elif [[ -z "$P_CONTENT" ]]; then
    echo "❌ TIMEOUT or empty response"
    P_HEALTHY=false
else
    echo "⚠️ UNKNOWN ($P_CONTENT)"
    P_HEALTHY=false
fi
rm -f "$TEMP_FILE"

# Test Stable Horde API
echo -n "2. Stable Horde: "
H_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 \
  "https://stablehorde.net/api/v2/status/heartbeat" 2>/dev/null || echo "TIMEOUT")
if [[ "$H_STATUS" == "200" ]]; then
    echo "✅ HEALTHY (API responding)"
    H_HEALTHY=true
else
    echo "❌ ISSUE ($H_STATUS)"
    H_HEALTHY=false
fi

# Test internet
echo -n "3. Internet: "
I_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 3 "https://google.com" 2>/dev/null || echo "TIMEOUT")
if [[ "$I_STATUS" == "200" || "$I_STATUS" == "301" ]]; then
    echo "✅ OK"
else
    echo "❌ NO INTERNET"
fi

echo ""
echo "=== Recommendation ==="
if [[ "$P_HEALTHY" == "true" ]]; then
    echo "✅ Use: Pollinations.ai (primary) - working normally"
elif [[ "$H_HEALTHY" == "true" ]]; then
    echo "🔄 Use: Stable Horde (fallback) - Pollinations is currently down"
    echo ""
    echo "Stable Horde usage:"
    echo "  1. POST to https://stablehorde.net/api/v2/generate/async"
    echo "  2. Poll https://stablehorde.net/api/v2/generate/check/{id}"
    echo "  3. Get result from https://stablehorde.net/api/v2/generate/status/{id}"
else
    echo "❌ Both services unavailable. Check internet connection."
fi

Integration with Frontend Design

When building websites/apps, this skill works seamlessly with frontend development:

  1. During Development: Use Pollinations URLs directly as placeholders
  2. Before Production: Generate final images and save to your CDN
  3. For Dynamic Content: Use the API with proper caching
// Development: Direct URL (fast iteration)
<img src="https://image.pollinations.ai/prompt/..." />

// Production: Cached on your CDN
<img src="https://your-cdn.com/images/hero-cached.png" />

Activation Keywords

This skill activates automatically when you mention:

  • "generate an image", "create a picture", "make an illustration"
  • "hero image for", "banner for", "background for"
  • "mockup of", "product shot", "app icon"
  • "placeholder image", "avatar", "thumbnail"
  • "illustration of", "graphic of", "visual for"
  • Any image asset request during web/app development

Documentation Site Assets (SpecWeave Brand)

When generating images for SpecWeave documentation sites, use these brand guidelines:

Brand Colors for Prompts

ColorHexUsage
Primary Purple#7c3aedMain brand color, gradients
Purple Dark#6d28d9Accents, shadows
Purple Light#a78bfaHighlights, glows
Purple Darkest#5b21b6Deep backgrounds

Include in prompts:

purple violet gradient #7c3aed
,
professional SaaS aesthetic

Standard Docs Dimensions

Asset TypeWidthHeightModelUsage
Hero Banner19201080fluxHomepage hero, landing pages
Feature Card800600fluxFeature illustrations
Section Header1200400fluxSection banners
Icon6464fluxNavigation, feature icons
Empty State400300flux-animeEmpty states, placeholders
Social Card1200630fluxOG images, social sharing

Docs-Specific Prompt Templates

Asset TypePrompt Pattern
Hero
[concept] in abstract form, purple gradient #7c3aed to #a78bfa, professional SaaS, glowing nodes, dark background, 8k, clean minimal
Feature Illustration
isometric illustration of [feature], purple accent #7c3aed, white background, clean vector style, professional
Section Banner
abstract [theme] visualization, flowing lines, purple gradient #7c3aed, minimal, professional, wide format
Icon
minimal icon [concept], purple fill #7c3aed, white background, app icon style, centered, simple
Living Docs
interconnected documents with glowing purple connections #7c3aed, network visualization, professional, clean
Agent System
AI agents as geometric shapes in orbital formation, purple violet theme #7c3aed, futuristic, professional
Workflow
branching flowchart paths, glowing circuit lines, purple gradient #7c3aed, decision tree visualization, minimal

SpecWeave Docs Ready-to-Use URLs

Living Documentation Illustration:

https://image.pollinations.ai/prompt/interconnected%20hexagonal%20document%20nodes%20forming%20network%2C%20glowing%20purple%20connections%20%237c3aed%2C%20gradient%20to%20%23a78bfa%2C%20professional%20SaaS%2C%20dark%20background%2C%208k%2C%20minimal%20vector?width=800&height=600&model=flux&nologo=true&seed=42

Multi-Agent System Illustration:

https://image.pollinations.ai/prompt/interconnected%20AI%20agents%20as%20geometric%20avatars%20in%20orbital%20formation%2C%20purple%20violet%20theme%20%237c3aed%2C%20futuristic%20holographic%2C%20professional%2C%20clean%20dark%20background%2C%208k?width=800&height=600&model=flux&nologo=true&seed=42

Workflow/Decision Tree Illustration:

https://image.pollinations.ai/prompt/branching%20flowchart%20paths%20made%20of%20glowing%20circuit%20lines%2C%20purple%20gradient%20%237c3aed%20to%20%23a78bfa%2C%20decision%20trees%2C%20minimal%20geometric%2C%20professional%2C%20dark%20background?width=800&height=600&model=flux&nologo=true&seed=42

Related Skills

  • frontend-design: For UI/UX design patterns
  • browser-automation: For screenshot capture
  • docusaurus: For documentation site setup
  • technical-writing: For documentation content

Project-Specific Learnings

Before starting work, check for project-specific learnings:

# Check if skill memory exists for this skill
cat .specweave/skill-memories/image-generation.md 2>/dev/null || echo "No project learnings yet"

Project learnings are automatically captured by the reflection system when corrections or patterns are identified during development. These learnings help you understand project-specific conventions and past decisions.