ui-ux-pro-max-cli 2.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -0
- package/assets/data/_sync_all.py +414 -0
- package/assets/data/app-interface.csv +31 -0
- package/assets/data/charts.csv +26 -0
- package/assets/data/colors.csv +162 -0
- package/assets/data/design.csv +1776 -0
- package/assets/data/draft.csv +1779 -0
- package/assets/data/google-fonts.csv +1924 -0
- package/assets/data/icons.csv +106 -0
- package/assets/data/landing.csv +35 -0
- package/assets/data/products.csv +162 -0
- package/assets/data/react-performance.csv +45 -0
- package/assets/data/stacks/angular.csv +51 -0
- package/assets/data/stacks/astro.csv +54 -0
- package/assets/data/stacks/flutter.csv +53 -0
- package/assets/data/stacks/html-tailwind.csv +56 -0
- package/assets/data/stacks/javafx.csv +76 -0
- package/assets/data/stacks/jetpack-compose.csv +53 -0
- package/assets/data/stacks/laravel.csv +51 -0
- package/assets/data/stacks/nextjs.csv +53 -0
- package/assets/data/stacks/nuxt-ui.csv +71 -0
- package/assets/data/stacks/nuxtjs.csv +59 -0
- package/assets/data/stacks/react-native.csv +52 -0
- package/assets/data/stacks/react.csv +54 -0
- package/assets/data/stacks/shadcn.csv +61 -0
- package/assets/data/stacks/svelte.csv +54 -0
- package/assets/data/stacks/swiftui.csv +51 -0
- package/assets/data/stacks/threejs.csv +54 -0
- package/assets/data/stacks/vue.csv +50 -0
- package/assets/data/styles.csv +85 -0
- package/assets/data/typography.csv +74 -0
- package/assets/data/ui-reasoning.csv +162 -0
- package/assets/data/ux-guidelines.csv +100 -0
- package/assets/scripts/core.py +263 -0
- package/assets/scripts/design_system.py +1157 -0
- package/assets/scripts/search.py +114 -0
- package/assets/skills/banner-design/SKILL.md +196 -0
- package/assets/skills/banner-design/references/banner-sizes-and-styles.md +118 -0
- package/assets/skills/brand/SKILL.md +97 -0
- package/assets/skills/brand/references/approval-checklist.md +169 -0
- package/assets/skills/brand/references/asset-organization.md +157 -0
- package/assets/skills/brand/references/brand-guideline-template.md +140 -0
- package/assets/skills/brand/references/color-palette-management.md +186 -0
- package/assets/skills/brand/references/consistency-checklist.md +94 -0
- package/assets/skills/brand/references/logo-usage-rules.md +185 -0
- package/assets/skills/brand/references/messaging-framework.md +85 -0
- package/assets/skills/brand/references/typography-specifications.md +214 -0
- package/assets/skills/brand/references/update.md +118 -0
- package/assets/skills/brand/references/visual-identity.md +96 -0
- package/assets/skills/brand/references/voice-framework.md +88 -0
- package/assets/skills/brand/scripts/extract-colors.cjs +341 -0
- package/assets/skills/brand/scripts/inject-brand-context.cjs +349 -0
- package/assets/skills/brand/scripts/sync-brand-to-tokens.cjs +266 -0
- package/assets/skills/brand/scripts/validate-asset.cjs +387 -0
- package/assets/skills/brand/templates/brand-guidelines-starter.md +275 -0
- package/assets/skills/design/SKILL.md +313 -0
- package/assets/skills/design/data/cip/deliverables.csv +51 -0
- package/assets/skills/design/data/cip/industries.csv +21 -0
- package/assets/skills/design/data/cip/mockup-contexts.csv +21 -0
- package/assets/skills/design/data/cip/styles.csv +21 -0
- package/assets/skills/design/data/icon/styles.csv +16 -0
- package/assets/skills/design/data/logo/colors.csv +56 -0
- package/assets/skills/design/data/logo/industries.csv +56 -0
- package/assets/skills/design/data/logo/styles.csv +56 -0
- package/assets/skills/design/references/banner-sizes-and-styles.md +118 -0
- package/assets/skills/design/references/cip-deliverable-guide.md +95 -0
- package/assets/skills/design/references/cip-design.md +121 -0
- package/assets/skills/design/references/cip-prompt-engineering.md +84 -0
- package/assets/skills/design/references/cip-style-guide.md +68 -0
- package/assets/skills/design/references/design-routing.md +207 -0
- package/assets/skills/design/references/icon-design.md +122 -0
- package/assets/skills/design/references/logo-color-psychology.md +101 -0
- package/assets/skills/design/references/logo-design.md +92 -0
- package/assets/skills/design/references/logo-prompt-engineering.md +158 -0
- package/assets/skills/design/references/logo-style-guide.md +109 -0
- package/assets/skills/design/references/slides-copywriting-formulas.md +84 -0
- package/assets/skills/design/references/slides-create.md +4 -0
- package/assets/skills/design/references/slides-html-template.md +295 -0
- package/assets/skills/design/references/slides-layout-patterns.md +137 -0
- package/assets/skills/design/references/slides-strategies.md +94 -0
- package/assets/skills/design/references/slides.md +42 -0
- package/assets/skills/design/references/social-photos-design.md +329 -0
- package/assets/skills/design/scripts/cip/core.py +215 -0
- package/assets/skills/design/scripts/cip/generate.py +484 -0
- package/assets/skills/design/scripts/cip/render-html.py +424 -0
- package/assets/skills/design/scripts/cip/search.py +127 -0
- package/assets/skills/design/scripts/icon/generate.py +487 -0
- package/assets/skills/design/scripts/logo/core.py +175 -0
- package/assets/skills/design/scripts/logo/generate.py +362 -0
- package/assets/skills/design/scripts/logo/search.py +114 -0
- package/assets/skills/design-system/SKILL.md +244 -0
- package/assets/skills/design-system/data/slide-backgrounds.csv +11 -0
- package/assets/skills/design-system/data/slide-charts.csv +26 -0
- package/assets/skills/design-system/data/slide-color-logic.csv +14 -0
- package/assets/skills/design-system/data/slide-copy.csv +26 -0
- package/assets/skills/design-system/data/slide-layout-logic.csv +16 -0
- package/assets/skills/design-system/data/slide-layouts.csv +26 -0
- package/assets/skills/design-system/data/slide-strategies.csv +16 -0
- package/assets/skills/design-system/data/slide-typography.csv +15 -0
- package/assets/skills/design-system/references/component-specs.md +236 -0
- package/assets/skills/design-system/references/component-tokens.md +214 -0
- package/assets/skills/design-system/references/primitive-tokens.md +203 -0
- package/assets/skills/design-system/references/semantic-tokens.md +215 -0
- package/assets/skills/design-system/references/states-and-variants.md +241 -0
- package/assets/skills/design-system/references/tailwind-integration.md +251 -0
- package/assets/skills/design-system/references/token-architecture.md +224 -0
- package/assets/skills/design-system/scripts/embed-tokens.cjs +99 -0
- package/assets/skills/design-system/scripts/fetch-background.py +317 -0
- package/assets/skills/design-system/scripts/generate-slide.py +770 -0
- package/assets/skills/design-system/scripts/generate-tokens.cjs +205 -0
- package/assets/skills/design-system/scripts/html-token-validator.py +327 -0
- package/assets/skills/design-system/scripts/search-slides.py +218 -0
- package/assets/skills/design-system/scripts/slide-token-validator.py +35 -0
- package/assets/skills/design-system/scripts/slide_search_core.py +453 -0
- package/assets/skills/design-system/scripts/validate-tokens.cjs +251 -0
- package/assets/skills/design-system/templates/design-tokens-starter.json +143 -0
- package/assets/skills/slides/SKILL.md +40 -0
- package/assets/skills/slides/references/copywriting-formulas.md +84 -0
- package/assets/skills/slides/references/create.md +4 -0
- package/assets/skills/slides/references/html-template.md +295 -0
- package/assets/skills/slides/references/layout-patterns.md +137 -0
- package/assets/skills/slides/references/slide-strategies.md +94 -0
- package/assets/skills/ui-styling/LICENSE.txt +202 -0
- package/assets/skills/ui-styling/SKILL.md +324 -0
- package/assets/skills/ui-styling/references/canvas-design-system.md +320 -0
- package/assets/skills/ui-styling/references/shadcn-accessibility.md +471 -0
- package/assets/skills/ui-styling/references/shadcn-components.md +424 -0
- package/assets/skills/ui-styling/references/shadcn-theming.md +373 -0
- package/assets/skills/ui-styling/references/tailwind-customization.md +483 -0
- package/assets/skills/ui-styling/references/tailwind-responsive.md +382 -0
- package/assets/skills/ui-styling/references/tailwind-utilities.md +455 -0
- package/assets/skills/ui-styling/scripts/requirements.txt +17 -0
- package/assets/skills/ui-styling/scripts/shadcn_add.py +308 -0
- package/assets/skills/ui-styling/scripts/tailwind_config_gen.py +473 -0
- package/assets/skills/ui-styling/scripts/tests/coverage-ui.json +1 -0
- package/assets/skills/ui-styling/scripts/tests/requirements.txt +3 -0
- package/assets/skills/ui-styling/scripts/tests/test_shadcn_add.py +266 -0
- package/assets/skills/ui-styling/scripts/tests/test_tailwind_config_gen.py +336 -0
- package/assets/templates/base/quick-reference.md +297 -0
- package/assets/templates/base/skill-content.md +368 -0
- package/assets/templates/platforms/agent.json +21 -0
- package/assets/templates/platforms/augment.json +18 -0
- package/assets/templates/platforms/claude.json +21 -0
- package/assets/templates/platforms/codebuddy.json +21 -0
- package/assets/templates/platforms/codex.json +21 -0
- package/assets/templates/platforms/continue.json +21 -0
- package/assets/templates/platforms/copilot.json +21 -0
- package/assets/templates/platforms/cursor.json +21 -0
- package/assets/templates/platforms/droid.json +21 -0
- package/assets/templates/platforms/gemini.json +21 -0
- package/assets/templates/platforms/kilocode.json +21 -0
- package/assets/templates/platforms/kiro.json +21 -0
- package/assets/templates/platforms/opencode.json +21 -0
- package/assets/templates/platforms/qoder.json +21 -0
- package/assets/templates/platforms/roocode.json +21 -0
- package/assets/templates/platforms/trae.json +21 -0
- package/assets/templates/platforms/warp.json +18 -0
- package/assets/templates/platforms/windsurf.json +21 -0
- package/dist/index.js +10630 -0
- package/package.json +51 -0
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
CIP Design Generator - Generate corporate identity mockups using Gemini Nano Banana
|
|
5
|
+
|
|
6
|
+
Uses Gemini's native image generation (Nano Banana Flash/Pro) for high-quality mockups.
|
|
7
|
+
Supports text-and-image-to-image generation for using actual brand logos.
|
|
8
|
+
|
|
9
|
+
- gemini-2.5-flash-image: Fast generation, cost-effective (default)
|
|
10
|
+
- gemini-3-pro-image-preview: Pro quality, 4K text rendering
|
|
11
|
+
|
|
12
|
+
Image Editing (text-and-image-to-image):
|
|
13
|
+
When --logo is provided, the script uses Gemini's image editing capability
|
|
14
|
+
to incorporate the actual logo into CIP mockups instead of generating one.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import argparse
|
|
18
|
+
import json
|
|
19
|
+
import os
|
|
20
|
+
import sys
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from datetime import datetime
|
|
23
|
+
|
|
24
|
+
# Add parent directory for imports
|
|
25
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
26
|
+
from core import search, get_cip_brief
|
|
27
|
+
|
|
28
|
+
# Model options
|
|
29
|
+
MODELS = {
|
|
30
|
+
"flash": "gemini-2.5-flash-image", # Nano Banana Flash - fast, default
|
|
31
|
+
"pro": "gemini-3-pro-image-preview" # Nano Banana Pro - quality, 4K text
|
|
32
|
+
}
|
|
33
|
+
DEFAULT_MODEL = "flash"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def load_logo_image(logo_path):
|
|
37
|
+
"""Load logo image using PIL for Gemini image editing"""
|
|
38
|
+
try:
|
|
39
|
+
from PIL import Image
|
|
40
|
+
except ImportError:
|
|
41
|
+
print("Error: pillow package not installed.")
|
|
42
|
+
print("Install with: pip install pillow")
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
logo_path = Path(logo_path)
|
|
46
|
+
if not logo_path.exists():
|
|
47
|
+
print(f"Error: Logo file not found: {logo_path}")
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
img = Image.open(logo_path)
|
|
52
|
+
# Convert to RGB if necessary (Gemini works best with RGB)
|
|
53
|
+
if img.mode in ('RGBA', 'P'):
|
|
54
|
+
# Create white background for transparent images
|
|
55
|
+
background = Image.new('RGB', img.size, (255, 255, 255))
|
|
56
|
+
if img.mode == 'RGBA':
|
|
57
|
+
background.paste(img, mask=img.split()[3]) # Use alpha channel as mask
|
|
58
|
+
else:
|
|
59
|
+
background.paste(img)
|
|
60
|
+
img = background
|
|
61
|
+
elif img.mode != 'RGB':
|
|
62
|
+
img = img.convert('RGB')
|
|
63
|
+
return img
|
|
64
|
+
except Exception as e:
|
|
65
|
+
print(f"Error loading logo: {e}")
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
# Load environment variables
|
|
69
|
+
def load_env():
|
|
70
|
+
"""Load environment variables from .env files"""
|
|
71
|
+
env_paths = [
|
|
72
|
+
Path(__file__).parent.parent.parent / ".env",
|
|
73
|
+
Path.home() / ".claude" / "skills" / ".env",
|
|
74
|
+
Path.home() / ".claude" / ".env"
|
|
75
|
+
]
|
|
76
|
+
for env_path in env_paths:
|
|
77
|
+
if env_path.exists():
|
|
78
|
+
with open(env_path) as f:
|
|
79
|
+
for line in f:
|
|
80
|
+
line = line.strip()
|
|
81
|
+
if line and not line.startswith("#") and "=" in line:
|
|
82
|
+
key, value = line.split("=", 1)
|
|
83
|
+
if key not in os.environ:
|
|
84
|
+
os.environ[key] = value.strip('"\'')
|
|
85
|
+
|
|
86
|
+
load_env()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def build_cip_prompt(deliverable, brand_name, style=None, industry=None, mockup=None, use_logo_image=False):
|
|
90
|
+
"""Build an optimized prompt for CIP mockup generation
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
deliverable: Type of deliverable (business card, letterhead, etc.)
|
|
94
|
+
brand_name: Name of the brand
|
|
95
|
+
style: Design style preference
|
|
96
|
+
industry: Industry for style recommendations
|
|
97
|
+
mockup: Mockup context override
|
|
98
|
+
use_logo_image: If True, prompt is optimized for image editing with logo
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
# Get deliverable details
|
|
102
|
+
deliverable_info = search(deliverable, "deliverable", 1)
|
|
103
|
+
deliverable_data = deliverable_info.get("results", [{}])[0] if deliverable_info.get("results") else {}
|
|
104
|
+
|
|
105
|
+
# Get style details
|
|
106
|
+
style_info = search(style or "corporate minimal", "style", 1) if style else {}
|
|
107
|
+
style_data = style_info.get("results", [{}])[0] if style_info.get("results") else {}
|
|
108
|
+
|
|
109
|
+
# Get industry details
|
|
110
|
+
industry_info = search(industry or "technology", "industry", 1) if industry else {}
|
|
111
|
+
industry_data = industry_info.get("results", [{}])[0] if industry_info.get("results") else {}
|
|
112
|
+
|
|
113
|
+
# Get mockup context
|
|
114
|
+
mockup_context = deliverable_data.get("Mockup Context", "clean professional")
|
|
115
|
+
if mockup:
|
|
116
|
+
mockup_info = search(mockup, "mockup", 1)
|
|
117
|
+
if mockup_info.get("results"):
|
|
118
|
+
mockup_data = mockup_info["results"][0]
|
|
119
|
+
mockup_context = mockup_data.get("Scene Description", mockup_context)
|
|
120
|
+
|
|
121
|
+
# Build prompt components
|
|
122
|
+
deliverable_name = deliverable_data.get("Deliverable", deliverable)
|
|
123
|
+
description = deliverable_data.get("Description", "")
|
|
124
|
+
dimensions = deliverable_data.get("Dimensions", "")
|
|
125
|
+
logo_placement = deliverable_data.get("Logo Placement", "center")
|
|
126
|
+
|
|
127
|
+
style_name = style_data.get("Style Name", style or "corporate")
|
|
128
|
+
primary_colors = style_data.get("Primary Colors", industry_data.get("Primary Colors", "#0F172A #FFFFFF"))
|
|
129
|
+
typography = style_data.get("Typography", industry_data.get("Typography", "clean sans-serif"))
|
|
130
|
+
materials = style_data.get("Materials", "premium quality")
|
|
131
|
+
finishes = style_data.get("Finishes", "professional")
|
|
132
|
+
|
|
133
|
+
mood = style_data.get("Mood", industry_data.get("Mood", "professional"))
|
|
134
|
+
|
|
135
|
+
# Construct the prompt - different for image editing vs pure generation
|
|
136
|
+
if use_logo_image:
|
|
137
|
+
# Image editing prompt: instructs to USE the provided logo image
|
|
138
|
+
prompt_parts = [
|
|
139
|
+
f"Create a professional corporate identity mockup photograph of a {deliverable_name}",
|
|
140
|
+
f"Use the EXACT logo from the provided image - do NOT modify or recreate the logo",
|
|
141
|
+
f"The logo MUST appear exactly as shown in the input image",
|
|
142
|
+
f"Place the logo on the {deliverable_name} at: {logo_placement}",
|
|
143
|
+
f"Brand name: '{brand_name}'",
|
|
144
|
+
f"{description}" if description else "",
|
|
145
|
+
f"Design style: {style_name}",
|
|
146
|
+
f"Color scheme matching the logo colors",
|
|
147
|
+
f"Materials: {materials} with {finishes} finish",
|
|
148
|
+
f"Setting: {mockup_context}",
|
|
149
|
+
f"Mood: {mood}",
|
|
150
|
+
"Photorealistic product photography",
|
|
151
|
+
"Soft natural lighting, professional studio quality",
|
|
152
|
+
"8K resolution, sharp details"
|
|
153
|
+
]
|
|
154
|
+
else:
|
|
155
|
+
# Pure text-to-image prompt
|
|
156
|
+
prompt_parts = [
|
|
157
|
+
f"Professional corporate identity mockup photograph",
|
|
158
|
+
f"showing {deliverable_name} for brand '{brand_name}'",
|
|
159
|
+
f"{description}" if description else "",
|
|
160
|
+
f"{style_name} design style",
|
|
161
|
+
f"using colors {primary_colors}",
|
|
162
|
+
f"{typography} typography",
|
|
163
|
+
f"logo placement: {logo_placement}",
|
|
164
|
+
f"{materials} materials with {finishes} finish",
|
|
165
|
+
f"{mockup_context} setting",
|
|
166
|
+
f"{mood} mood",
|
|
167
|
+
"photorealistic product photography",
|
|
168
|
+
"soft natural lighting",
|
|
169
|
+
"high quality professional shot",
|
|
170
|
+
"8k resolution detailed"
|
|
171
|
+
]
|
|
172
|
+
|
|
173
|
+
prompt = ", ".join([p for p in prompt_parts if p])
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
"prompt": prompt,
|
|
177
|
+
"deliverable": deliverable_name,
|
|
178
|
+
"style": style_name,
|
|
179
|
+
"brand": brand_name,
|
|
180
|
+
"colors": primary_colors,
|
|
181
|
+
"mockup_context": mockup_context,
|
|
182
|
+
"logo_placement": logo_placement
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def generate_with_nano_banana(prompt_data, output_dir=None, model_key="flash", aspect_ratio="1:1", logo_image=None):
|
|
187
|
+
"""Generate image using Gemini Nano Banana (native image generation)
|
|
188
|
+
|
|
189
|
+
Supports two modes:
|
|
190
|
+
1. Text-to-image: Pure prompt-based generation (logo_image=None)
|
|
191
|
+
2. Image editing: Text-and-image-to-image using provided logo (logo_image=PIL.Image)
|
|
192
|
+
|
|
193
|
+
Models:
|
|
194
|
+
- flash: gemini-2.5-flash-image (fast, cost-effective) - DEFAULT
|
|
195
|
+
- pro: gemini-3-pro-image-preview (quality, 4K text rendering)
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
prompt_data: Dict with prompt, deliverable, brand, etc.
|
|
199
|
+
output_dir: Output directory for generated images
|
|
200
|
+
model_key: 'flash' or 'pro'
|
|
201
|
+
aspect_ratio: Output aspect ratio (1:1, 16:9, etc.)
|
|
202
|
+
logo_image: PIL.Image object of the brand logo for image editing mode
|
|
203
|
+
"""
|
|
204
|
+
try:
|
|
205
|
+
from google import genai
|
|
206
|
+
from google.genai import types
|
|
207
|
+
except ImportError:
|
|
208
|
+
print("Error: google-genai package not installed.")
|
|
209
|
+
print("Install with: pip install google-genai")
|
|
210
|
+
return None
|
|
211
|
+
|
|
212
|
+
api_key = os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY")
|
|
213
|
+
if not api_key:
|
|
214
|
+
print("Error: GEMINI_API_KEY or GOOGLE_API_KEY not set")
|
|
215
|
+
return None
|
|
216
|
+
|
|
217
|
+
client = genai.Client(api_key=api_key)
|
|
218
|
+
|
|
219
|
+
prompt = prompt_data["prompt"]
|
|
220
|
+
model_name = MODELS.get(model_key, MODELS[DEFAULT_MODEL])
|
|
221
|
+
|
|
222
|
+
# Determine mode
|
|
223
|
+
mode = "image-editing" if logo_image else "text-to-image"
|
|
224
|
+
|
|
225
|
+
print(f"\n🎨 Generating CIP mockup...")
|
|
226
|
+
print(f" Mode: {mode}")
|
|
227
|
+
print(f" Deliverable: {prompt_data['deliverable']}")
|
|
228
|
+
print(f" Brand: {prompt_data['brand']}")
|
|
229
|
+
print(f" Style: {prompt_data['style']}")
|
|
230
|
+
print(f" Model: {model_name}")
|
|
231
|
+
print(f" Context: {prompt_data['mockup_context']}")
|
|
232
|
+
if logo_image:
|
|
233
|
+
print(f" Logo: Using provided image ({logo_image.size[0]}x{logo_image.size[1]})")
|
|
234
|
+
|
|
235
|
+
try:
|
|
236
|
+
# Build contents: either just prompt or [prompt, image] for image editing
|
|
237
|
+
if logo_image:
|
|
238
|
+
# Image editing mode: pass both prompt and logo image
|
|
239
|
+
contents = [prompt, logo_image]
|
|
240
|
+
else:
|
|
241
|
+
# Text-to-image mode: just the prompt
|
|
242
|
+
contents = prompt
|
|
243
|
+
|
|
244
|
+
# Use generate_content with response_modalities=['IMAGE'] for Nano Banana
|
|
245
|
+
response = client.models.generate_content(
|
|
246
|
+
model=model_name,
|
|
247
|
+
contents=contents,
|
|
248
|
+
config=types.GenerateContentConfig(
|
|
249
|
+
response_modalities=['IMAGE'], # Uppercase required
|
|
250
|
+
image_config=types.ImageConfig(
|
|
251
|
+
aspect_ratio=aspect_ratio
|
|
252
|
+
)
|
|
253
|
+
)
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
# Extract image from response
|
|
257
|
+
if response.candidates and response.candidates[0].content.parts:
|
|
258
|
+
for part in response.candidates[0].content.parts:
|
|
259
|
+
if hasattr(part, 'inline_data') and part.inline_data:
|
|
260
|
+
# Save image
|
|
261
|
+
output_dir = output_dir or Path.cwd()
|
|
262
|
+
output_dir = Path(output_dir)
|
|
263
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
264
|
+
|
|
265
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
266
|
+
brand_slug = prompt_data["brand"].lower().replace(" ", "-")
|
|
267
|
+
deliverable_slug = prompt_data["deliverable"].lower().replace(" ", "-")
|
|
268
|
+
filename = f"{brand_slug}-{deliverable_slug}-{timestamp}.png"
|
|
269
|
+
filepath = output_dir / filename
|
|
270
|
+
|
|
271
|
+
image_data = part.inline_data.data
|
|
272
|
+
with open(filepath, "wb") as f:
|
|
273
|
+
f.write(image_data)
|
|
274
|
+
|
|
275
|
+
print(f"\n✅ Generated: {filepath}")
|
|
276
|
+
return str(filepath)
|
|
277
|
+
|
|
278
|
+
print("No image generated in response")
|
|
279
|
+
return None
|
|
280
|
+
|
|
281
|
+
except Exception as e:
|
|
282
|
+
print(f"Error generating image: {e}")
|
|
283
|
+
return None
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def generate_cip_set(brand_name, industry, style=None, deliverables=None, output_dir=None, model_key="flash", logo_path=None, aspect_ratio="1:1"):
|
|
287
|
+
"""Generate a complete CIP set for a brand
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
brand_name: Brand name to generate for
|
|
291
|
+
industry: Industry type for style recommendations
|
|
292
|
+
style: Optional specific style override
|
|
293
|
+
deliverables: List of deliverables to generate (default: core set)
|
|
294
|
+
output_dir: Output directory for images
|
|
295
|
+
model_key: 'flash' (fast) or 'pro' (quality)
|
|
296
|
+
logo_path: Path to brand logo image for image editing mode
|
|
297
|
+
aspect_ratio: Output aspect ratio
|
|
298
|
+
"""
|
|
299
|
+
|
|
300
|
+
# Load logo image if provided
|
|
301
|
+
logo_image = None
|
|
302
|
+
if logo_path:
|
|
303
|
+
logo_image = load_logo_image(logo_path)
|
|
304
|
+
if not logo_image:
|
|
305
|
+
print("Warning: Could not load logo, falling back to text-to-image mode")
|
|
306
|
+
|
|
307
|
+
# Get CIP brief for the brand
|
|
308
|
+
brief = get_cip_brief(brand_name, industry, style)
|
|
309
|
+
|
|
310
|
+
# Default deliverables if not specified
|
|
311
|
+
if not deliverables:
|
|
312
|
+
deliverables = ["business card", "letterhead", "office signage", "vehicle", "polo shirt"]
|
|
313
|
+
|
|
314
|
+
results = []
|
|
315
|
+
for deliverable in deliverables:
|
|
316
|
+
prompt_data = build_cip_prompt(
|
|
317
|
+
deliverable=deliverable,
|
|
318
|
+
brand_name=brand_name,
|
|
319
|
+
style=brief.get("style", {}).get("Style Name"),
|
|
320
|
+
industry=industry,
|
|
321
|
+
use_logo_image=(logo_image is not None)
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
filepath = generate_with_nano_banana(
|
|
325
|
+
prompt_data,
|
|
326
|
+
output_dir,
|
|
327
|
+
model_key=model_key,
|
|
328
|
+
aspect_ratio=aspect_ratio,
|
|
329
|
+
logo_image=logo_image
|
|
330
|
+
)
|
|
331
|
+
if filepath:
|
|
332
|
+
results.append({
|
|
333
|
+
"deliverable": deliverable,
|
|
334
|
+
"filepath": filepath,
|
|
335
|
+
"prompt": prompt_data["prompt"]
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
return results
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def check_logo_required(brand_name, skip_prompt=False):
|
|
342
|
+
"""Check if logo is required and suggest logo-design skill if not provided
|
|
343
|
+
|
|
344
|
+
Returns:
|
|
345
|
+
str: 'continue' to proceed without logo, 'generate' to use logo-design skill, 'exit' to abort
|
|
346
|
+
"""
|
|
347
|
+
if skip_prompt:
|
|
348
|
+
return 'continue'
|
|
349
|
+
|
|
350
|
+
print(f"\n⚠️ No logo image provided for '{brand_name}'")
|
|
351
|
+
print(" Without a logo, AI will generate its own interpretation of the brand logo.")
|
|
352
|
+
print("")
|
|
353
|
+
print(" Options:")
|
|
354
|
+
print(" 1. Continue without logo (AI-generated logo interpretation)")
|
|
355
|
+
print(" 2. Generate a logo first using 'logo-design' skill")
|
|
356
|
+
print(" 3. Exit and provide a logo path with --logo")
|
|
357
|
+
print("")
|
|
358
|
+
|
|
359
|
+
try:
|
|
360
|
+
choice = input(" Enter choice [1/2/3] (default: 1): ").strip()
|
|
361
|
+
if choice == '2':
|
|
362
|
+
return 'generate'
|
|
363
|
+
elif choice == '3':
|
|
364
|
+
return 'exit'
|
|
365
|
+
return 'continue'
|
|
366
|
+
except (EOFError, KeyboardInterrupt):
|
|
367
|
+
return 'continue'
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def main():
|
|
371
|
+
parser = argparse.ArgumentParser(
|
|
372
|
+
description="Generate CIP mockups using Gemini Nano Banana",
|
|
373
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
374
|
+
epilog="""
|
|
375
|
+
Examples:
|
|
376
|
+
# Generate with brand logo (RECOMMENDED)
|
|
377
|
+
python generate.py --brand "TopGroup" --logo /path/to/logo.png --deliverable "business card"
|
|
378
|
+
|
|
379
|
+
# Generate CIP set with logo
|
|
380
|
+
python generate.py --brand "TopGroup" --logo /path/to/logo.png --industry "consulting" --set
|
|
381
|
+
|
|
382
|
+
# Generate without logo (AI interprets brand)
|
|
383
|
+
python generate.py --brand "TechFlow" --deliverable "business card" --no-logo-prompt
|
|
384
|
+
|
|
385
|
+
# Generate with Pro model (higher quality, 4K text)
|
|
386
|
+
python generate.py --brand "TechFlow" --logo logo.png --deliverable "business card" --model pro
|
|
387
|
+
|
|
388
|
+
# Specify output directory and aspect ratio
|
|
389
|
+
python generate.py --brand "MyBrand" --logo logo.png --deliverable "vehicle" --output ./mockups --ratio 16:9
|
|
390
|
+
|
|
391
|
+
Models:
|
|
392
|
+
flash (default): gemini-2.5-flash-image - Fast, cost-effective
|
|
393
|
+
pro: gemini-3-pro-image-preview - Quality, 4K text rendering
|
|
394
|
+
|
|
395
|
+
Image Editing Mode:
|
|
396
|
+
When --logo is provided, uses Gemini's text-and-image-to-image capability
|
|
397
|
+
to incorporate your ACTUAL logo into the CIP mockups.
|
|
398
|
+
"""
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
parser.add_argument("--brand", "-b", required=True, help="Brand name")
|
|
402
|
+
parser.add_argument("--logo", "-l", help="Path to brand logo image (enables image editing mode)")
|
|
403
|
+
parser.add_argument("--deliverable", "-d", help="Single deliverable to generate")
|
|
404
|
+
parser.add_argument("--deliverables", help="Comma-separated list of deliverables")
|
|
405
|
+
parser.add_argument("--industry", "-i", default="technology", help="Industry type")
|
|
406
|
+
parser.add_argument("--style", "-s", help="Design style")
|
|
407
|
+
parser.add_argument("--mockup", "-m", help="Mockup context")
|
|
408
|
+
parser.add_argument("--set", action="store_true", help="Generate full CIP set")
|
|
409
|
+
parser.add_argument("--output", "-o", help="Output directory")
|
|
410
|
+
parser.add_argument("--model", default="flash", choices=["flash", "pro"], help="Model: flash (fast) or pro (quality)")
|
|
411
|
+
parser.add_argument("--ratio", default="1:1", help="Aspect ratio (1:1, 16:9, 4:3, etc.)")
|
|
412
|
+
parser.add_argument("--prompt-only", action="store_true", help="Only show prompt, don't generate")
|
|
413
|
+
parser.add_argument("--json", "-j", action="store_true", help="Output as JSON")
|
|
414
|
+
parser.add_argument("--no-logo-prompt", action="store_true", help="Skip logo prompt, proceed without logo")
|
|
415
|
+
|
|
416
|
+
args = parser.parse_args()
|
|
417
|
+
|
|
418
|
+
# Check if logo is provided, prompt user if not
|
|
419
|
+
logo_image = None
|
|
420
|
+
if args.logo:
|
|
421
|
+
logo_image = load_logo_image(args.logo)
|
|
422
|
+
if not logo_image:
|
|
423
|
+
print("Error: Could not load logo image")
|
|
424
|
+
sys.exit(1)
|
|
425
|
+
elif not args.prompt_only:
|
|
426
|
+
# No logo provided - ask user what to do
|
|
427
|
+
action = check_logo_required(args.brand, skip_prompt=args.no_logo_prompt)
|
|
428
|
+
if action == 'generate':
|
|
429
|
+
print("\n💡 To generate a logo, use the logo-design skill:")
|
|
430
|
+
print(f" python ~/.claude/skills/design/scripts/logo/generate.py --brand \"{args.brand}\" --industry \"{args.industry}\"")
|
|
431
|
+
print("\n Then re-run this command with --logo <generated_logo.png>")
|
|
432
|
+
sys.exit(0)
|
|
433
|
+
elif action == 'exit':
|
|
434
|
+
print("\n Provide logo with: --logo /path/to/your/logo.png")
|
|
435
|
+
sys.exit(0)
|
|
436
|
+
# else: continue without logo
|
|
437
|
+
|
|
438
|
+
use_logo = logo_image is not None
|
|
439
|
+
|
|
440
|
+
if args.set or args.deliverables:
|
|
441
|
+
# Generate multiple deliverables
|
|
442
|
+
deliverables = args.deliverables.split(",") if args.deliverables else None
|
|
443
|
+
|
|
444
|
+
if args.prompt_only:
|
|
445
|
+
results = []
|
|
446
|
+
deliverables = deliverables or ["business card", "letterhead", "office signage", "vehicle", "polo shirt"]
|
|
447
|
+
for d in deliverables:
|
|
448
|
+
prompt_data = build_cip_prompt(d, args.brand, args.style, args.industry, args.mockup, use_logo_image=use_logo)
|
|
449
|
+
results.append(prompt_data)
|
|
450
|
+
if args.json:
|
|
451
|
+
print(json.dumps(results, indent=2))
|
|
452
|
+
else:
|
|
453
|
+
for r in results:
|
|
454
|
+
print(f"\n{r['deliverable']}:\n{r['prompt']}\n")
|
|
455
|
+
else:
|
|
456
|
+
results = generate_cip_set(
|
|
457
|
+
args.brand, args.industry, args.style, deliverables, args.output,
|
|
458
|
+
model_key=args.model, logo_path=args.logo, aspect_ratio=args.ratio
|
|
459
|
+
)
|
|
460
|
+
if args.json:
|
|
461
|
+
print(json.dumps(results, indent=2))
|
|
462
|
+
else:
|
|
463
|
+
print(f"\n✅ Generated {len(results)} CIP mockups")
|
|
464
|
+
else:
|
|
465
|
+
# Generate single deliverable
|
|
466
|
+
deliverable = args.deliverable or "business card"
|
|
467
|
+
prompt_data = build_cip_prompt(deliverable, args.brand, args.style, args.industry, args.mockup, use_logo_image=use_logo)
|
|
468
|
+
|
|
469
|
+
if args.prompt_only:
|
|
470
|
+
if args.json:
|
|
471
|
+
print(json.dumps(prompt_data, indent=2))
|
|
472
|
+
else:
|
|
473
|
+
print(f"\nPrompt:\n{prompt_data['prompt']}")
|
|
474
|
+
else:
|
|
475
|
+
filepath = generate_with_nano_banana(
|
|
476
|
+
prompt_data, args.output, model_key=args.model,
|
|
477
|
+
aspect_ratio=args.ratio, logo_image=logo_image
|
|
478
|
+
)
|
|
479
|
+
if args.json:
|
|
480
|
+
print(json.dumps({"filepath": filepath, **prompt_data}, indent=2))
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
if __name__ == "__main__":
|
|
484
|
+
main()
|