# Nano Banana Image Generator

> Generate AI images using Nano Banana Pro (Gemini). Use this skill when the user needs images - thumbnails, social posts, blog headers, or creative visuals. Follows an iterative workflow - brainstorm concepts, select direction, generate in multiple styles, then produce via API.

- **Type:** Skill
- **Install:** `agentstack add skill-cdeistopened-content-os-nano-banana-image-generator`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [cdeistopened](https://agentstack.voostack.com/s/cdeistopened)
- **Installs:** 0
- **Category:** [Content & Media](https://agentstack.voostack.com/c/content-and-media)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [cdeistopened](https://github.com/cdeistopened)
- **Source:** https://github.com/cdeistopened/content-os/tree/main/skills/content/nano-banana-image-generator

## Install

```sh
agentstack add skill-cdeistopened-content-os-nano-banana-image-generator
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Nano Banana Image Generator

Generate professional, non-generic images using Nano Banana Pro (Gemini API).

## Workflow Overview

1. **Brainstorm Concepts** - Generate 4-6 high-level visual ideas
2. **Select Direction** - User picks the concept they like
3. **Source Reference Photos** - Find high-res images of real people/places (if applicable)
4. **Optimize Prompt** - Refine into a strong, detailed prompt
5. **Style Variations** - Adapt to 2-3 different visual styles
6. **Generate Images** - Run via Gemini API

## Step 1: Brainstorm Concepts

### When to Ask Clarifying Questions

Before brainstorming, assess if you have enough information. Ask 2-4 focused questions if:
- **Subject** is unclear or too generic
- **Purpose/Context** is missing (what's this for?)
- **Style** preferences are unspecified
- **Text requirements** are ambiguous

**Skip questions if:** The user provides a detailed brief or says "just generate it." Don't create friction when the request is already clear.

**Example:**
> User: "Can you write me a prompt for a hero image for my landing page?"
>
> You: "A few quick questions:
> 1. What's the product/service?
> 2. Any specific mood - modern/minimal, bold/energetic, warm/approachable?
> 3. Should there be text in the image itself?"

### Generating Concepts

When the user provides a topic or use case, generate 4-6 high-level visual concepts. Each concept should be:

- **One sentence** describing the visual idea
- **Concrete and immediate** - you can picture it instantly
- **Conceptual but not abstract** - a clear object/scene with meaning
- **Non-generic** - avoid cliches (no lightbulbs for ideas, no books for education)

**Format:**

```
1. **[Short label]** - One sentence description of the visual concept and why it works.

2. **[Short label]** - One sentence description...
```

**Example for "newsletter about self-directed learning":**

```
1. **Compass with crayon needle** - A compass where the needle is a crayon, suggesting direction comes from the learner's own hand.

2. **Path that branches into many paths** - A single dirt path splitting into dozens of colorful trails, each heading somewhere different.

3. **Empty frame on an easel** - A blank canvas on an easel in a field, suggesting the learner creates their own picture.

4. **Backpack with roots** - A school backpack sitting on grass, but roots are growing out the bottom into the soil - learning that plants itself.
```

Wait for user to select before proceeding.

## Step 2: Source Reference Photos (Person-Based Images)

When generating images that depict a real person (tribute posters, portraits, editorial illustrations featuring someone's likeness), you **must** source a high-resolution reference photo before generating.

### Why This Matters

- Input photo resolution directly determines output quality. A 283px input produces a blurry, unusable output. A 1920px+ input produces sharp, detailed results.
- The model needs a clear, well-lit photo to capture likeness accurately.
- Photo era matters: a 1913 photo of someone will produce a young-looking result even if the prompt says "elderly."

### Process

1. **Search for the person** using WebSearch or WebFetch. Look for:
   - Official organization pages (foundations, universities, publishers)
   - Wikipedia/Wikimedia Commons (check actual resolution - thumbnails are too small)
   - Library of Congress, public domain archives
   - Professional photography sites, press kits

2. **Verify resolution before downloading.** Target minimum 1000px on the longest edge, ideally 1920px+. Check the actual image dimensions, not the page thumbnail.

3. **Verify the era/age.** If the content discusses someone in their later years, don't use a photo from their twenties. Match the photo to the narrative.

4. **Download and save** to the same output directory as the final images, with a descriptive name:
   - `{name}-reference-hires.jpg` - Primary reference photo
   - `{name}-reference-{year}.jpg` - If era-specific (e.g., `montessori-reference-1946.jpg`)

5. **Use with `--input` flag** when generating:
   ```bash
   python generate_image.py "prompt describing the style..." \
     --input path/to/reference-hires.jpg \
     --model pro --aspect 16:9
   ```

### Resolution Quick Reference

| Input Resolution | Output Quality |
|-----------------|---------------|
| < 500px | Unusable - blurry, distorted |
| 500-999px | Marginal - may work for stylized illustrations |
| 1000-1920px | Good - suitable for most uses |
| 1920px+ | Excellent - sharp detail, accurate likeness |

### Troubleshooting Likeness

- **Doesn't look like them?** Try a different reference photo with clearer facial features and better lighting.
- **Wrong age?** Find a photo from the correct era.
- **Wikimedia rate-limiting (429)?** Use alternative sources (LOC, official sites, press kits).

## Step 3: Optimize the Prompt

Once the user selects a concept, develop it into a full prompt. Structure:

```
Create a [style type] illustration of [subject].

CONCEPT: [Expand the one-sentence idea into a clear visual description]

STYLE: [Artistic approach - load from references/styles/ if brand-specific]

COMPOSITION: [Framing, focal point, negative space, balance]

COLORS: [Palette - describe by name, not hex codes which may render as text]

TEXTURE: [Surface qualities, analog/digital feel]

AVOID: [What should NOT appear - be specific]

FORMAT: [Aspect ratio]
```

**Key principles:**
- Natural language, full sentences - no tag soup
- Describe colors by name (burnt orange, sky blue, near-black) not hex codes
- Maximum 2-3 elements - if it feels busy, remove something
- Favor metaphor over literal depiction

## Step 3: Style Variations

Adapt the optimized prompt to 2-3 different styles from `references/styles/`:

- **watercolor-line.md** - Ink linework with watercolor washes, warm **(DEFAULT for thumbnails)**
- **opened-editorial.md** - Conceptual, brand colors, editorial wit
- **minimalist-ink.md** - High-contrast black and white, crosshatching
- **newyorker-cartoon.md** - Single-panel observational humor, crosshatching, italic serif caption **(for editorial commentary)**

**Default behavior:** For blog thumbnails and article headers, use watercolor-line style unless otherwise specified. This style provides warmth and approachability while maintaining editorial quality.

**New Yorker style:** When user asks for "New Yorker cartoon," "editorial cartoon," or observational humor illustrations, load `references/styles/newyorker-cartoon.md` for the full style guide including caption formulas, humor principles, and prompt template.

**For comic ideation:** Use the `single-panel-comic` skill first to generate concepts and captions using Elijah's formula library, then return here for image generation. The workflow is:
```
single-panel-comic (ideation + caption) → nano-banana-image-generator (visual)
```

Present all variations to user so they can choose which to generate, or generate all.

## Step 4: Generate via API

### Setup

The Gemini API key is stored in the vault root `.env` file. The script looks for `GEMINI_API_KEY` or `GOOGLE_API_KEY`.

**Requirements:** `pip install google-genai pillow`

### Running the Script

The script lives at `.claude/skills/nano-banana-image-generator/scripts/generate_image.py`.

```bash
# From the OpenEd Vault root directory:
cd "/Users/charliedeist/Library/Mobile Documents/com~apple~CloudDocs/Root Docs/OpenEd Vault"

# Set the API key and run
export GEMINI_API_KEY=$(grep GEMINI_API_KEY .env | cut -d'=' -f2) && \
python ".claude/skills/nano-banana-image-generator/scripts/generate_image.py" \
  "Your prompt here" \
  --model pro \
  --aspect 16:9 \
  --output "Studio/Content Engine Deck" \
  --name "my-image"
```

**Options:**
- `--model pro` (higher quality, supports aspect ratio) or `--model flash` (faster, cheaper)
- `--aspect 16:9`, `1:1`, `9:16`, `3:4`, `4:3` (only works with pro model)
- `--variations N` - generate N versions
- `--output ./path` - save location (default: current directory)
- `--name prefix` - filename prefix (legacy, prefer `--seo-name`)
- `--input path/to/image.png` - use a reference image for rework/edit mode
- `--seo-name slug` - SEO-friendly filename (e.g. `john-taylor-gatto-education-reformer`). Output: `{slug}-gen.jpg`
- `--context "Article title or topic"` - generates alt text suggestion in the metadata sidecar

**Format detection:** The script detects the actual image format (JPEG vs PNG) from Gemini's response bytes and saves with the correct extension. No more `.png` files containing JPEG data.

**Metadata sidecar:** Every generated image gets a `.meta.json` file alongside it containing:
- `alt_text` - Auto-generated from prompt + context
- `keywords` - Extracted from context
- `original_format` - Detected format (jpeg/png)
- `dimensions` - Width and height in pixels
- `aspect_ratio` - The requested ratio
- `prompt_summary` - First 200 chars of the prompt
- `suggested_seo_name` - The seo-name if provided

**Note:** For flash model, aspect ratio config is ignored - include the ratio in your prompt text instead.

### SEO Workflow (Recommended for Blog Content)

For any blog article or SEO content, use the full SEO workflow:

```bash
# 1. Generate with SEO name and context
export GEMINI_API_KEY=$(grep GEMINI_API_KEY .env | cut -d'=' -f2) && \
python3 ".claude/skills/nano-banana-image-generator/scripts/generate_image.py" \
  "A watercolor illustration of a child building a treehouse" \
  --model pro --aspect 16:9 \
  --seo-name "project-based-learning-treehouse" \
  --context "How Project-Based Learning Transforms Homeschool Education" \
  --output "Studio/SEO Content Production/project-based-learning/"

# 2. Convert to WebP for web delivery
python3 ".claude/skills/nano-banana-image-generator/scripts/image_optimizer.py" \
  "Studio/SEO Content Production/project-based-learning/project-based-learning-treehouse-gen.jpg" \
  --use thumbnail

# Result: project-based-learning-treehouse-gen-thumbnail.webp (1200x675)
# Plus updated .meta.json with WebP path and dimensions
```

### Image Optimizer

The `image_optimizer.py` script converts images to WebP with target dimension presets. It keeps the original file intact (edit/rework needs the lossless source).

```bash
python3 ".claude/skills/nano-banana-image-generator/scripts/image_optimizer.py" \
  path/to/image.jpg --use thumbnail
```

**Presets:**

| Preset | Dimensions | Use Case |
|--------|-----------|----------|
| `thumbnail` | 1200x675 | Webflow blog thumbnails (16:9) |
| `social-square` | 1080x1080 | Instagram, LinkedIn square |
| `social-portrait` | 1080x1350 | Instagram portrait (4:5) |
| `inline` | max-width 800px | In-article images |

**Options:**
- `--quality N` - WebP quality 1-100 (default: 85)
- `--output ./path` - output directory (default: same as input)

The optimizer updates the `.meta.json` sidecar with `webp_path`, `webp_dimensions`, and `webp_preset`.

### Editing Existing Images

To modify an existing image, use the `--input` flag with a path to the source image:

```bash
export GEMINI_API_KEY=$(grep GEMINI_API_KEY .env | cut -d'=' -f2) && \
python ".claude/skills/nano-banana-image-generator/scripts/generate_image.py" \
  "Add a striped shirt to the child. Remove the signature from the bottom right corner." \
  --input "Studio/Social Media/original-image.png" \
  --model pro \
  --aspect 1:1 \
  --output "Studio/Social Media" \
  --name "edited-image"
```

**Editing capabilities:**
- Add, remove, or modify visual elements
- Change clothing, backgrounds, or objects
- Remove unwanted text, signatures, or watermarks
- Adjust colors or style elements
- Keep specific elements while changing others

**Best practices for edit prompts:**
- Be explicit about what to change AND what to keep
- List changes as numbered items for clarity
- Say "Keep everything else exactly the same" to preserve other elements
- Use "Remove X" for deletions, "Change X to Y" for modifications

**Output location:** ALWAYS save images in the same folder as the content they belong to - not a generic images dump. This is critical for organization.

**Routing by content type:**

| Content Type | Output Location |
|--------------|-----------------|
| Newsletter | `Studio/OpenEd Daily Studio/[date-folder]/` |
| Podcast episode | `Studio/Podcast Studio/[episode-folder]/` |
| Blog article | `Studio/SEO Content Production/[article-folder]/` |
| Guest contributor | `Studio/SEO Content Production/Guest Contributors/[name]/` |
| Social media | `Studio/Social Media Transformation/[campaign]/` |
| Hub page | `Content/Open Education Hub/[topic]/` |

**Before generating:** Identify the content context and determine the correct output path. If a project folder exists, route there. If not, create the folder first.

**Naming convention:** Use descriptive prefixes that indicate purpose:
- `thumbnail-draft.png` - Working thumbnail
- `thumbnail-final.png` - Approved thumbnail  
- `header-[concept].png` - Article header
- `social-[platform].png` - Platform-specific social image

## Step 6: Iterate

After user reviews generated images:
- **80% good?** Use `--input` flag to make targeted changes to the existing image
- **Composition off?** Adjust framing or element placement in prompt
- **Wrong style?** Try a different style reference
- **Too busy?** Simplify to fewer elements
- **Colors wrong?** Be more explicit about palette

**When to regenerate vs. edit:**
- **Edit** when the image is mostly right but needs specific fixes (remove element, change clothing, fix text)
- **Regenerate** when the composition, style, or concept needs a complete rethink

## Prompting Principles

### Write Like a Creative Director

Brief the model like a human artist. Use proper grammar, full sentences, and descriptive adjectives.

| Don't | Do |
|-------|-----|
| "Cool car, neon, city, night, 8k" | "A cinematic wide shot of a futuristic sports car speeding through a rainy Tokyo street at night. The neon signs reflect off the wet pavement and the car's metallic chassis." |

**Be specific about:**
- **Subject:** Instead of "a woman," say "a sophisticated elderly woman wearing a vintage chanel-style suit"
- **Materiality:** Describe textures - "matte finish," "brushed steel," "soft velvet," "crumpled paper"
- **Setting:** Define location, time of day, weather
- **Lighting:** Specify mood and light source
- **Mood:** Emotional tone of the image

### Provide Context

Context helps the model make logical artistic decisions. Include the "why" or "for whom."

**Example:** "Create an image of a sandwich for a Brazilian high-end gourmet cookbook."
*(Model infers: professional plating, shallow depth of field, perfect lighting)*

### Keep It Simple

- One clear focal point
- Maximum 2-3 elements total
- Generous negative space
- If it feels busy, remove something

### Avoid the Generic

- No lightbulbs for "ideas"
- No stacks of books for "education"
- No happy children raising hands
- No glossy AI aesthetic

## Resources

### references/styles/
Brand and aesthetic style definitions:
- `opened-editorial.md` - OpenEd brand style
- `minimalist-ink.md` - Black and white ink illustration
- `watercolor-line.md` - Ink with watercolor washes
- `newyorker-cartoon.md` - New Yorker single-panel cartoon (crosshatching, understated humor, italic serif caption)

### references/concepts/
Saved prompts for reusable images:
- `paper-airplane-newsletter.md` - Newsletter header variations
- `ed-horse-error.md` - Ed mascot for error states
- `dual-exposure-tribute.md` - Photo-grid composite tribute posters (Instagram 1:1 + thumbnail 16:9)

### scripts/ (in this skill folder)
- `generate_image.py` - Gemini API image generation (Nano Banana / Nano Banana Pro)

## Prompt Modifiers Reference

| Category | Examples |
|----------|----------|
| **Lighting** | golden hour, dramatic shadows, soft diffused light, neon glow, overcast |
| **Style** | cinematic, editorial, technical diagram, hand-drawn, photorealistic |
| **T

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [cdeistopened](https://github.com/cdeistopened)
- **Source:** [cdeistopened/content-os](https://github.com/cdeistopened/content-os)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-cdeistopened-content-os-nano-banana-image-generator
- Seller: https://agentstack.voostack.com/s/cdeistopened
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
