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.
git clone https://github.com/majiayu000/claude-skill-registry
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"
skills/data/image-generation-anton-abyzov-specweave/SKILL.mdAI 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:
| Output | What To Do |
|---|---|
| ✅ Use Pollinations.ai URLs below |
| 🔄 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 Check | Meaning | Action |
|---|---|---|
| ✅ Healthy | Use Pollinations.ai |
| ✅ Healthy | Use Pollinations.ai |
| ❌ Service error (502/503 in body) | → Use Stable Horde |
| ❌ 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:
| Condition | Action | Max Attempts |
|---|---|---|
| Timeout | Switch provider | 1 |
| HTTP 5xx | Switch provider | 1 |
| "Could not process image" | Switch provider | 1 |
| Non-image response | Switch provider | 1 |
| Both providers fail | STOP and report | 0 |
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:
- The image file may be corrupted or incomplete (502 error in disguise)
- The image format is unsupported
- The image URL returned an error page, not actual image data
Action: Do NOT retry with Claude's Read tool. Instead:
- Download the image with curl first
- Verify it's actually an image:
file downloaded.png - 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
| Parameter | Values | Default | Description |
|---|---|---|---|
| 64-1024 (multiples of 64) | 512 | Image width |
| 64-1024 (multiples of 64) | 512 | Image height |
| 1-150 | 30 | Diffusion steps |
| 1-30 | 7.5 | Prompt adherence |
| k_euler_a, k_dpm_2, etc. | k_euler_a | Sampling method |
| ["stable_diffusion", "SDXL 1.0"] | auto | Model 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
| Parameter | Values | Default | Description |
|---|---|---|---|
| 256-2048 | 1024 | Image width in pixels |
| 256-2048 | 1024 | Image height in pixels |
| flux, turbo, flux-realism, flux-anime, flux-3d, flux-cablyai | flux | AI model to use |
| any integer | random | Reproducible results |
| true | false | Remove watermark |
| true | false | Prompt enhancement |
| true | false | Safety filter |
Available Models
| Model | Best For | Quality | Speed |
|---|---|---|---|
| General purpose, photorealistic | Highest | Medium |
| Ultra-realistic photos | Very High | Medium |
| Anime/illustration style | High | Fast |
| 3D renders, product mockups | High | Medium |
| Artistic, creative styles | High | Fast |
| Quick iterations, drafts | Medium | Fastest |
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 Case | Quality Modifiers |
|---|---|
| Website Hero | |
| Product Shot | |
| App Icon | |
| Illustration | |
| Avatar | |
| Background | |
Aspect Ratios for Common Use Cases
| Use Case | Width | Height | Ratio |
|---|---|---|---|
| Hero Banner | 1920 | 1080 | 16:9 |
| Social Media Post | 1200 | 1200 | 1:1 |
| Portrait/Avatar | 800 | 1200 | 2:3 |
| Product Card | 800 | 600 | 4:3 |
| Mobile Splash | 1080 | 1920 | 9:16 |
| App Icon | 512 | 512 | 1:1 |
| OG Image | 1200 | 630 | ~1.9:1 |
| Thumbnail | 400 | 300 | 4: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)

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
- Use descriptive prompts - More detail = better results
- Include quality modifiers - "8k, professional, detailed"
- Specify the style - "photograph", "illustration", "3D render"
- Define lighting - "studio lighting", "natural light", "cinematic"
- Set appropriate dimensions - Match your actual use case
- Use seeds for consistency - Same seed = reproducible results
- Cache generated images - Save to CDN for production
DON'T
- Don't use generic prompts - "a picture of something"
- Don't request copyrighted content - No brand logos, celebrities
- Don't use in loops without throttling - Rate limits apply
- Don't skip the
param - Avoids watermarksnologo=true - Don't generate same image repeatedly - Use seed + cache
Rate Limits & Caching Strategy
Pollinations Rate Limits
| Tier | Limit | Signup |
|---|---|---|
| Anonymous | 1 req/15s | None |
| Seed (free) | 1 req/5s | Free registration |
| Flower | 1 req/3s | Paid |
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 Code | Provider | Meaning | Solution |
|---|---|---|---|
| Both | ✅ Success | Image generated |
| Both | Bad Request | Fix prompt (invalid characters, too long) |
| Pollinations | Rate Limited | Wait 15s or switch to Stable Horde |
| Both | Internal Error | Retry once, then switch provider |
| Pollinations | Bad Gateway | → Use Stable Horde immediately |
| Both | Service Unavailable | → Use Stable Horde immediately |
| Pollinations | Gateway Timeout | → Use Stable Horde immediately |
| Both | Network/DNS Error | Check internet, try Stable Horde |
Common Issues & Fixes
| Issue | Solution |
|---|---|
| Claude Code stuck | Run health check first, use fallback on 5xx |
| Slow generation | Use model (Pollinations) or reduce steps (Horde) |
| Poor quality | Add quality modifiers, use or |
| Wrong style | Specify style explicitly: "photograph", "illustration" |
| Watermark appears | Add parameter |
| Inconsistent results | Use same parameter |
| Rate limited | Wait 15s or use Stable Horde (no rate limits) |
| Image not loading | URL-encode the prompt properly |
| Stable Horde slow | Normal: 30-120s queue time, be patient |
| Base64 decode fails | Ensure you're getting the full 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:
- During Development: Use Pollinations URLs directly as placeholders
- Before Production: Generate final images and save to your CDN
- 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
| Color | Hex | Usage |
|---|---|---|
| Primary Purple | #7c3aed | Main brand color, gradients |
| Purple Dark | #6d28d9 | Accents, shadows |
| Purple Light | #a78bfa | Highlights, glows |
| Purple Darkest | #5b21b6 | Deep backgrounds |
Include in prompts:
purple violet gradient #7c3aed, professional SaaS aesthetic
Standard Docs Dimensions
| Asset Type | Width | Height | Model | Usage |
|---|---|---|---|---|
| Hero Banner | 1920 | 1080 | flux | Homepage hero, landing pages |
| Feature Card | 800 | 600 | flux | Feature illustrations |
| Section Header | 1200 | 400 | flux | Section banners |
| Icon | 64 | 64 | flux | Navigation, feature icons |
| Empty State | 400 | 300 | flux-anime | Empty states, placeholders |
| Social Card | 1200 | 630 | flux | OG images, social sharing |
Docs-Specific Prompt Templates
| Asset Type | Prompt Pattern |
|---|---|
| Hero | |
| Feature Illustration | |
| Section Banner | |
| Icon | |
| Living Docs | |
| Agent System | |
| Workflow | |
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.