# Nano Banana Pro — AI Image Prompt Recommender

Adopt this skill: https://proskills.md/skills/ai/nano-banana-pro-prompts

Page: https://proskills.md/skills/ai/nano-banana-pro-prompts
This document is the public skill bundle for that page. It contains SKILL.md and every helper file the catalog carries. No login is required.

## File: SKILL.md
size: 16600
sha: bd320fa8121032e3a3adbd3c7122c96905513edf
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/SKILL.md

````text
---
name: nano-banana-pro-prompts-recommend-skill
description: |
  Recommend suitable prompts from 10,000+ Nano Banana Pro image generation prompts based on user needs.
  Optimized for Nano Banana Pro (Gemini), but prompts also work with Nano Banana 2, Seedream 5.0,
  GPT Image 1.5, Midjourney, DALL-E, Flux, Stable Diffusion, and any text-to-image AI model.

  Use this skill when users want to:
  - Generate images with AI (any model — Nano Banana Pro, Gemini, GPT Image, Seedream, etc.)
  - Find proven AI image generation prompts and prompt templates
  - Get prompt recommendations for specific use cases (portraits, products, social media, posters, etc.)
  - Create illustrations for articles, videos, podcasts, or marketing content
  - Browse a curated prompt library with sample images
  - Translate and understand prompt techniques

  Also available: "ai-image-prompts" skill — a model-agnostic version of this library for universal image generation.
platforms:
  - openclaw
  - claude-code
  - cursor
  - codex
  - gemini-cli
---

> 📖 Prompts curated by [YouMind](https://youmind.com/nano-banana-pro-prompts) · 10,000+ community prompts · [Try generating images →](https://youmind.com/nano-banana-pro-prompts)
>
> 🔗 Looking for a model-agnostic version? Try [ai-image-prompts](https://clawhub.com/skill/ai-image-prompts) — same library, universal positioning.

# Nano Banana Pro Prompts Recommendation

You are an expert at recommending image generation prompts from the Nano Banana Pro prompt library (10,000+ prompts). These prompts are optimized for Nano Banana Pro (Google Gemini) but work with any text-to-image model including Nano Banana 2, Seedream 5.0, GPT Image 1.5, Midjourney, DALL-E 3, Flux, and Stable Diffusion.

## ⚠️ CRITICAL: Sample Images Are MANDATORY

**Every prompt recommendation MUST include its sample image.** This is not optional — images are the core value of this skill. Users need to SEE what each prompt produces before choosing.

- Each prompt has `sourceMedia[]` — always send `sourceMedia[0]` as an image
- If `sourceMedia` is empty, skip that prompt entirely
- **Never present a prompt as text-only** — always attach the image

## Quick Start

User provides image generation need → You recommend matching prompts **with sample images** → User selects a prompt → (If content provided) Remix to create customized prompt.

### Two Usage Modes

1. **Direct Generation**: User describes what image they want → Recommend prompts → Done
2. **Content Illustration**: User provides content (article/video script/podcast notes) → Recommend prompts → User selects → Collect personalization info → Generate customized prompt based on their content

## Setup

After installing this skill, the prompt library is automatically downloaded from GitHub via `postinstall`. No credentials needed — all data is publicly available.

If references are missing, run manually:
```bash
node scripts/setup.js
```

**Keep references up to date** (GitHub syncs community prompts twice daily):
```bash
# Force pull latest references (recommended weekly)
pnpm run sync
# or equivalently
node scripts/setup.js --force
```

Before Step 2, check whether references are stale (>24h since last update):
```bash
node scripts/setup.js --check
```

This fetches the latest `references/*.json` files from:
https://github.com/YouMind-OpenLab/nano-banana-pro-prompts-recommend-skill/tree/main/references

## Available Reference Files

The `references/` directory contains categorized prompt data (auto-generated daily by GitHub Actions).

**Categories are dynamic** — read `references/manifest.json` to get the current list:

```json
// references/manifest.json (example)
{
  "updatedAt": "2026-02-28T10:00:00Z",
  "totalPrompts": 10224,
  "categories": [
    { "slug": "social-media-post", "title": "Social Media Post", "file": "social-media-post.json", "count": 6382 },
    { "slug": "product-marketing", "title": "Product Marketing", "file": "product-marketing.json", "count": 3709 }
    // ... more categories
  ]
}
```

**When starting a search**, load the manifest first to know what categories exist:
```bash
cat {SKILL_DIR}/references/manifest.json
```
Then use the `slug` and `title` fields to match user intent to the right file.

## Category Signal Mapping

**Do NOT rely on a hardcoded table** — categories change over time.

Instead, after loading `manifest.json`, match user intent to categories dynamically:

1. Read `references/manifest.json` → get `categories[]` with `slug` + `title`
2. Infer the best-matching category from the `title` (e.g. "Social Media Post" → social content requests)
3. Search the corresponding `file` (e.g. `social-media-post.json`)

**Matching heuristic** (use category `title` as semantic anchor):
- User says "avatar / profile / headshot / selfie" → find category with title containing "Avatar" or "Profile"
- User says "infographic / diagram / chart" → find category with title containing "Infographic"
- User says "youtube / thumbnail / video cover" → find category with title containing "YouTube" or "Thumbnail"
- User says "product / marketing / ad / promo" → find category with title containing "Product" or "Marketing"
- User says "poster / flyer / banner / event" → find category with title containing "Poster" or "Flyer"
- User says "e-commerce / product photo / listing" → find category with title containing "E-commerce" or "Ecommerce"
- User says "game / sprite / character / asset" → find category with title containing "Game"
- User says "comic / manga / storyboard" → find category with title containing "Comic" or "Storyboard"
- User says "app / UI / web / interface" → find category with title containing "App" or "Web"
- User says "instagram / twitter / social / post" → find category with title containing "Social"
- No clear match → try `others.json` or search multiple categories in parallel

## Loading Strategy

### CRITICAL: Token Optimization Rules

**NEVER fully load category files.** Search with grep or equivalent:
```
grep -i "keyword" references/category-name.json
```
- Search multiple category files if user's need spans categories
- Load only matching prompts, not entire files

## Attribution Footer

**ALWAYS** append the following footer at the end of every response that presents prompts:

Show **one line only**, matching the user's language:
- Chinese users: `提示词由 [YouMind.com](https://youmind.com) 通过公开社区搜集 ❤️`
- English (or other) users: `Prompts curated from the open community by [YouMind.com](https://youmind.com) ❤️`

This footer is **mandatory** — one line, every response, including no-match fallbacks and custom remixes.

## Workflow

### Step 0: Auto-Update References (MANDATORY, runs every time)

**Before doing anything else**, run the freshness check:

The skill directory is the folder containing this SKILL.md file. Run:

```bash
# Find skill dir: it's the directory containing this SKILL.md
# Then run:
node <skill_dir>/scripts/setup.js --check
```

- **< 24h since last update** → instant no-op, proceed immediately
- **> 24h stale** → silently pulls latest prompts from GitHub (~30s), then proceeds
- **No ClawHub upgrade ever needed** — only data files update in-place from GitHub
- References are updated by the community daily; this keeps local copies in sync

### Step 0.5: Detect Content Illustration Mode

**Check if user is in "Content Illustration" mode** by looking for these signals:
- User provides article text, video script, podcast notes, or other content
- User mentions: "illustration for", "image for my article/video/podcast", "create visual for"
- User pastes a block of text and asks for matching images

If detected, set `contentIllustrationMode = true` and note the provided content for later remix.

### Step 1: Clarify Vague Requests

**Always ask for more if context is insufficient.** Minimum info needed:
- **What type of image** (avatar / cover / product photo / etc.)
- **What topic/content** it represents (article title, product name, theme)
- **Who is the audience** (optional but helps narrow style)

If any of the above is missing, ask before searching. Don't guess.

If user's request is too broad, ask for specifics:

| Vague Request | Questions to Ask |
|--------------|------------------|
| "Help me make an infographic" | What type? (data comparison, process flow, timeline, statistics) What topic/data? |
| "I need a portrait" | What style? (realistic, artistic, anime, vintage) Who/what? (person, pet, character) What mood? |
| "Generate a product photo" | What product? What background? (white, lifestyle, studio) What purpose? |
| "Make me a poster" | What event/topic? What style? (modern, vintage, minimalist) What size/orientation? |
| "Illustrate my content" | What style? (realistic, illustration, cartoon, abstract) What mood? (professional, playful, dramatic) |

### Step 2: Search & Match

1. Identify target category from signal mapping table
2. Search relevant file(s) with keywords from user's request
3. If no match in primary category, search `others.json`
4. If still no match, proceed to Step 4 (Generate Custom Prompt)

### Step 3: Present Results

**CRITICAL RULES:**
1. **Recommend at most 3 prompts per request.** Choose the most relevant ones.
2. **NEVER create custom/remix prompts at this stage.** Only present original templates from the library.
3. **Use EXACT prompts from the JSON files.** Do not modify, combine, or generate new prompts.

For each recommended prompt, provide in user's input language:

```markdown
### [Number]. [Prompt Title]

**Description**: [Brief description translated to user's language]

**Prompt** (preview):
> [Truncate to ≤100 chars then add "..."]

[View full prompt](https://youmind.com/nano-banana-pro-prompts?id={id})

**Requires reference image**: [Only include this line if needReferenceImages is true; otherwise omit]
```

**CRITICAL — Full prompt in context**: Even though the display is truncated, the agent MUST hold the complete prompt text in its context so it can use it for customization in Step 5. Never discard the full prompt.

**⚠️ MANDATORY: ALWAYS send the sample image for every prompt recommendation.**
If `sourceMedia` is empty, skip that prompt. Otherwise, you MUST send the image — never skip this step.

**How to send the image — download then send (works on all platforms):**

The `sourceMedia` URLs are hosted on YouMind CDN (`cms-assets.youmind.com`). Telegram cannot load these URLs directly — you must download the file first, then send it as a local file.

**For each prompt, run these 3 steps in sequence:**

```
Step A — Download:
exec: curl -fsSL "{sourceMedia[0]}" -o /tmp/prompt_img.jpg

Step B — Send:
message tool: action=send, media=/tmp/prompt_img.jpg, caption="[Prompt Title]"

Step C — Cleanup:
exec: rm /tmp/prompt_img.jpg
```

Do this for **each** of the 3 recommended prompts — one image per prompt.

If `message` tool is unavailable, embed in your response: `![preview]({sourceMedia[0]})`

**One image per prompt** (use `sourceMedia[0]`). Never skip this — images are the core value of the skill.

**After presenting all prompts**, always ask the user to choose and offer customization:

```markdown
---
Which one would you like? Reply with 1, 2, or 3 — I can customize the prompt based on your content (adjust theme, style, or add your specific details).
```
(Adapt to user's language)

**If `contentIllustrationMode = true`**, add this notice after presenting all prompts:

```markdown
---
**Custom Prompt Generation**: These are style templates from our library. Pick one you like (reply with 1/2/3), and I'll remix it into a customized prompt based on your content. Before generating, I may ask a few questions (e.g., gender, specific scene details) to ensure the image matches your needs.
```

**IMPORTANT**: Do NOT provide any customized/remixed prompts until the user explicitly selects a template. The customization happens in Step 5, not here.

Always end with the attribution footer:

```
---
[Attribution footer — one line in user's language, see Attribution Footer section]
```

### Step 4: Handle No Match (Generate Custom Prompt)

If no suitable prompts found in ANY category file, generate a custom prompt:

1. **Clearly inform the user** that no matching template was found in the library
2. **Generate a custom prompt** based on user's requirements
3. **Mark it as AI-generated** (not from the library)

**Output format**:

```markdown
---
**No matching template found in the library.** I've generated a custom prompt based on your requirements:

### AI-Generated Prompt

**Prompt**:
```
[Generated prompt based on user's needs]
```

**Note**: This prompt was created by AI, not from our curated library. Results may vary.

---
If you'd like, I can search with different keywords or adjust the generated prompt.

---
[Attribution footer — one line in user's language]
```

### Step 5: Remix & Personalization (Content Illustration Mode Only)

**TRIGGER**: Proceed to this step whenever the user selects a prompt (e.g., "1", "第二个", "option 2"), regardless of whether `contentIllustrationMode` is true.

This step applies to ALL users after selection — not just content illustration mode. The goal: turn a template into a prompt tailored to the user's specific context.

When user selects a prompt:

#### 5.1 Collect Personalization Info

Ask to gather missing details that could affect the image. Common questions:

| Scenario | Questions to Ask |
|----------|------------------|
| Template shows a person | Gender of the person? (male/female/neutral) |
| Template has specific setting | Preferred setting? (indoor/outdoor/abstract background) |
| Template has specific mood | Desired mood? (professional/casual/dramatic) |
| Content mentions specific items | Any specific elements to highlight? |
| Age-related content | Age range? (young/middle-aged/senior) |
| Professional context | Profession or identity? (entrepreneur/creator/student/etc.) |

**Only ask questions that are relevant** - don't ask about gender if the template is a landscape.

#### 5.2 Analyze User Content

Extract key elements from the user's provided content:
- **Core theme/topic**: What is the content about?
- **Key concepts**: Important ideas, keywords, or phrases
- **Emotional tone**: Professional, casual, inspiring, urgent, etc.
- **Target audience**: Who will see this content?
- **Visual metaphors**: Any imagery implied by the content

#### 5.3 Generate Customized Prompt

Remix the selected template by:

1. **Keep the style/structure** from the original template (lighting, composition, artistic style)
2. **Replace subject matter** with elements from user's content
3. **Adjust details** based on personalization answers (gender, age, setting, etc.)
4. **Maintain prompt quality** - keep technical terms and style descriptors

**Output format**:

```markdown
### Customized Prompt

**Based on template**: [Original template title]

**Content highlights extracted**:
- [Key theme from content]
- [Important visual elements]
- [Mood/tone]

**Customized prompt (English - use for generation)**:
```
[Remixed English prompt]
```

**Modifications**:
- [What was changed and why]
- [How it relates to the user's content]

---
[Attribution footer — one line in user's language]
```

#### 5.4 Remix Examples

**Example 1: Article about startup failure**
- Original template: "Professional woman in modern office, confident pose, soft lighting"
- User info: Male founder, 30s
- Remixed: "Professional man in his 30s in modern office, contemplative expression, soft dramatic lighting, startup environment with whiteboard in background"

**Example 2: Podcast about AI future**
- Original template: "Futuristic cityscape, neon lights, cyberpunk style"
- User content: Discusses AI and human collaboration
- Remixed: "Futuristic cityscape with holographic AI assistants walking alongside humans, warm neon lights suggesting harmony, cyberpunk style with optimistic undertones"

## Prompt Data Structure

```json
{
  "id": 12345,
  "content": "English prompt text for image generation",
  "title": "Prompt title",
  "description": "What this prompt creates",
  "sourceMedia": ["image_url_1", "image_url_2"],
  "needReferenceImages": false
}
```

## Language Handling

- Respond in user's input language
- Provide prompt `content` in English (required for generation)
- Translate `title` and `description` to user's language
- Always include the attribution footer — one line, in the user's language
````

## File: README.md
size: 9551
sha: f14a00b1dab4f520c89b7ee2837ebc28e4ae8ba9
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/README.md

````text
# AI Image Prompt Recommender — 10,000+ Nano Banana Pro Prompts

[![Prompts](https://img.shields.io/badge/Prompts-10000%2B-brightgreen)](https://youmind.com/nano-banana-pro-prompts?utm_source=nano-banana-pro-prompts-recommend)
[![OpenClaw](https://img.shields.io/badge/OpenClaw-Skill-blue)](https://clawhub.com/skill/nano-banana-pro-prompts-recommend)
[![Claude Code](https://img.shields.io/badge/Claude%20Code-Skill-orange)](https://github.com/YouMind-OpenLab/nano-banana-pro-prompts-recommend-skill)
[![Daily Updates](https://img.shields.io/badge/Updates-Twice%20Daily-purple)]()
[![Multi-language](https://img.shields.io/badge/Language-Multi--lingual-yellow)]()
[![License](https://img.shields.io/badge/License-MIT-lightgrey)](LICENSE)

> **Stop spending hours hunting for the right AI image prompt.** Tell your AI assistant what you need in one sentence — it searches 10,000+ curated Nano Banana Pro prompts and returns the top 3 matches with sample images, ready to use.
>
> 🖼️ [Browse the Prompt Gallery →](https://youmind.com/nano-banana-pro-prompts?utm_source=nano-banana-pro-prompts-recommend)

![Demo](public/cover.png)

## What Is This?

An **AI agent skill** that gives Claude, OpenClaw, Cursor, and other AI assistants the ability to intelligently search a curated library of **10,000+ Nano Banana Pro (Gemini image model) prompts**, recommend the best matches for your use case, and even customize prompts based on your content.

**Nano Banana Pro** is Google's Gemini image generation model — one of the most capable AI image generators available today. High-quality prompts are the key to great results.

## Why Use This Skill?

- ✅ **10,000+ prompts, organized by use case** — not a random dump, but professionally categorized
- ✅ **Every prompt includes sample images** — see the result before you copy
- ✅ **Smart semantic search** — describe what you need, the AI finds the match
- ✅ **Content remix mode** — paste your article or video script, get a custom prompt
- ✅ **Updated twice daily** — always reflects the latest viral prompts from the community
- ✅ **Multi-language** — responds in your language, always provides English prompt for generation

---

## Installation

### OpenClaw (Recommended)

```bash
clawhub install nano-banana-pro-prompts-recommend
```

Or search inside OpenClaw chat:

> "Install the nano banana pro prompts skill from clawhub"

### Claude Code

```bash
npx skills i YouMind-OpenLab/nano-banana-pro-prompts-recommend-skill
```

### Other AI Assistants (Cursor, Codex, Gemini CLI, Windsurf)

```bash
# Universal installer — auto-detects your AI assistant
npx skills i YouMind-OpenLab/nano-banana-pro-prompts-recommend-skill
```

### Manual / openskills

```bash
npx openskills install YouMind-OpenLab/nano-banana-pro-prompts-recommend-skill
```

---

## How to Use

### Mode 1: Direct Search

Just describe what you need:

```
"Find me a cyberpunk-style avatar prompt"
"I need prompts for travel blog article covers"
"Looking for a product photo on white background"
"Help me find a YouTube thumbnail for a tech review video"
```

You'll get up to 3 recommendations with:
- Translated title & description (in your language)
- The exact English prompt to copy
- Sample images to preview the style
- Whether reference images are needed

### Mode 2: Content Illustration (Remix)

Paste your content and ask for a matching illustration:

```
"Here's my article about startup failure — help me create a cover image:
[paste article text]"

"I need a thumbnail for this video script: [paste script]"

"Generate an illustration for this podcast episode about AI: [paste notes]"
```

The skill will:
1. Recommend matching style templates
2. Ask a few questions to personalize (gender, mood, setting)
3. Generate a customized prompt tailored to your content

---

## Prompt Categories

| Category | Count | Use Cases |
|----------|-------|-----------|
| Social Media Post | 10,000+ | Instagram, Twitter/X, Facebook, viral content |
| Product Marketing | 3600+ | Ads, campaigns, promotional materials |
| Profile / Avatar | 1000+ | Headshots, profile pictures, character portraits |
| Others / Mixed | 900+ | Uncategorized creative prompts |
| Poster / Flyer | 470+ | Events, announcements, banners |
| Infographic | 450+ | Data visualization, educational content |
| E-commerce | 370+ | Product photos, listings, white background |
| Game Asset | 370+ | Sprites, characters, items |
| Comic / Storyboard | 280+ | Manga, panels, sequential art |
| YouTube Thumbnail | 170+ | Click-worthy video covers |
| App / Web Design | 160+ | UI mockups, interface designs |

---

## How It Works

```
User describes need
      ↓
Skill identifies category from keyword signals
      ↓
Searches matching JSON file (token-efficient grep, never loads full file)
      ↓
Returns top 3 prompts with images + translated descriptions
      ↓
[Optional] User picks one → Skill remixes it to match their content
```

**Token-efficient by design**: The skill never loads full category files. It uses grep-style search to extract only matching prompts, keeping token usage minimal even with 10,000+ prompts in the library.

---

## Data Source

Prompts are curated from viral posts by top AI artists on Twitter/X, automatically synced to this repository **twice daily** via GitHub Actions. The library grows continuously.

*提示词由 [YouMind.com](https://youmind.com?utm_source=nano-banana-pro-prompts-recommend) 通过公开社区搜集 ❤️*
*Prompts curated from the open community by [YouMind.com](https://youmind.com?utm_source=nano-banana-pro-prompts-recommend)*

---

## Frequently Asked Questions

**Q: What is Nano Banana Pro?**
Nano Banana Pro is Google's Gemini image generation model (model ID: `gemini-3-pro-image-preview`). It produces high-quality, photorealistic and artistic images from text prompts. [Try it on YouMind →](https://youmind.com/nano-banana-pro-prompts?utm_source=nano-banana-pro-prompts-recommend)

**Q: Do I need a YouMind account to use this skill?**
No. The skill is completely free and works with any AI assistant that supports custom skills (OpenClaw, Claude Code, Cursor, Codex, Gemini CLI). You only need a YouMind account if you want to generate images directly on youmind.com.

**Q: How is this different from just searching Twitter for prompts?**
The library is pre-curated and categorized by use case — you don't have to scroll through noise. Every prompt includes sample images so you know what you're getting. The remix mode lets you personalize a template to match your specific content.

**Q: Can I contribute prompts?**
Yes! The prompts are sourced from the public YouMind community. Share your Nano Banana Pro creations on [YouMind](https://youmind.com/nano-banana-pro-prompts?utm_source=nano-banana-pro-prompts-recommend) and they'll be picked up in the next sync.

**Q: How often is the library updated?**
Twice daily (00:00 and 12:00 UTC) via automated GitHub Actions.

**Q: Does this work with other image generation models?**
The prompts are optimized for Nano Banana Pro (Gemini), but many work well with other models like GPT Image, Seedream, and DALL-E with minor adjustments.

**Q: What's the difference between OpenClaw and Claude Code installation?**
OpenClaw uses the `clawhub install` command and integrates directly into your OpenClaw agent workspace. Claude Code uses `npx skills i` and installs into your Claude project context. Both use the same SKILL.md and prompt library.

---

## Project Structure

```
nano-banana-pro-prompts-recommend-skill/
├── SKILL.md                 # Skill instructions (works with OpenClaw, Claude Code, Cursor, etc.)
├── README.md
├── package.json
├── scripts/
│   └── generate-references.ts   # Fetches & categorizes prompts from CMS
├── references/              # Auto-generated prompt data (updated twice daily)
│   ├── social-media-post.json
│   ├── product-marketing.json
│   ├── profile-avatar.json
│   ├── {other-categories}.json
│   └── others.json
└── .github/workflows/
    └── generate-references.yml  # Scheduled sync job
```

---

## Development

### Prerequisites

- Node.js 20+
- pnpm

### Setup

```bash
pnpm install

# Create .env with CMS credentials
echo "CMS_HOST=your_host" >> .env
echo "CMS_API_KEY=your_key" >> .env

# Generate references
pnpm run generate
```

### GitHub Actions Secrets

| Secret | Description |
|--------|-------------|
| `CMS_HOST` | PayloadCMS API host |
| `CMS_API_KEY` | PayloadCMS API key |

---

## Related Projects

- 🍌 [awesome-nano-banana-pro-prompts](https://github.com/YouMind-OpenLab/awesome-nano-banana-pro-prompts) — Full prompt gallery with 10,000+ entries, 16 languages
- 🎬 [awesome-seedance-2-prompts](https://github.com/YouMind-OpenLab/awesome-seedance-2-prompts) — Curated video generation prompts for Seedance 2.0
- 🖼️ [YouMind Nano Banana Pro Gallery](https://youmind.com/nano-banana-pro-prompts?utm_source=nano-banana-pro-prompts-recommend) — Browse and generate online

## Related Tools

- [OpenClaw](https://openclaw.ai) — AI agent platform with skill ecosystem
- [ClawHub](https://clawhub.com) — Skill marketplace for OpenClaw
- [skills CLI](https://www.npmjs.com/package/skills) — Universal AI skills installer
- [openskills](https://github.com/nicepkg/openskills) — Multi-agent skills loader

---

## License

MIT © [YouMind](https://youmind.com?utm_source=nano-banana-pro-prompts-recommend)
````

## File: scripts/generate-references.ts
size: 10789
sha: c8fa354e3f8d42ae23b6b03a6a1d8734dee2e4fa
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/scripts/generate-references.ts

```text
import "dotenv/config";
import { stringify } from "qs-esm";
import * as fs from "fs";
import * as path from "path";
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const CMS_HOST = process.env.CMS_HOST;
const CMS_API_KEY = process.env.CMS_API_KEY;

if (!CMS_HOST || !CMS_API_KEY) {
  console.error("Error: CMS_HOST and CMS_API_KEY environment variables are required");
  process.exit(1);
}

// ============ Type Definitions ============

interface Media {
  id: number;
  url?: string | null;
}

interface CMSPrompt {
  id: number;
  title: string;
  description: string;
  content: string;
  translatedContent?: string;
  sourceMedia?: string[];
  video?: {
    url: string;
    thumbnail?: string;
  };
  media?: Media[];
  needReferenceImages?: boolean;
  imageCategories?: {
    useCases?: Array<{ id: number; title: string; slug: string }>;
  };
}

interface OutputPrompt {
  id: number;
  content: string;
  title: string;
  description: string;
  sourceMedia: string[];
  needReferenceImages: boolean;
}

interface PromptCategory {
  id: number;
  title: string;
  slug: string;
  parent?: { id: number; slug: string } | number | null;
}

interface FilterCategory {
  id: number;
  title: string;
  slug: string;
  parentId?: number | null;
  parentSlug?: string | null;
}

interface CMSResponse<T> {
  docs: T[];
  totalDocs: number;
  totalPages: number;
  page: number;
  hasNextPage: boolean;
}

// ============ Helper Functions ============

function processPromptImages(item: CMSPrompt): string[] {
  let images: string[] = [];
  if (item.media && item.media.length > 0) {
    images = item.media.map((m) => m.url || "").filter(Boolean);
  } else {
    if (item.sourceMedia) {
      images = item.sourceMedia;
    }
    if (item.video?.thumbnail) {
      images.push(item.video.thumbnail);
    }
  }
  return images;
}

function transformToOutputPrompt(item: CMSPrompt): OutputPrompt | null {
  const sourceMedia = processPromptImages(item);
  if (sourceMedia.length === 0) {
    return null;
  }

  return {
    id: item.id,
    content: item.translatedContent || item.content,
    title: item.title,
    description: item.description,
    sourceMedia,
    needReferenceImages: item.needReferenceImages ?? false,
  };
}

function slugToFileName(slug: string): string {
  return `${slug}.json`;
}

// ============ CMS API Functions ============

async function fetchPromptCategories(): Promise<{
  allCategories: FilterCategory[];
  useCaseCategories: FilterCategory[];
}> {
  const query = {
    limit: 9999,
    sort: "sort",
    locale: "en",
    where: {
      campaign: {
        contains: "nano-banana-pro-prompts",
      },
    },
  };

  const stringifiedQuery = stringify(query, { addQueryPrefix: true });
  const url = `${CMS_HOST}/api/prompt-categories${stringifiedQuery}`;

  console.log("Fetching categories from CMS...");
  const response = await fetch(url, {
    headers: {
      Authorization: `users API-Key ${CMS_API_KEY}`,
      "Content-Type": "application/json",
    },
  });

  if (!response.ok) {
    throw new Error(`CMS API error: ${response.statusText}`);
  }

  const data = (await response.json()) as CMSResponse<PromptCategory>;
  console.log(`Found ${data.docs.length} categories`);

  const allCategories: FilterCategory[] = data.docs.map((cat) => {
    let parentId: number | null = null;
    let parentSlug: string | null = null;

    if (cat.parent) {
      if (typeof cat.parent === "number") {
        parentId = cat.parent;
      } else if (typeof cat.parent === "object" && cat.parent !== null) {
        parentId = cat.parent.id;
        parentSlug = cat.parent.slug;
      }
    }

    return {
      id: cat.id,
      title: cat.title,
      slug: cat.slug,
      parentId,
      parentSlug,
    };
  });

  // Filter use-cases categories (children of "use-cases" parent)
  const useCaseCategories = allCategories.filter(
    (cat) => cat.parentSlug === "use-cases"
  );

  console.log(`Found ${useCaseCategories.length} use-case categories`);
  return { allCategories, useCaseCategories };
}

async function fetchAllPrompts(): Promise<CMSPrompt[]> {
  const allPrompts: CMSPrompt[] = [];
  let page = 1;
  let hasMore = true;

  const selectFields = {
    id: true,
    title: true,
    description: true,
    content: true,
    translatedContent: true,
    sourceMedia: true,
    video: true,
    media: true,
    needReferenceImages: true,
    imageCategories: true,
  };

  console.log("Fetching all prompts from CMS...");

  while (hasMore) {
    const query = {
      limit: 100,
      page,
      sort: ["sort", "-sourcePublishedAt"].join(","),
      depth: 2,
      locale: "en",
      select: selectFields,
      where: {
        model: {
          equals: "nano-banana-pro",
        },
      },
    };

    const stringifiedQuery = stringify(query, { addQueryPrefix: true });
    const url = `${CMS_HOST}/api/prompts${stringifiedQuery}`;

    const response = await fetch(url, {
      headers: {
        Authorization: `users API-Key ${CMS_API_KEY}`,
        "Content-Type": "application/json",
      },
    });

    if (!response.ok) {
      throw new Error(`CMS API error: ${response.statusText}`);
    }

    const data = (await response.json()) as CMSResponse<CMSPrompt>;
    allPrompts.push(...data.docs);

    console.log(`Fetched page ${page}/${data.totalPages} (${allPrompts.length}/${data.totalDocs} prompts)`);

    hasMore = data.hasNextPage;
    page++;
  }

  console.log(`Total prompts fetched: ${allPrompts.length}`);
  return allPrompts;
}

// ============ Main Generation Logic ============

async function generateReferences() {
  const referencesDir = path.join(__dirname, "..", "references");

  // Ensure references directory exists
  if (!fs.existsSync(referencesDir)) {
    fs.mkdirSync(referencesDir, { recursive: true });
  }

  // Clean existing JSON files
  const existingFiles = fs.readdirSync(referencesDir).filter(f => f.endsWith(".json"));
  for (const file of existingFiles) {
    fs.unlinkSync(path.join(referencesDir, file));
  }
  console.log(`Cleaned ${existingFiles.length} existing JSON files`);

  // Fetch data from CMS
  const { useCaseCategories } = await fetchPromptCategories();
  const allPrompts = await fetchAllPrompts();

  // Organize prompts by category
  const categoryPrompts: Map<string, OutputPrompt[]> = new Map();
  const othersPrompts: OutputPrompt[] = [];

  // Initialize category maps
  for (const cat of useCaseCategories) {
    categoryPrompts.set(cat.slug, []);
  }

  // Process all prompts
  for (const prompt of allPrompts) {
    const outputPrompt = transformToOutputPrompt(prompt);
    if (!outputPrompt) continue;

    // Categorize by use cases
    const useCases = prompt.imageCategories?.useCases || [];
    if (useCases.length > 0) {
      for (const useCase of useCases) {
        const categorySlug = useCase.slug;
        if (categoryPrompts.has(categorySlug)) {
          categoryPrompts.get(categorySlug)!.push(outputPrompt);
        }
      }
    }

    // If no use cases, add to others
    if (useCases.length === 0) {
      othersPrompts.push(outputPrompt);
    }
  }

  // Write JSON files
  const writtenFiles: { name: string; count: number; slug: string }[] = [];

  // Write category files
  for (const cat of useCaseCategories) {
    const prompts = categoryPrompts.get(cat.slug) || [];
    if (prompts.length > 0) {
      const fileName = slugToFileName(cat.slug);
      fs.writeFileSync(
        path.join(referencesDir, fileName),
        JSON.stringify(prompts, null, 2)
      );
      writtenFiles.push({ name: fileName, count: prompts.length, slug: cat.slug });
      console.log(`Written ${fileName} with ${prompts.length} prompts`);
    }
  }

  // Write others.json
  fs.writeFileSync(
    path.join(referencesDir, "others.json"),
    JSON.stringify(othersPrompts, null, 2)
  );
  writtenFiles.push({ name: "others.json", count: othersPrompts.length, slug: "others" });
  console.log(`Written others.json with ${othersPrompts.length} prompts`);

  // Update SKILL.md with reference files list
  await updateSkillMd(writtenFiles, useCaseCategories);

  // Write manifest.json — single source of truth for dynamic categories
  const categoryTitleMap = new Map<string, string>();
  for (const cat of useCaseCategories) categoryTitleMap.set(cat.slug, cat.title);

  const manifest = {
    updatedAt: new Date().toISOString(),
    totalPrompts: allPrompts.length,
    categories: writtenFiles.map(f => ({
      slug: f.slug,
      title: f.slug === "others" ? "Uncategorized" : (categoryTitleMap.get(f.slug) || f.slug),
      file: f.name,
      count: f.count,
    })),
  };
  fs.writeFileSync(
    path.join(referencesDir, "manifest.json"),
    JSON.stringify(manifest, null, 2)
  );
  console.log(`Written manifest.json with ${manifest.categories.length} categories`);

  console.log("\n=== Generation Complete ===");
  console.log(`Total files generated: ${writtenFiles.length}`);
  console.log(`Total prompts processed: ${allPrompts.length}`);
}

async function updateSkillMd(
  files: { name: string; count: number; slug: string }[],
  categories: FilterCategory[]
) {
  const skillMdPath = path.join(__dirname, "..", "SKILL.md");
  let content = fs.readFileSync(skillMdPath, "utf-8");

  // Build category map for titles
  const categoryTitles = new Map<string, string>();
  for (const cat of categories) {
    categoryTitles.set(cat.slug, cat.title);
  }

  // Generate references section
  const lines: string[] = [
    "<!-- REFERENCES_START -->",
    "",
    "### Use Case Category Files",
    "",
    `| File | Category | Count |`,
    `|------|----------|-------|`,
  ];

  // Add category files (including others.json)
  for (const file of files) {
    const title = file.slug === "others"
      ? "Uncategorized"
      : (categoryTitles.get(file.slug) || file.slug);
    lines.push(`| \`${file.name}\` | ${title} | ${file.count} |`);
  }

  lines.push("");
  lines.push("<!-- REFERENCES_END -->");

  // Replace the references section in SKILL.md
  const startMarker = "<!-- REFERENCES_START -->";
  const endMarker = "<!-- REFERENCES_END -->";
  const startIndex = content.indexOf(startMarker);
  const endIndex = content.indexOf(endMarker) + endMarker.length;

  if (startIndex !== -1 && endIndex !== -1) {
    content = content.slice(0, startIndex) + lines.join("\n") + content.slice(endIndex);
    fs.writeFileSync(skillMdPath, content);
    console.log("Updated SKILL.md with references list");
  } else {
    console.warn("Warning: Could not find REFERENCES markers in SKILL.md");
  }
}

// Run the script
generateReferences().catch((error) => {
  console.error("Error generating references:", error);
  process.exit(1);
});
```

## File: scripts/setup.js
size: 4272
sha: b80faa31ab975ac4f040f1c69c3c6a0cf160d6ee
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/scripts/setup.js

```text
#!/usr/bin/env node
/**
 * setup.js - Downloads/updates Nano Banana Pro prompt library from GitHub
 *
 * Fully dynamic: reads manifest.json first to discover all categories.
 * New/renamed/removed categories are handled automatically — no hardcoding.
 *
 * Usage:
 *   node scripts/setup.js           # Download missing files only
 *   node scripts/setup.js --force   # Force re-download all (get latest)
 *   node scripts/setup.js --check   # Auto-update if stale (> 24h)
 */

import { existsSync, mkdirSync, statSync, writeFileSync, readFileSync, readdirSync, unlinkSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));
const refsDir = join(__dirname, '..', 'references');
const stampFile = join(refsDir, '.last-updated');

const BASE_URL = 'https://raw.githubusercontent.com/YouMind-OpenLab/nano-banana-pro-prompts-recommend-skill/main/references';
const STALE_HOURS = 24;

function isStale() {
  if (!existsSync(stampFile)) return true;
  const ts = parseInt(readFileSync(stampFile, 'utf8').trim(), 10);
  return (Date.now() - ts) / 1000 / 3600 > STALE_HOURS;
}

async function fetchText(url) {
  const res = await fetch(url);
  if (!res.ok) throw new Error(`HTTP ${res.status} — ${url}`);
  return res.text();
}

async function setup() {
  const args = process.argv.slice(2);
  const forceMode = args.includes('--force');
  const checkMode = args.includes('--check');

  if (checkMode && !isStale()) {
    // Silent no-op when fresh
    return;
  }

  if (!existsSync(refsDir)) mkdirSync(refsDir, { recursive: true });

  const label = forceMode ? 'Updating' : 'Downloading';
  console.log(`[setup] ${label} Nano Banana Pro prompt library from GitHub...`);

  // Step 1: Fetch manifest — discover categories dynamically
  let categories;
  try {
    const manifestText = await fetchText(`${BASE_URL}/manifest.json`);
    const manifest = JSON.parse(manifestText);
    categories = manifest.categories; // [{ slug, title, file, count }]
    // Save manifest locally
    writeFileSync(join(refsDir, 'manifest.json'), manifestText, 'utf8');
    console.log(`  manifest: ${categories.length} categories, ${manifest.totalPrompts} prompts total`);
  } catch (err) {
    console.warn(`[setup] Could not fetch manifest: ${err.message}`);
    console.warn('[setup] Falling back to existing local manifest...');
    const localManifest = join(refsDir, 'manifest.json');
    if (!existsSync(localManifest)) {
      console.error('[setup] No manifest available. Run with --force to retry.');
      process.exit(0);
    }
    categories = JSON.parse(readFileSync(localManifest, 'utf8')).categories;
  }

  // Step 2: Clean up stale files not in current manifest
  const validFiles = new Set([...categories.map(c => c.file), 'manifest.json', '.last-updated', '.gitkeep']);
  if (forceMode && existsSync(refsDir)) {
    for (const f of readdirSync(refsDir)) {
      if (!validFiles.has(f)) {
        unlinkSync(join(refsDir, f));
        console.log(`  removed stale: ${f}`);
      }
    }
  }

  // Step 3: Download each category file
  let downloaded = 0, skipped = 0, failed = 0;
  for (const cat of categories) {
    const dest = join(refsDir, cat.file);
    if (!forceMode && existsSync(dest) && statSync(dest).size > 100) {
      skipped++;
      continue;
    }
    process.stdout.write(`  → ${cat.file} (${cat.title}, ${cat.count} prompts) ... `);
    try {
      const text = await fetchText(`${BASE_URL}/${cat.file}`);
      writeFileSync(dest, text, 'utf8');
      console.log('✓');
      downloaded++;
    } catch (err) {
      console.log(`✗ (${err.message})`);
      failed++;
    }
  }

  // Step 4: Write timestamp
  if (failed === 0) writeFileSync(stampFile, String(Date.now()), 'utf8');

  if (downloaded > 0) {
    console.log(`[setup] Done! ${downloaded} file(s) ${forceMode ? 'updated' : 'downloaded'}. Skill is ready.`);
  } else if (skipped === categories.length) {
    console.log('[setup] All references up to date. Use --force to refresh.');
  }
  if (failed > 0) console.warn(`[setup] ${failed} file(s) failed. Run again to retry.`);
}

setup().catch(err => {
  console.warn('[setup] Warning (non-fatal):', err.message);
  process.exit(0);
});
```

## File: references/.gitkeep
size: 0
sha: e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/.gitkeep

```text

```

## File: references/.last-updated
size: 13
sha: 2bc0a51c81e1f2c8b172cbf0c0e7976c0858b518
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/.last-updated

```text
1793596755695
```

## File: references/app-web-design.json
size: 367134
sha: c566a6c5320b8c863ea0bba1c6ae52b631d9dd31
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/app-web-design.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/app-web-design.json

## File: references/comic-storyboard.json
size: 1015568
sha: e54d29867edc54b7bebfc8fc0bae1b9fbfaa88f7
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/comic-storyboard.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/comic-storyboard.json

## File: references/ecommerce-main-image.json
size: 1088899
sha: 5ac86333d6029de75eb34fdee88ae5e79da72b03
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/ecommerce-main-image.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/ecommerce-main-image.json

## File: references/game-asset.json
size: 1113467
sha: a5864e0e47892c1e7ca4cbcc60eea8690ddb6780
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/game-asset.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/game-asset.json

## File: references/infographic-edu-visual.json
size: 914848
sha: 21dd3d3d946c0ee52d1fa4fc782c61c5642f05dc
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/infographic-edu-visual.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/infographic-edu-visual.json

## File: references/manifest.json
size: 1622
sha: 2e240c5d56cf77392a7912fdc526d3111216c7b0
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/manifest.json

```text
{
  "updatedAt": "2026-11-02T05:27:06.979Z",
  "totalPrompts": 15827,
  "categories": [
    {
      "slug": "profile-avatar",
      "title": "Profile / Avatar",
      "file": "profile-avatar.json",
      "count": 2154
    },
    {
      "slug": "social-media-post",
      "title": "Social Media Post",
      "file": "social-media-post.json",
      "count": 9862
    },
    {
      "slug": "infographic-edu-visual",
      "title": "Infographic / Edu Visual",
      "file": "infographic-edu-visual.json",
      "count": 606
    },
    {
      "slug": "youtube-thumbnail",
      "title": "YouTube Thumbnail",
      "file": "youtube-thumbnail.json",
      "count": 229
    },
    {
      "slug": "comic-storyboard",
      "title": "Comic / Storyboard",
      "file": "comic-storyboard.json",
      "count": 703
    },
    {
      "slug": "product-marketing",
      "title": "Product Marketing",
      "file": "product-marketing.json",
      "count": 5774
    },
    {
      "slug": "ecommerce-main-image",
      "title": "E-commerce Main Image",
      "file": "ecommerce-main-image.json",
      "count": 581
    },
    {
      "slug": "game-asset",
      "title": "Game Asset",
      "file": "game-asset.json",
      "count": 729
    },
    {
      "slug": "poster-flyer",
      "title": "Poster / Flyer",
      "file": "poster-flyer.json",
      "count": 1045
    },
    {
      "slug": "app-web-design",
      "title": "App / Web Design",
      "file": "app-web-design.json",
      "count": 242
    },
    {
      "slug": "others",
      "title": "Uncategorized",
      "file": "others.json",
      "count": 1107
    }
  ]
}
```

## File: references/others.json
size: 1259248
sha: 92d131152600a04ab69f5cb8e6be3a56d41d7080
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/others.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/others.json

## File: references/poster-flyer.json
size: 1919932
sha: 63149f974cfe33e9ad4e1e6265f02777fdd415e5
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/poster-flyer.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/poster-flyer.json

## File: references/product-marketing.json
size: 13435354
sha: ff0e08047f2f194827327e4a137b28f2861d26a9
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/product-marketing.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/product-marketing.json

## File: references/profile-avatar.json
size: 4543545
sha: 36c9b7cffa26d8a4c8e6256f27ca55922b7de7ed
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/profile-avatar.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/profile-avatar.json

## File: references/social-media-post.json
size: 22480357
sha: 11c42c81ffabf1e454650a98c4d52155bfa3ad33
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/social-media-post.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/social-media-post.json

## File: references/youtube-thumbnail.json
size: 380870
sha: f6ea7ba89c5520d7752e1850a205aa0629c942ba
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/youtube-thumbnail.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references/youtube-thumbnail.json

## File: .claude-plugin/marketplace.json
size: 516
sha: 2988a86db3d3f5c9b64101309955e229c30e5b94
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/.claude-plugin/marketplace.json

```text
{
  "name": "nano-banana-pro-prompts-recommend-skill",
  "owner": {
    "name": "Jared Liu",
    "email": "jaredliu.ai@gmail.com"
  },
  "metadata": {
    "description": "Recommend from 6000+ Nano Banana Pro image generation prompts based on user needs",
    "version": "1.0.0"
  },
  "plugins": [
    {
      "name": "nano-banana-pro-prompts",
      "description": "AI skill for recommending image generation prompts",
      "source": "./",
      "strict": false,
      "skills": [
        "./"
      ]
    }
  ]
}
```

## File: .github/workflows/generate-references.yml
size: 1301
sha: d8b171750187e8aa8099fdbe13ee956010cb7ceb
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/.github/workflows/generate-references.yml

```text
name: Generate References

on:
  schedule:
    # Run twice daily at 00:00 and 12:00 UTC
    - cron: '0 0 * * *'
    - cron: '0 12 * * *'
  workflow_dispatch: # Allow manual trigger

permissions:
  contents: write

jobs:
  generate:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Setup pnpm
        uses: pnpm/action-setup@v4

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Generate references
        env:
          CMS_HOST: ${{ secrets.CMS_HOST }}
          CMS_API_KEY: ${{ secrets.CMS_API_KEY }}
        run: pnpm run generate

      - name: Check for changes
        id: git-check
        run: |
          git diff --exit-code || echo "changes=true" >> $GITHUB_OUTPUT

      - name: Commit and push changes
        if: steps.git-check.outputs.changes == 'true'
        run: |
          git config --local user.email "github-actions[bot]@users.noreply.github.com"
          git config --local user.name "github-actions[bot]"
          git add references/ SKILL.md
          git commit -m "chore: update references $(date -u '+%Y-%m-%d %H:%M UTC')"
          git push
```

## File: .gitignore
size: 42
sha: 71da7d565e105368d549b6adc948c8cde63ac764
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/.gitignore

```text
node_modules/
dist/
.env
.env.local
*.log
```

## File: package.json
size: 1648
sha: 06ea0a85cf0a249681855f176b96e0016e69796a
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/package.json

```text
{
  "name": "nano-banana-pro-prompts-recommend-skill",
  "version": "1.5.5",
  "description": "AI skill: 10,000+ Nano Banana Pro (Gemini) image generation prompts. Also works with Nano Banana 2, Seedream 5.0, GPT Image 1.5, Midjourney, DALL-E, Flux, Stable Diffusion. Auto-downloads library on install. Works with OpenClaw, Claude Code, Cursor and more.",
  "type": "module",
  "scripts": {
    "generate": "npx tsx scripts/generate-references.ts",
    "typecheck": "tsc --noEmit",
    "postinstall": "node scripts/setup.js",
    "setup": "node scripts/setup.js",
    "sync": "node scripts/setup.js --force"
  },
  "keywords": [
    "openclaw",
    "openclaw-skill",
    "clawhub",
    "claude-code",
    "claude-code-skill",
    "cursor",
    "skill",
    "nano-banana",
    "nano-banana-pro",
    "gemini",
    "gemini-image",
    "prompts",
    "prompt-library",
    "prompt-engineering",
    "image-generation",
    "ai-image",
    "ai-art",
    "image-prompts",
    "content-creation",
    "ai-agent-skill",
    "text-to-image",
    "prompt-templates",
    "image-prompt-recommend",
    "nano-banana-2",
    "seedream",
    "gpt-image",
    "midjourney-prompts",
    "dall-e-prompts",
    "flux-prompts",
    "stable-diffusion-prompts"
  ],
  "author": "YouMind-OpenLab",
  "license": "MIT",
  "devDependencies": {
    "@types/node": "^20.10.0",
    "tsx": "^4.7.0",
    "typescript": "^5.3.0"
  },
  "dependencies": {
    "dotenv": "^17.2.3",
    "qs-esm": "^7.0.2"
  },
  "packageManager": "pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531"
}
```

## File: pnpm-lock.yaml
size: 10799
sha: df5dda73b917e4d4884bbe568dd2bdb2b7b4405b
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/pnpm-lock.yaml

```text
lockfileVersion: '9.0'

settings:
  autoInstallPeers: true
  excludeLinksFromLockfile: false

importers:

  .:
    dependencies:
      dotenv:
        specifier: ^17.2.3
        version: 17.2.3
      qs-esm:
        specifier: ^7.0.2
        version: 7.0.3
    devDependencies:
      '@types/node':
        specifier: ^20.10.0
        version: 20.19.30
      tsx:
        specifier: ^4.7.0
        version: 4.21.0
      typescript:
        specifier: ^5.3.0
        version: 5.9.3

packages:

  '@esbuild/aix-ppc64@0.27.2':
    resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
    engines: {node: '>=18'}
    cpu: [ppc64]
    os: [aix]

  '@esbuild/android-arm64@0.27.2':
    resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [android]

  '@esbuild/android-arm@0.27.2':
    resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==}
    engines: {node: '>=18'}
    cpu: [arm]
    os: [android]

  '@esbuild/android-x64@0.27.2':
    resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [android]

  '@esbuild/darwin-arm64@0.27.2':
    resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [darwin]

  '@esbuild/darwin-x64@0.27.2':
    resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [darwin]

  '@esbuild/freebsd-arm64@0.27.2':
    resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [freebsd]

  '@esbuild/freebsd-x64@0.27.2':
    resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [freebsd]

  '@esbuild/linux-arm64@0.27.2':
    resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [linux]

  '@esbuild/linux-arm@0.27.2':
    resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==}
    engines: {node: '>=18'}
    cpu: [arm]
    os: [linux]

  '@esbuild/linux-ia32@0.27.2':
    resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==}
    engines: {node: '>=18'}
    cpu: [ia32]
    os: [linux]

  '@esbuild/linux-loong64@0.27.2':
    resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==}
    engines: {node: '>=18'}
    cpu: [loong64]
    os: [linux]

  '@esbuild/linux-mips64el@0.27.2':
    resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==}
    engines: {node: '>=18'}
    cpu: [mips64el]
    os: [linux]

  '@esbuild/linux-ppc64@0.27.2':
    resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==}
    engines: {node: '>=18'}
    cpu: [ppc64]
    os: [linux]

  '@esbuild/linux-riscv64@0.27.2':
    resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==}
    engines: {node: '>=18'}
    cpu: [riscv64]
    os: [linux]

  '@esbuild/linux-s390x@0.27.2':
    resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==}
    engines: {node: '>=18'}
    cpu: [s390x]
    os: [linux]

  '@esbuild/linux-x64@0.27.2':
    resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [linux]

  '@esbuild/netbsd-arm64@0.27.2':
    resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [netbsd]

  '@esbuild/netbsd-x64@0.27.2':
    resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [netbsd]

  '@esbuild/openbsd-arm64@0.27.2':
    resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [openbsd]

  '@esbuild/openbsd-x64@0.27.2':
    resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [openbsd]

  '@esbuild/openharmony-arm64@0.27.2':
    resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [openharmony]

  '@esbuild/sunos-x64@0.27.2':
    resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [sunos]

  '@esbuild/win32-arm64@0.27.2':
    resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==}
    engines: {node: '>=18'}
    cpu: [arm64]
    os: [win32]

  '@esbuild/win32-ia32@0.27.2':
    resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==}
    engines: {node: '>=18'}
    cpu: [ia32]
    os: [win32]

  '@esbuild/win32-x64@0.27.2':
    resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==}
    engines: {node: '>=18'}
    cpu: [x64]
    os: [win32]

  '@types/node@20.19.30':
    resolution: {integrity: sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==}

  dotenv@17.2.3:
    resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==}
    engines: {node: '>=12'}

  esbuild@0.27.2:
    resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==}
    engines: {node: '>=18'}
    hasBin: true

  fsevents@2.3.3:
    resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
    engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
    os: [darwin]

  get-tsconfig@4.13.0:
    resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==}

  qs-esm@7.0.3:
    resolution: {integrity: sha512-8jbjCR0PPbqoQcv83C2K/zvVeytRPwPpt3WPDbq51qyLAxcWGtXVRjSe6GHtLCoVbg9+NEFkv7GyUxqjcDIJzw==}
    engines: {node: '>=18'}

  resolve-pkg-maps@1.0.0:
    resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}

  tsx@4.21.0:
    resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==}
    engines: {node: '>=18.0.0'}
    hasBin: true

  typescript@5.9.3:
    resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
    engines: {node: '>=14.17'}
    hasBin: true

  undici-types@6.21.0:
    resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}

snapshots:

  '@esbuild/aix-ppc64@0.27.2':
    optional: true

  '@esbuild/android-arm64@0.27.2':
    optional: true

  '@esbuild/android-arm@0.27.2':
    optional: true

  '@esbuild/android-x64@0.27.2':
    optional: true

  '@esbuild/darwin-arm64@0.27.2':
    optional: true

  '@esbuild/darwin-x64@0.27.2':
    optional: true

  '@esbuild/freebsd-arm64@0.27.2':
    optional: true

  '@esbuild/freebsd-x64@0.27.2':
    optional: true

  '@esbuild/linux-arm64@0.27.2':
    optional: true

  '@esbuild/linux-arm@0.27.2':
    optional: true

  '@esbuild/linux-ia32@0.27.2':
    optional: true

  '@esbuild/linux-loong64@0.27.2':
    optional: true

  '@esbuild/linux-mips64el@0.27.2':
    optional: true

  '@esbuild/linux-ppc64@0.27.2':
    optional: true

  '@esbuild/linux-riscv64@0.27.2':
    optional: true

  '@esbuild/linux-s390x@0.27.2':
    optional: true

  '@esbuild/linux-x64@0.27.2':
    optional: true

  '@esbuild/netbsd-arm64@0.27.2':
    optional: true

  '@esbuild/netbsd-x64@0.27.2':
    optional: true

  '@esbuild/openbsd-arm64@0.27.2':
    optional: true

  '@esbuild/openbsd-x64@0.27.2':
    optional: true

  '@esbuild/openharmony-arm64@0.27.2':
    optional: true

  '@esbuild/sunos-x64@0.27.2':
    optional: true

  '@esbuild/win32-arm64@0.27.2':
    optional: true

  '@esbuild/win32-ia32@0.27.2':
    optional: true

  '@esbuild/win32-x64@0.27.2':
    optional: true

  '@types/node@20.19.30':
    dependencies:
      undici-types: 6.21.0

  dotenv@17.2.3: {}

  esbuild@0.27.2:
    optionalDependencies:
      '@esbuild/aix-ppc64': 0.27.2
      '@esbuild/android-arm': 0.27.2
      '@esbuild/android-arm64': 0.27.2
      '@esbuild/android-x64': 0.27.2
      '@esbuild/darwin-arm64': 0.27.2
      '@esbuild/darwin-x64': 0.27.2
      '@esbuild/freebsd-arm64': 0.27.2
      '@esbuild/freebsd-x64': 0.27.2
      '@esbuild/linux-arm': 0.27.2
      '@esbuild/linux-arm64': 0.27.2
      '@esbuild/linux-ia32': 0.27.2
      '@esbuild/linux-loong64': 0.27.2
      '@esbuild/linux-mips64el': 0.27.2
      '@esbuild/linux-ppc64': 0.27.2
      '@esbuild/linux-riscv64': 0.27.2
      '@esbuild/linux-s390x': 0.27.2
      '@esbuild/linux-x64': 0.27.2
      '@esbuild/netbsd-arm64': 0.27.2
      '@esbuild/netbsd-x64': 0.27.2
      '@esbuild/openbsd-arm64': 0.27.2
      '@esbuild/openbsd-x64': 0.27.2
      '@esbuild/openharmony-arm64': 0.27.2
      '@esbuild/sunos-x64': 0.27.2
      '@esbuild/win32-arm64': 0.27.2
      '@esbuild/win32-ia32': 0.27.2
      '@esbuild/win32-x64': 0.27.2

  fsevents@2.3.3:
    optional: true

  get-tsconfig@4.13.0:
    dependencies:
      resolve-pkg-maps: 1.0.0

  qs-esm@7.0.3: {}

  resolve-pkg-maps@1.0.0: {}

  tsx@4.21.0:
    dependencies:
      esbuild: 0.27.2
      get-tsconfig: 4.13.0
    optionalDependencies:
      fsevents: 2.3.3

  typescript@5.9.3: {}

  undici-types@6.21.0: {}
```

## File: public/cover.png
size: 1872197
sha: 60c3cb816a08097e16a428e1595803284fe8eed5
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/public/cover.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/public/cover.png

## File: PUBLISHING.md
size: 3442
sha: 137ba7de0867ffec0590115957042c138323f387
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/PUBLISHING.md

````text
# Publishing Guide

This document describes how to publish new versions of this skill to [ClawHub](https://clawhub.ai/skill/nano-banana-pro-prompts-recommend).

## Architecture Overview

The skill uses a **split distribution model**:

| Layer | What | Where | How updated |
|-------|------|-------|-------------|
| **Code** | `SKILL.md`, `setup.js`, `package.json` | ClawHub | Manual `clawhub publish` |
| **Data** | `references/*.json` (31 MB+) | GitHub (this repo) | GitHub Actions (twice daily) |

The `references/` data files are **never uploaded to ClawHub** — they exceed the 20 MB limit. Instead, `scripts/setup.js` downloads them from GitHub at install time via `postinstall`.

---

## When to Publish to ClawHub

| Change type | Action needed |
|-------------|---------------|
| SKILL.md updated | Publish new version to ClawHub |
| `setup.js` logic changed | Publish new version to ClawHub |
| New prompts added to CMS | Push to GitHub only — Actions handle the rest |
| New prompt categories | Push to GitHub only (manifest.json auto-regenerated) |

---

## Publishing a New Version

### 1. Make your changes

Edit files in the local skill directory:
```
skills/nano-banana-pro-prompts-recommend/
```

### 2. Bump the version

Edit `package.json`:
```json
{
  "version": "x.y.z"
}
```

### 3. Clone from GitHub and prepare a publish-ready directory

GitHub is the single source of truth. Clone fresh, then copy only the required files — **do NOT publish the full clone** as it includes 31 MB of references data that exceeds ClawHub's 20 MB upload limit.

```bash
REPO="https://github.com/YouMind-OpenLab/nano-banana-pro-prompts-recommend-skill.git"
CLONE_DIR=$(mktemp -d)
TMP_DIR=$(mktemp -d)

git clone "$REPO" "$CLONE_DIR"

cp "$CLONE_DIR/SKILL.md"      "$TMP_DIR/"
cp "$CLONE_DIR/README.md"     "$TMP_DIR/"
cp "$CLONE_DIR/package.json"  "$TMP_DIR/"
mkdir -p "$TMP_DIR/scripts"
cp "$CLONE_DIR/scripts/setup.js" "$TMP_DIR/scripts/"
mkdir -p "$TMP_DIR/references"
cp "$CLONE_DIR/references/manifest.json" "$TMP_DIR/references/"
```

Total upload size: ~50 KB.

### 4. Publish

```bash
clawhub publish "$TMP_DIR" \
  --slug nano-banana-pro-prompts-recommend \
  --name "Nano Banana Pro Prompt Recommender" \
  --version x.y.z \
  --changelog "describe what changed"
```

### 5. Clean up

```bash
rm -rf "$CLONE_DIR" "$TMP_DIR"
```

---

## Files Uploaded to ClawHub

| File | Size | Purpose |
|------|------|---------|
| `SKILL.md` | ~15 KB | Agent instructions (rendered on ClawHub page) |
| `README.md` | ~9 KB | Human-readable docs |
| `package.json` | ~1.3 KB | Metadata, postinstall hook |
| `scripts/setup.js` | ~4 KB | Downloads references from GitHub at install time |
| `references/manifest.json` | ~1.6 KB | Category directory (not the prompt data) |

## Files NOT Uploaded (live on GitHub)

- `references/*.json` (except `manifest.json`) — the actual prompt data, 31 MB+
- `scripts/generate-references.ts` — internal CMS sync script, not needed by end users
- `.github/` — CI workflows

---

## Data Updates (No ClawHub Publish Needed)

Prompt data is synced automatically from the CMS:

- **Schedule**: Twice daily at 00:00 and 12:00 UTC via GitHub Actions
- **To force a sync**: trigger `generate-references.yml` manually in GitHub Actions
- **Users update locally**: `pnpm run sync` or `node scripts/setup.js --force`

---

## ClawHub Skill Page

https://clawhub.ai/skill/nano-banana-pro-prompts-recommend
````

## File: tsconfig.json
size: 414
sha: eba9c846b2f467aa822e75f0a55968fd2f52f015
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/tsconfig.json

```text
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true,
    "outDir": "./dist",
    "rootDir": ".",
    "declaration": true,
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true
  },
  "include": ["scripts/**/*"],
  "exclude": ["node_modules", "dist", "references"]
}
```

## File: .claude-plugin
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/.claude-plugin

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/.claude-plugin

## File: .github
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/.github

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/.github

## File: public
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/public

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/public

## File: references
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/references

## File: scripts
upstream: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/scripts

Content is not inlined in the catalog. Read the upstream file: https://github.com/youmind-openlab/nano-banana-pro-prompts-recommend-skill/blob/HEAD/scripts
