How to Autogenerate Images for New Blog Posts
Build a reliable pipeline that turns a new blog post into a reviewed, optimized featured image automatically.
To automatically create an image for every new blog post, build a trigger-to-publish pipeline:
- Detect a new draft or title.
- Extract the subject, audience, mood, composition, and aspect ratio.
- Send a structured prompt to an image-generation API or WordPress-native AI feature.
- Validate the result for prompt compliance, readable text, faces, logos, and prohibited content.
- Convert or compress the file.
- Upload it to your CMS and set it as the featured image.
- Generate descriptive alt text.
- Keep the post in review until a human approves the asset.
This design works with a server-side worker, WordPress, n8n, Zapier, or another workflow tool. The examples below use OpenAI’s Image API because it exposes explicit controls for model, size, quality, output format, compression, and background. The Image API guide documents generation and editing; the image-generation documentation covers the available parameters.
1. Define the image contract before generating
Automation becomes dependable when every post supplies the same fields. Store these values with the draft or derive them from the title and body:
| Field | Example | Why it matters |
|---|---|---|
| Topic | “How to cache API responses” | Controls the visual subject. |
| Audience | Backend developers | Sets the level and visual language. |
| Mood | Clear, technical, calm | Prevents random stylistic drift. |
| Composition | Server rack, request arrows, isolated subject | Leaves room for cropping and overlays. |
| Aspect ratio | 16:9 | Matches the card or hero slot. |
| Brand constraints | Palette, illustration style, no logos | Improves consistency and reduces legal risk. |
| Output | WebP, quality 80 | Controls file size and delivery cost. |
Keep the prompt template in version control. A version number in each generation record lets you reproduce an image or regenerate a series after a style change.
2. Choose an implementation surface
| Approach | Best for | Strengths | Watch-outs |
|---|---|---|---|
| Image API | A server job that creates one image per post | Explicit control over model, size, quality, format, edits, and storage | You own credentials, retries, storage, and WordPress upload logic. |
| Responses API image tool | Iterative or multi-turn workflows | Can use conversation context and image inputs for generation or edits | Requires more orchestration and state management. |
| WordPress connectors and AI Client | Teams that want generation inside WordPress | Dashboard and PHP/REST integration | Availability depends on WordPress version, connector, and provider. |
| WordPress plugin | Editors who want a ready-made UI or REST endpoint | Can provide editor actions, media-library generation, and capability-checked endpoints | Check maintenance, permissions, privacy, cost, and provider support. |
| n8n or Zapier workflow | Scheduled, multi-system publishing | Connects intake, prompting, generation, upload, and scheduling | Community examples do not guarantee vendor support or reliability. |
WordPress documents provider connections under Settings > Connectors. WordPress 7.0’s AI Client provides generate_image() and generate_images(); see the AI Client documentation. A plugin can expose a capability-checked REST endpoint for bulk automation, but review its permissions and maintenance before production.
3. Build the generation prompt
Use the article itself as context, but keep the visual instruction separate from editorial claims. A useful template is:
Generate a 16:9 editorial illustration for a developer blog post.
Topic: {{title}}
Audience: {{audience}}
Core concept: {{summary}}
Visual subject: {{subject}}
Composition: {{composition}}
Mood: {{mood}}
Style: {{brand_style}}
Use a clear focal point and leave safe space around the edges for cropping.
Do not include words, letters, logos, watermarks, recognizable brands, or UI copy.
Do not depict claims that are not supported by the article.
For most featured images, landscape dimensions are appropriate. OpenAI documents square, landscape, portrait, and custom dimension constraints, along with PNG, JPEG, and WebP output options. Select quality based on the visual complexity and your budget; use a smaller output when the image will only appear as a card.
4. Complete Python pipeline with the Image API
The following worker reads a title, generates an image, validates basic properties, converts it to WebP, and leaves a file ready for your CMS upload. Install dependencies with pip install openai pillow and set OPENAI_API_KEY.
import base64
import io
import os
from pathlib import Path
from PIL import Image
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
TITLE = "How to cache API responses"
SUMMARY = "A practical guide to reducing repeated backend requests with safe cache invalidation."
OUTPUT = Path("featured-image.webp")
prompt = f"""Generate a 16:9 editorial illustration for a developer blog post.
Topic: {TITLE}
Audience: backend developers
Core concept: {SUMMARY}
Visual subject: a web request passing through a cache before reaching an origin server
Composition: one clear focal point, directional flow, generous margins for cropping
Mood: clear, technical, calm
Style: modern flat editorial illustration with restrained blue and orange accents
Do not include words, letters, logos, watermarks, or UI copy.
Do not depict unsupported claims."""
result = client.images.generate(
model="gpt-image-1",
prompt=prompt,
size="1536x1024",
quality="medium",
output_format="png",
)
item = result.data[0]
if not item.b64_json:
raise RuntimeError("The image response did not contain base64 image data")
raw = base64.b64decode(item.b64_json)
image = Image.open(io.BytesIO(raw)).convert("RGB")
if image.width / image.height < 1.4:
raise RuntimeError(f"Unexpected aspect ratio: {image.size}")
image.save(OUTPUT, "WEBP", quality=82, method=6)
print(f"Wrote {OUTPUT} ({OUTPUT.stat().st_size} bytes)")
Store the prompt, model, dimensions, quality, output format, file hash, and generation timestamp with the post. If the API returns a refusal, timeout, or malformed output, mark the image step failed and keep the post in draft.
5. Node.js version
Install the SDK with npm install openai sharp. This example writes a compressed WebP file.
import fs from "node:fs/promises";
import OpenAI from "openai";
import sharp from "sharp";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const title = "How to cache API responses";
const prompt = `Generate a 16:9 editorial illustration for a developer blog post.
Topic: ${title}
Audience: backend developers
Core concept: a request passing through a cache before reaching an origin server
Composition: one focal point, directional flow, safe margins
Style: modern flat editorial illustration
Do not include words, letters, logos, watermarks, or UI copy.`;
const result = await client.images.generate({
model: "gpt-image-1",
prompt,
size: "1536x1024",
quality: "medium",
output_format: "png",
});
const base64 = result.data?.[0]?.b64_json;
if (!base64) throw new Error("Image response did not contain base64 data");
await sharp(Buffer.from(base64, "base64"))
.resize({ width: 1536, height: 1024, fit: "cover" })
.webp({ quality: 82 })
.toFile("featured-image.webp");
6. cURL request
For a direct HTTP job, send a multipart request to the Images API. Check the current API reference for the exact model and account access available to your project.
curl https://api.openai.com/v1/images/generations \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-1",
"prompt": "16:9 editorial illustration for a developer blog post about caching API responses; clear technical composition; no words, letters, logos, watermarks, or UI copy",
"size": "1536x1024",
"quality": "medium",
"output_format": "png"
}'
The response contains image data according to the selected output mode. Decode base64 data or download the returned URL before it expires, then store the resulting file in durable object storage.
7. Upload and set the WordPress featured image
After generation, upload the binary to WordPress's media endpoint, then update the post's featured_media field. The account used by the worker needs permission to upload media and edit the target post.
curl -X POST "https://example.com/wp-json/wp/v2/media" \
-u "$WP_USER:$WP_APP_PASSWORD" \
-H "Content-Disposition: attachment; filename=featured-image.webp" \
-H "Content-Type: image/webp" \
--data-binary @featured-image.webp
curl -X POST "https://example.com/wp-json/wp/v2/posts/123" \
-u "$WP_USER:$WP_APP_PASSWORD" \
-H "Content-Type: application/json" \
-d '{"featured_media":456,"status":"draft"}'
Use the returned media ID, not the filename, when updating the post. Generate alt text from the actual image and article context, then have an editor verify that it describes visible content rather than repeating the headline.
8. Validate every generated image
Validation should happen before upload or before the post can move to scheduled status.
- Dimensions: confirm the expected aspect ratio and minimum pixel size.
- File integrity: decode the image and reject corrupt or empty files.
- Prompt compliance: check subject, mood, composition, and prohibited elements.
- Text quality: reject accidental letters or unreadable generated text. The safest default for blog art is no text.
- Brand safety: look for accidental logos, trademarks, recognizable people, or misleading charts.
- Editorial accuracy: ensure the image does not imply a result or statistic the article does not support.
- Accessibility: write concise alt text describing what is visible and useful to someone who cannot see the image.
- File size: compress and verify that the final asset fits your page-performance budget.
Treat generated assets as draft creative work. OpenAI's publication policy says that a human must take ultimate responsibility for published content; its service terms also address infringement claims and rights to supplied inputs. Keep a human approval state in the workflow.
9. Add retries, idempotency, and a fallback
- Create a stable job key from the post ID and prompt version.
- Write the job state before calling the image provider.
- Retry transient network errors with exponential backoff and a maximum attempt count.
- Do not retry validation failures indefinitely; send them to review with the failure reason.
- Store the provider response, file hash, and status transition.
- If generation times out, is moderated, or produces an unusable image, leave the post in draft and attach a reviewed fallback image.
- Make upload and post-update operations idempotent so a retry cannot create duplicate media.
state = {
"job_key": f"post-{post_id}-image-v3",
"status": "queued",
"attempt": 0,
"prompt_version": "v3",
"fallback_media_id": 42,
}
# Persist state before generation. On restart, resume from the last completed step.
10. n8n or Zapier workflow design
A no-code or low-code workflow can use these steps:
- Trigger: new WordPress draft, database row, RSS item, or webhook.
- Normalize: extract title, excerpt, category, audience, and brand style.
- Prompt: build the versioned image brief.
- Generate: call the provider's image action.
- Inspect: validate dimensions, file type, prohibited elements, and response status.
- Transform: convert to WebP or JPEG and apply a size limit.
- Upload: create the WordPress media item.
- Alt text: generate and route it through review.
- Approve: notify an editor or keep the post in draft.
- Publish: set
featured_mediaand schedule only after approval.
Use a dead-letter path for failures. Community workflow examples can accelerate setup, but verify provider support, permissions, privacy, and maintenance before relying on them for production publishing.
11. Performance, reliability, and cost
| Concern | Practical choice |
|---|---|
| Latency | Run generation asynchronously after the draft is saved; do not block the editor request. |
| Throughput | Queue jobs and cap concurrency to your provider limits. |
| Retries | Retry transient failures with backoff; route refusals and validation failures to review. |
| Storage | Keep the original and optimized derivative only when you need both. |
| Bandwidth | Serve WebP or JPEG derivatives sized for the actual card and hero slots. |
| Budget | Choose output dimensions and quality deliberately; avoid regenerating unchanged posts. |
| Consistency | Version prompts and brand instructions; record every generation input. |
| Observability | Log job duration, provider status, validation result, file size, and publication state. |
The reported figure of more than 130 million users creating over 700 million images in ChatGPT's first week is an adoption figure, not evidence that automated blog images improve rankings, traffic, or conversions. There is no authoritative benchmark for those outcomes in the supplied research.
12. Troubleshooting
| Error or symptom | Likely cause | Fix |
|---|---|---|
| 401 or 403 response | Missing, invalid, or unauthorized API key | Check the environment variable, project permissions, and account access. |
| 429 response | Rate or usage limit | Queue requests, reduce concurrency, back off, and review account limits. |
| Timeout | Provider latency or a blocked worker request | Use an asynchronous queue, a longer job timeout, retry with backoff, and preserve draft status. |
| Image contains random text or logos | Prompt ambiguity or model artifact | Explicitly prohibit text and logos, validate the output, and regenerate or use a fallback. |
| Wrong crop in cards | Subject is too close to an edge | Request safe margins and generate at the target landscape ratio. |
| Huge file | Lossless output or oversized dimensions | Convert to WebP or JPEG, set quality, and create derivatives. |
| Duplicate media after retry | Upload step is not idempotent | Use a job key or file hash to find an existing attachment before uploading. |
| Post publishes without an image | Workflow advanced before upload or review completed | Require successful media ID and human approval as publish conditions. |
| Alt text describes the headline | Alt text was generated from metadata only | Generate it from the actual image and verify visible details manually. |
13. Or skip the browser setup
If the image you need is a screenshot of a live page rather than generated artwork, ScreenshotNeo returns a PNG, JPEG, WebP, or PDF from one GET request. Its API accepts the URL and supports full-page capture, element selectors, custom CSS and JavaScript, device presets, dark mode, cookies, headers, waiting rules, blocking controls, resizing, caching, signed links, asynchronous jobs, bulk capture, and PDF options.
Use the ScreenshotNeo API documentation for the complete parameter list:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' }); const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and each response reports the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Start with the free ScreenshotNeo account.
14. Publication checklist
- Topic, audience, mood, composition, and ratio are present.
- Prompt version and generation metadata are stored.
- Image decodes successfully at the expected dimensions.
- No accidental text, logos, misleading charts, or unsupported claims are visible.
- File is compressed for the target placement.
- Alt text describes the visible image.
- Media upload returned a valid ID.
- Post remains draft until human approval.
- Fallback asset and failure notification are configured.
- Prompt, model, dimensions, file hash, reviewer, and publication time are logged.
FAQ
Can the title alone produce a good image?
It can produce a starting point, but adding audience, subject, composition, mood, ratio, and exclusions makes results more consistent and easier to review.
Should every post have a unique prompt?
Use one versioned template for consistency, then fill it with post-specific fields. Change the template only when you intend to change the visual system.
Should generated images be published automatically?
Keep a human review gate. Generation can fail, include artifacts, or imply claims that the article does not make.
What format should a featured image use?
Use the format your CMS and delivery stack handle efficiently. WebP or JPEG derivatives are practical for most web cards; retain a higher-quality source when you need future crops.
Can this workflow generate several images?
Yes. The same queue can create a featured image and in-content illustrations, but validate and review each asset independently.


