Back to Blog
Case Study
9 min read

Case Study: Our Newsletter Generates Its Own Hero Images

Real production setup: Candlewood Lake hyperlocal newsletter uses AI writer/editor agents that call MediaEngine POST /api/jobs with nano-banana. Hero images auto-attached. ~13s generation, 1 credit each.

Automation
Content pipeline
Real-world example
Newsletter

The Setup

We operate a hyperlocal newsletter covering the Candlewood Lake region (CT). The publication automates content discovery, article writing, and image generation.

**Stack:** - Claude agents for research and writing - MediaEngine for hero image generation - A standard newsletter platform for distribution - Cadence: recurring editions, each with a generated hero

The Challenge

Manual hero image selection was the bottleneck. Writers would finish articles, then we'd spend 10-15 minutes searching stock sites or generating images manually. It broke the automation flow.

**Goal:** Generate hero images automatically as part of the writing pipeline, zero manual touch.

The Solution

Architecture

1. Agent writes article → outputs JSON:
   {
     "title": "Summer Parking Changes Coming to Lake Road",
     "summary": "Town announces new parking restrictions...",
     "content": "..."

2. Trigger hero image generation: POST https://api.mcpmediaengine.com/api/jobs { "type": "image", "model": "nano-banana", "inputParams": { "prompt": "Summer lake town scene, parking lots, no text, no faces", "aspect_ratio": "16:9" }, "idempotencyKey": "candlewood-summer-parking-changes" }

3. Poll job status every 2 seconds until complete: GET https://api.mcpmediaengine.com/api/jobs/{jobId}

4. Attach result to article: { ...article, "heroImageUrl": "https://storage.../hero.jpg" }

5. Push to the newsletter platform, schedule send ```

Code Example

async function publishNewsletterArticle(article: {
  title: string;
  summary: string;
  content: string;
}) {

// Step 1: Generate hero image const jobResponse = await fetch( 'https://api.mcpmediaengine.com/api/jobs', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.MEDIA_ENGINE_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ type: 'image', model: 'nano-banana', inputParams: { prompt: `Candlewood Lake region scene: ${article.title}, no text, no faces`, aspect_ratio: '16:9' }, idempotencyKey: `candlewood-${slugify(article.title)}` }) } );

const { data: job } = await jobResponse.json();

// Step 2: Poll for completion let result; let attempts = 0; while (attempts < 30) { const statusResponse = await fetch( `https://api.mcpmediaengine.com/api/jobs/${job.mediaJobId}`, { headers: { 'Authorization': `Bearer ${process.env.MEDIA_ENGINE_API_KEY}` } } ); result = await statusResponse.json();

if (result.data.status === 'done') break; if (result.data.status === 'failed') throw new Error(`Job failed: ${result.data.errorMessage}`);

await new Promise(r => setTimeout(r, 2000)); // Wait 2s before retry attempts++; }

const generationTime = Date.now() - startTime;

// Step 3: Publish to the newsletter platform with image await newsletter.articles.create({ title: article.title, content: article.content, heroImageUrl: result.outputs[0].url, metadata: { generatedHeroTime: `${generationTime}ms`, mediaEngineJobId: job.mediaJobId } });

console.log(`Published ${article.title} in ${generationTime}ms`); } ```

Results

Time

  • **Manual selection:** 10-15 minutes per article
  • **Automated generation:** 13-15 seconds wall-clock time (agent writes in parallel, image generates async)

Cost

  • 15 articles/month × 1 credit = 15 credits
  • Monthly cost: **$1.09** (amortized from Starter plan)

Quality

Image results are "on-brand" because we control the prompt. Examples: - Watercolor lake scenes for nature articles - Town square photos for community news - Neighborhood street scenes for real estate updates

All images are: - Aspect ratio 16:9 (consistent) - No text or faces (no copyright issues) - Candlewood-themed (regionally relevant)

The Idempotency Key

Notice the idempotency key:

idempotencyKey: `candlewood-${slugify(article.title)}`

This prevents duplicate image generation if the agent crashes mid-publish. On retry, MediaEngine returns the original job instead of re-generating.

**Result:** No wasted credits, no duplicate images in archives.

What We Learned

1. Prompts Matter

Generic prompts ("a lake") produce generic images. Specific prompts ("Candlewood Lake waterfront at sunset, summer, sailboats on water") produce on-brand results.

2. Watercolor Transforms Work

We apply watercolor transforms to some images for a consistent aesthetic. At 0.8 denoising strength, results are reliable. Never apply clay or material transforms — they fail.

3. Async is Essential

Synchronous image generation would block the publishing pipeline. Async with polling lets us parallelize: write article, generate image, publish all together.

4. QA is Optional but Recommended

We don't manually QA every image (time/cost trade-off). For high-profile articles, we generate 3 variations and pick the best. For routine posts, we auto-publish.

**Cost/benefit:** 2 minutes QA per 10 articles = net positive time savings.

5. Batch Runs (Weekly Publishes)

Every Sunday, we publish 4 articles. Generating 4 images sequentially = 60s; parallel = 15s.

We batch all 4 job submissions at once, then poll all in parallel. **Net time: ~30 seconds**.

Scaling Strategy

As we grow, we plan to:

1. **Increase to daily publishing** — Hermes agents will write 1-2 posts daily, auto-publish with hero images 2. **Add social media variants** — Generate 1:1 (Instagram), 2:3 (Pinterest), 16:9 (LinkedIn) from each article via img2img 3. **Add video intro frames** — Use gpt-image-2 for higher-quality video thumbnails (4 credits vs. 1 for nano)

**Projected monthly cost at daily publishing:** ~$35-50 (Starter plan + small overage).

Key Takeaway

Automating hero image generation collapsed our content bottleneck. What was 10-15 minutes of manual work per article is now 15 seconds of async generation. The newsletter now publishes on schedule, every time, without human touch.

MediaEngine fit because it's: - **Fast** (nano-banana in ~13s) - **Cheap** (1 credit per image) - **Async** (polling/webhooks, no blocking) - **Idempotent** (retry-safe via keys)

Next Steps

  • Deploy this pattern for your own content pipeline
  • Review [cost optimization strategies](/blog/how-much-does-ai-image-generation-cost-for-an-automated-content-pipeline) for scaling
  • Explore [style transforms](/blog/ai-image-styles-compared-watercolor-cartoon-claymation) for visual variety
Share this article