Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive AI design skill providing design intelligence across platforms with 161 reasoning rules.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/logo/generate.py
1#!/usr/bin/env python32# -*- coding: utf-8 -*-3"""4Logo Generation Script using Gemini Nano Banana API5Uses Gemini 2.5 Flash Image and Gemini 3 Pro Image Preview models67Models:8- Nano Banana (default): gemini-2.5-flash-image - fast, high-volume, low-latency9- Nano Banana Pro (--pro): gemini-3-pro-image-preview - professional quality, advanced reasoning1011Usage:12python generate.py --prompt "tech startup logo minimalist blue"13python generate.py --prompt "coffee shop vintage badge" --style vintage --output logo.png14python generate.py --brand "TechFlow" --industry tech --style minimalist15python generate.py --brand "TechFlow" --pro # Use Nano Banana Pro model1617Batch mode (generates multiple variants):18python generate.py --brand "Unikorn" --batch 9 --output-dir ./logos --pro19"""2021import argparse22import os23import sys24import time25from pathlib import Path26from datetime import datetime2728# Load environment variables29def load_env():30"""Load .env files in priority order"""31env_paths = [32Path(__file__).parent.parent.parent / ".env",33Path.home() / ".claude" / "skills" / ".env",34Path.home() / ".claude" / ".env"35]3637for env_path in env_paths:38if env_path.exists():39with open(env_path) as f:40for line in f:41line = line.strip()42if line and not line.startswith('#') and '=' in line:43key, value = line.split('=', 1)44if key not in os.environ:45os.environ[key] = value.strip('"\'')4647load_env()4849try:50from google import genai51from google.genai import types52except ImportError:53print("Error: google-genai package not installed.")54print("Install with: pip install google-genai")55sys.exit(1)565758# ============ CONFIGURATION ============59GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")6061# Gemini "Nano Banana" model configurations for image generation62GEMINI_FLASH = "gemini-2.5-flash-image" # Nano Banana: fast, high-volume, low-latency63GEMINI_PRO = "gemini-3-pro-image-preview" # Nano Banana Pro: professional quality, advanced reasoning6465# Supported aspect ratios66ASPECT_RATIOS = ["1:1", "16:9", "9:16", "4:3", "3:4"]67DEFAULT_ASPECT_RATIO = "1:1" # Square is ideal for logos6869# Logo-specific prompt templates70LOGO_PROMPT_TEMPLATE = """Generate a professional logo image: {prompt}7172Style requirements:73- Clean vector-style illustration suitable for a logo74- Simple, scalable design that works at any size75- Clear silhouette and recognizable shape76- Professional quality suitable for business use77- Centered composition on plain white or transparent background78- No text unless specifically requested79- High contrast and clear edges80- Square format, perfectly centered81- Output as a clean, high-quality logo image82"""8384STYLE_MODIFIERS = {85"minimalist": "minimalist, simple geometric shapes, clean lines, lots of white space, single color or limited palette",86"vintage": "vintage, retro, badge style, distressed texture, heritage feel, warm earth tones",87"modern": "modern, sleek, gradient colors, tech-forward, innovative feel",88"luxury": "luxury, elegant, gold accents, refined, premium feel, serif typography",89"playful": "playful, fun, colorful, friendly, approachable, rounded shapes",90"corporate": "corporate, professional, trustworthy, stable, conservative colors",91"organic": "organic, natural, flowing lines, earth tones, sustainable feel",92"geometric": "geometric, abstract, mathematical precision, symmetrical",93"hand-drawn": "hand-drawn, artisan, sketch-like, authentic, imperfect lines",94"3d": "3D, dimensional, depth, shadows, isometric perspective",95"abstract": "abstract mark, conceptual, symbolic, non-literal representation, artistic interpretation",96"lettermark": "lettermark, single letter or initials, typographic, monogram style, distinctive character",97"wordmark": "wordmark, logotype, custom typography, brand name as logo, distinctive lettering",98"emblem": "emblem, badge, crest style, enclosed design, traditional, authoritative feel",99"mascot": "mascot, character, friendly face, personified, memorable figure",100"gradient": "gradient, color transition, vibrant, modern digital feel, smooth color flow",101"lineart": "line art, single stroke, continuous line, elegant simplicity, wire-frame style",102"negative-space": "negative space, clever use of white space, hidden meaning, dual imagery, optical illusion"103}104105INDUSTRY_PROMPTS = {106"tech": "technology company, digital, innovative, modern, circuit-like elements",107"healthcare": "healthcare, medical, caring, trust, cross or heart symbol",108"finance": "financial services, stable, trustworthy, growth, upward elements",109"food": "food and beverage, appetizing, warm colors, welcoming",110"fashion": "fashion brand, elegant, stylish, refined, artistic",111"fitness": "fitness and sports, dynamic, energetic, powerful, movement",112"eco": "eco-friendly, sustainable, natural, green, leaf or earth elements",113"education": "education, knowledge, growth, learning, book or cap symbol",114"real-estate": "real estate, property, home, roof or building silhouette",115"creative": "creative agency, artistic, unique, expressive, colorful"116}117118119def enhance_prompt(base_prompt, style=None, industry=None, brand_name=None):120"""Enhance the logo prompt with style and industry modifiers"""121prompt_parts = [base_prompt]122123if style and style in STYLE_MODIFIERS:124prompt_parts.append(STYLE_MODIFIERS[style])125126if industry and industry in INDUSTRY_PROMPTS:127prompt_parts.append(INDUSTRY_PROMPTS[industry])128129if brand_name:130prompt_parts.insert(0, f"Logo for '{brand_name}':")131132combined = ", ".join(prompt_parts)133return LOGO_PROMPT_TEMPLATE.format(prompt=combined)134135136def generate_logo(prompt, style=None, industry=None, brand_name=None,137output_path=None, use_pro=False, aspect_ratio=None):138"""Generate a logo using Gemini models with image generation139140Args:141aspect_ratio: Image aspect ratio. Options: "1:1", "16:9", "9:16", "4:3", "3:4"142Default is "1:1" (square) for logos.143"""144145if not GEMINI_API_KEY:146print("Error: GEMINI_API_KEY not set")147print("Set it with: export GEMINI_API_KEY='your-key'")148return None149150# Initialize client151client = genai.Client(api_key=GEMINI_API_KEY)152153# Enhance the prompt154full_prompt = enhance_prompt(prompt, style, industry, brand_name)155156# Select model157model = GEMINI_PRO if use_pro else GEMINI_FLASH158model_label = "Nano Banana Pro (gemini-3-pro-image-preview)" if use_pro else "Nano Banana (gemini-2.5-flash-image)"159160# Set aspect ratio (default to 1:1 for logos)161ratio = aspect_ratio if aspect_ratio in ASPECT_RATIOS else DEFAULT_ASPECT_RATIO162163print(f"Generating logo with {model_label}...")164print(f"Aspect ratio: {ratio}")165print(f"Prompt: {full_prompt[:150]}...")166print()167168try:169# Generate image using Gemini with image generation capability170response = client.models.generate_content(171model=model,172contents=full_prompt,173config=types.GenerateContentConfig(174response_modalities=["IMAGE", "TEXT"],175image_config=types.ImageConfig(176aspect_ratio=ratio177),178safety_settings=[179types.SafetySetting(180category="HARM_CATEGORY_HATE_SPEECH",181threshold="BLOCK_LOW_AND_ABOVE"182),183types.SafetySetting(184category="HARM_CATEGORY_DANGEROUS_CONTENT",185threshold="BLOCK_LOW_AND_ABOVE"186),187types.SafetySetting(188category="HARM_CATEGORY_SEXUALLY_EXPLICIT",189threshold="BLOCK_LOW_AND_ABOVE"190),191types.SafetySetting(192category="HARM_CATEGORY_HARASSMENT",193threshold="BLOCK_LOW_AND_ABOVE"194),195]196)197)198199# Extract image from response200image_data = None201for part in response.candidates[0].content.parts:202if hasattr(part, 'inline_data') and part.inline_data:203if part.inline_data.mime_type.startswith('image/'):204image_data = part.inline_data.data205break206207if not image_data:208print("No image generated. The model may not have produced an image.")209print("Try a different prompt or check if the model supports image generation.")210return None211212# Determine output path213if output_path is None:214timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")215brand_slug = brand_name.lower().replace(" ", "_") if brand_name else "logo"216output_path = f"{brand_slug}_{timestamp}.png"217218# Save image219with open(output_path, "wb") as f:220f.write(image_data)221222print(f"Logo saved to: {output_path}")223return output_path224225except Exception as e:226print(f"Error generating logo: {e}")227return None228229230def generate_batch(prompt, brand_name, count, output_dir, use_pro=False, brand_context=None, aspect_ratio=None):231"""Generate multiple logo variants with different styles"""232233# Select appropriate styles for batch generation234batch_styles = [235("minimalist", "Clean, simple geometric shape with minimal details"),236("modern", "Sleek gradient with tech-forward aesthetic"),237("geometric", "Abstract geometric patterns, mathematical precision"),238("gradient", "Vibrant color transitions, modern digital feel"),239("abstract", "Conceptual symbolic representation"),240("lettermark", "Stylized letter 'U' as monogram"),241("negative-space", "Clever use of negative space, hidden meaning"),242("lineart", "Single stroke continuous line design"),243("3d", "Dimensional design with depth and shadows"),244]245246# Ensure output directory exists247os.makedirs(output_dir, exist_ok=True)248249results = []250model_label = "Pro" if use_pro else "Flash"251ratio = aspect_ratio if aspect_ratio in ASPECT_RATIOS else DEFAULT_ASPECT_RATIO252253print(f"\n{'='*60}")254print(f" BATCH LOGO GENERATION: {brand_name}")255print(f" Model: Nano Banana {model_label}")256print(f" Aspect Ratio: {ratio}")257print(f" Variants: {count}")258print(f" Output: {output_dir}")259print(f"{'='*60}\n")260261for i in range(min(count, len(batch_styles))):262style_key, style_desc = batch_styles[i]263264# Build enhanced prompt with brand context265enhanced_prompt = f"{prompt}, {style_desc}"266if brand_context:267enhanced_prompt = f"{brand_context}, {enhanced_prompt}"268269# Generate filename270filename = f"{brand_name.lower().replace(' ', '_')}_{style_key}_{i+1:02d}.png"271output_path = os.path.join(output_dir, filename)272273print(f"[{i+1}/{count}] Generating {style_key} variant...")274275result = generate_logo(276prompt=enhanced_prompt,277style=style_key,278industry="tech",279brand_name=brand_name,280output_path=output_path,281use_pro=use_pro,282aspect_ratio=aspect_ratio283)284285if result:286results.append(result)287print(f" ✓ Saved: {filename}\n")288else:289print(f" ✗ Failed: {style_key}\n")290291# Rate limiting between requests292if i < count - 1:293time.sleep(2)294295print(f"\n{'='*60}")296print(f" BATCH COMPLETE: {len(results)}/{count} logos generated")297print(f"{'='*60}\n")298299return results300301302def main():303parser = argparse.ArgumentParser(description="Generate logos using Gemini Nano Banana models")304parser.add_argument("--prompt", "-p", type=str, help="Logo description prompt")305parser.add_argument("--brand", "-b", type=str, help="Brand name")306parser.add_argument("--style", "-s", choices=list(STYLE_MODIFIERS.keys()), help="Logo style")307parser.add_argument("--industry", "-i", choices=list(INDUSTRY_PROMPTS.keys()), help="Industry type")308parser.add_argument("--output", "-o", type=str, help="Output file path")309parser.add_argument("--output-dir", type=str, help="Output directory for batch generation")310parser.add_argument("--batch", type=int, help="Number of logo variants to generate (batch mode)")311parser.add_argument("--brand-context", type=str, help="Additional brand context for prompts")312parser.add_argument("--pro", action="store_true", help="Use Nano Banana Pro (gemini-3-pro-image-preview) for professional quality")313parser.add_argument("--aspect-ratio", "-r", choices=ASPECT_RATIOS, default=DEFAULT_ASPECT_RATIO,314help=f"Image aspect ratio (default: {DEFAULT_ASPECT_RATIO} for logos)")315parser.add_argument("--list-styles", action="store_true", help="List available styles")316parser.add_argument("--list-industries", action="store_true", help="List available industries")317318args = parser.parse_args()319320if args.list_styles:321print("Available styles:")322for style, desc in STYLE_MODIFIERS.items():323print(f" {style}: {desc[:60]}...")324return325326if args.list_industries:327print("Available industries:")328for industry, desc in INDUSTRY_PROMPTS.items():329print(f" {industry}: {desc[:60]}...")330return331332if not args.prompt and not args.brand:333parser.error("Either --prompt or --brand is required")334335prompt = args.prompt or "professional logo"336337# Batch mode338if args.batch:339output_dir = args.output_dir or f"./{args.brand.lower().replace(' ', '_')}_logos"340generate_batch(341prompt=prompt,342brand_name=args.brand or "Logo",343count=args.batch,344output_dir=output_dir,345use_pro=args.pro,346brand_context=args.brand_context,347aspect_ratio=args.aspect_ratio348)349else:350generate_logo(351prompt=prompt,352style=args.style,353industry=args.industry,354brand_name=args.brand,355output_path=args.output,356use_pro=args.pro,357aspect_ratio=args.aspect_ratio358)359360361if __name__ == "__main__":362main()363