creative-poster
Production-grade генератор статичных постеров для Meta/Instagram через Gemini 3 Pro Image. Brand-library, multi-shot referencing, итеративный refine, variant explosion, multi-aspect outpaint, Vision-based QA, OCR конкурентов, locale-aware рендер, cross-model fallback. Пэйрится с creative-orchestrator.
Что делает простыми словами
Это «студия статичной рекламы». Дёргает Gemini 3 Pro Image (он же nano-banana-pro), знает как промптить постеры по 5-компонентной формуле, автоматически подмешивает brand-context из проекта и проверяет результат на типографические ошибки. По шагам:
- Загружает brand.yaml проекта → palette, шрифты, voice, forbidden — собирает BRAND CONTEXT блок
- Загружает preset recipe (один из 16 эстетических пресетов) → typography, palette, layout hints, avoid
- Применяет locale (ru/kk/en/uk) — добавляет text rendering hint для алфавита
- Если переданы
--referenceкартинки с ролями → multi-shot композиция с explicit role mapping - Собирает финальный промпт по 5-компонентной формуле (SUBJECT + ACTION + LOCATION + COMPOSITION + STYLE)
- Дёргает
gemini-3-pro-image-preview, при 429/503 — fallback chain - Логирует в
creative_postersтаблицу - Открывает HTML preview-страницу с payload sidebar (GR-1)
director.db, та же brand library — другой output формат (PNG вместо MP4). Используется для Meta/Instagram Feed (4:5) и Story (9:16) креативов.
5-Component Prompt Formula
Промпт для Gemini Pro Image собирается по жёсткой схеме (source: banana-claude, Google Cloud guide):
| Component | Что описывается |
|---|---|
| SUBJECT | Hero-объект с explicit reference role(s) — что главное в кадре, какая reference-картинка играет роль hero, какая — side angle, какая — logo |
| ACTION | Что происходит + viewer eye-tracking flow (куда движется взгляд зрителя по композиции) |
| LOCATION | World-building и атмосфера сцены — из user brief |
| COMPOSITION | Rule-of-thirds, где каждый элемент сидит в процентах (например «headline в верхней трети 15-25%, продукт в центре 40-60%») |
| STYLE | Camera (50mm equiv, 5° low angle), lighting RESULT (off-screen источники, никогда не visible equipment), artistic reference (Apple keynote / Philips Healthcare poster) |
HARD CONSTRAINTS (зашиты в SYSTEM_RULES)
Эти правила автоматически инжектятся в каждый промпт и проверяются в QA. Нарушение = auto-fail.
| # | Constraint | Почему |
|---|---|---|
| 1 | NO CTA button — никаких pill/badge с «Подробнее», «Узнать больше», «Записаться», «WhatsApp», стрелки → с текстом, любые clickable-looking прямоугольники | Meta добавляет CTA сама через page connection. Двойная кнопка = конфликт. |
| 2 | NO brand logo / wordmark / tagline / watermark | Meta добавляет page name + avatar автоматически. Бренд передаётся через colors/fonts/voice, не через рисование «APPARATUS» в углу. |
| 3 | NO photo/lighting equipment in frame — softbox, octobox, ring light, umbrella, light stand, tripod, reflector, gel, фотограф, камера всегда OFF-CAMERA | Видимый только результат света (тень, gradient, rim glow), не источник. Профессиональная съёмка не показывает оборудование. |
| 4 | Unicode glyph fidelity — ₸ это U+20B8, не Cyrillic Т; × это U+00D7, не Latin x; — и – — настоящие тире, не - |
Gemini Pro Image любит подменять символы похожими буквами. Критично для KZ-проектов с тенге. |
| 5 | No text truncation — каждая quoted строка в FULL без сокращений. «ИК-терапия» не должно стать «ИК», «протоколы для всех зон» не должно стать «протоколы» | Если слишком длинно — уменьшать font-size, не обрезать слова. |
| 6 | Single continuous background — никаких frames/borders/colored bars/zones edge-to-edge | Чтобы outpaint в 9:16 / 1:1 / 2:3 работал бесшовно. |
| 7 | NO служебных слов — «Offer», «Bullets», «4:5», «9:16», «Reels», «Stories», «Instagram», aspect-ratio цифры, safe-zone marker'ы | Эти слова попадают в промпт как разметка, но не должны проступать в финальном пикселе. |
| 8 | NO PROFIT badge как кнопка — PROFIT/BONUS текст в plain colored brand-accent цвете, без pill/capsule/ribbon/rounded rectangle background | Часто Gemini пытается обрамить PROFIT-текст плашкой, что выглядит как CTA = срабатывает constraint #1. |
multi_aspect.py отдельным шагом. Текст в центральной полосе 20-80% по вертикали, минимум 5% горизонтального margin.
16 aesthetic preset recipes
Каждый preset — YAML с description, typography, color_palette[], layout_hints[], avoid[]. Загружается через --preset-recipe <slug> и инжектится как PRESET RECIPE блок в промпт.
Original 8 (Wave 4L)
| Slug | Под что |
|---|---|
tech_minimal | SaaS, B2B, чистый минимал в духе Linear/Vercel |
premium_luxury | Premium-бренды, dark+gold, серьёзная типографика |
ugc_authentic | Натуральное UGC-ощущение, тёплый свет, неровная композиция |
editorial_magazine | Журнальный layout, Vogue/NYT, сильная типографика |
b2b_corporate | Корпоратив, deep navy + accent, чистые шрифты |
visual_hook_bold | Яркий контраст, большой текст, бьёт в глаз |
infographic_data | Цифры в центре, минимум картинки, чарты |
product_hero_clean | Продукт на белом, мягкий gradient, Apple keynote-стайл |
Added May 2026 (+8 из rohitg00/awesome-claude-design)
| Slug | Эстетика |
|---|---|
terminal_core | Berkeley Mono, Ollama-style — терминальный минимал |
warm_editorial | Cream + mocha + rust, Monocle-feel |
cinematic_dark | A24 / Apple keynote teaser, кинематографичная темнота |
playful_color | Notion / Linear плоский цвет, дружелюбно |
glass_futurism | visionOS / iOS 17 frosted glass |
neon_brutalist | Berghain / MSCHF / Off-White — резкий неон |
cult_indie | Mixed-media collage, Death & Co атмосфера |
swiss_minimal | Müller-Brockmann strict grid, швейцарская школа |
Кастомные пресеты добавляются как presets/<slug>.yaml в скилл-папку.
Brand auto-injection
Когда задан --project-dir, цепочка инжекции выглядит так:
1. Load
--project-dir/brand.yaml → BRAND CONTEXT блок (colors, fonts, voice, forbidden)
2. Load
--preset-recipe → PRESET RECIPE блок (typography, palette, layout hints, avoid)
3. Apply
--locale → text rendering hint (Cyrillic/Kazakh/English/Ukrainian)
4. If
--reference-role given → multi-shot composition с explicit role mapping
5. Try
--model → on 429/503 → fall through FALLBACK_CHAIN автоматически
brand.yaml — опциональная но настоятельно рекомендуемая штука. Без неё каждый gen.py требует brand colors/fonts/voice в --custom-prompt каждый раз. С ней — auto-injection.
Команды
Brand library
brand.py init <project-dir> [--from-project-yaml] brand.py show <project-dir> brand.py add-reference <project-dir> <image-path> brand.py validate <project-dir> brand.py to-prompt <project-dir> # рендерит brand-context блок
Генерация одного постера
gen.py \ --project-dir ~/video-projects/apparatus \ --output out.png \ --offer "..." --bullets "...\n...\n..." --profits "..." \ --reference path1.jpg --reference-role "hero product" \ --reference path2.jpg --reference-role "side angle" \ --reference path3.jpg --reference-role "logo asset" \ --style modern_performance \ --preset-recipe tech_minimal \ --custom-prompt "Brand: APPARATUS KZ. Background: deep navy gradient..." \ --locale ru \ [--aspect-ratio 4:5] [--upscale-4k] [--expand-9x16]
Refine (итерация)
refine.py --input poster.png --output v2.png \ --change "headline +30%, move device left, swap red badge for gold" \ --keep "layout, brand colors, all text content"
Multi-aspect (omnichannel)
multi_aspect.py --input base_4x5.png --output-dir out/ \ --formats feed,story,square,pinterest,wide \ --skip-same-aspect # Получим: <prefix>_feed_4x5.png, <prefix>_story_9x16.png, # <prefix>_square_1x1.png, и т.д.
Variants (A/B explosion)
variants.py --project-dir ~/video-projects/apparatus --output-dir out/ \ --base-offer "Конкурент уже купил УВТ" \ --bullets "...\n...\n..." --profits "..." --reference X \ --count 6 \ --explore-angles math,emotion,fear,curiosity,authority,benefit # Каждый angle переписывает OFFER через свою линзу # (math/emotion/fear/curiosity/authority/social/urgency/benefit) # через Gemini text model, потом дергает gen.py на каждый
QA (Vision-based)
qa_review.py --input poster.png \
--expect-text "Headline; Bullet1; Bullet2; Bullet3; Profit" \
[--brand-context "..."]
# → JSON: {score: 0-10, pass: bool, issues: [
# {type, severity, description, suggested_fix}
# ]}
# suggested_fix → сразу в refine.py --change
OCR (анализ конкурентов)
ocr.py --input competitor.jpg --structured # → JSON: headline / subhead / bullets / cta / profit_or_offer / # fine_print / brand / tagline # Фидится в video-copywriter --type reference
DB (track + learn)
db.py init # создать таблицы db.py log --output X.png --offer "..." --style ... # записать генерацию db.py list --project-dir ~/video-projects/apparatus db.py link-performance --poster-id N --fb-ad-id A --ctr 1.2 --cpl 3.4 db.py winners --project-dir ~/video-projects/apparatus --metric cpl
Multi-shot referencing
До 14 reference-картинок на запрос (для сравнения: у Veo лимит 3). Каждая может иметь explicit роль:
--reference hero.jpg --reference-role "hero product" --reference side.jpg --reference-role "side angle" --reference logo.png --reference-role "logo asset" --reference texture.jpg --reference-role "background texture"
Роли вшиваются в SUBJECT-блок как explicit «use IMAGE A for X, IMAGE B for Y» инструкции. Без ролей — Gemini сам решает что взять, что часто работает хуже.
Locales
| Locale | Что добавляет в промпт |
|---|---|
ru (default) | Cyrillic rendering hint, ё/ъ/ь fidelity |
kk | Kazakh Cyrillic с қ/ң/ғ/ү/ұ/һ/ә/і/ө |
en | Latin rendering, простая типографика |
uk | Ukrainian Cyrillic с і/ї/є/ґ |
Текст рендерится ровно так как передан — никакого авто-перевода. Locale только влияет на качество глифов.
Cross-model fallback chain
Default: gemini-3-pro-image-preview с автоматическим переходом при 429 / RESOURCE_EXHAUSTED / 500 / 503 / NOT_FOUND:
Качество падает по цепочке, но не падает с RESOURCE_EXHAUSTED-ошибкой. Отключить —
--no-fallback.
nano-banana-pro-preview — алиас для Pro-модели. Названия меняются между релизами, оба резолвятся.
Цены
| Операция | Модель | Цена |
|---|---|---|
| 4:5 base generation | gemini-3-pro-image-preview | $0.04 |
| 4K upscale (Pillow LANCZOS) | локально | free |
| 9:16 outpainting | gemini-3-pro-image-preview | $0.08 |
| QA review | gemini-2.5-flash | $0.001 |
| Refine (single) | gemini-3-pro-image-preview | $0.04 |
| OCR | gemini-2.5-flash | $0.001 |
| Variant rewrite (text only) | gemini-2.5-flash | $0.0001 |
Полный pipeline run (6 вариантов × 2 aspect'а + QA + delivery) ≈ $0.78. Дёшево относительно видео-пайплайна.
Скрипты
| Файл | Что делает |
|---|---|
scripts/gen.py главный |
Text→image с 5-component formula prompt. Brand auto-injection, multi-shot references, locale, cross-model fallback. Логирует в БД и открывает HTML preview. |
scripts/refine.py | Итеративный multi-turn edit (keep X, change Y) для тонкой подстройки |
scripts/multi_aspect.py | Outpaint base 4:5 → feed/story/square/pinterest/wide через SEAMLESS OUTPAINTING промпт |
scripts/variants.py |
Angle explosion — переписывает OFFER через линзы math/emotion/fear/curiosity/authority/social/urgency/benefit через Gemini text model, потом рендерит через gen.py |
scripts/qa_review.py |
Gemini Vision QA → JSON {score 0-10, pass, issues[{type, severity, description, suggested_fix}]}. suggested_fix сразу фидится в refine.py --change. |
scripts/ocr.py | OCR конкурентных постеров (plain или structured: headline / bullets / cta / profit / fine_print) |
scripts/brand.py |
brand.yaml CRUD (init, show, add-reference, validate, to-prompt). Auto-injection во все gen.py вызовы. |
scripts/db.py |
creative_posters + creative_performance + project_creative_posters таблицы. Логирует каждую генерацию, линкует Meta-API метрики для winners-репорта. |
scripts/present.py |
GR-1: HTML preview-страница с payload sidebar (model, aspect, style, preset, locale, cost, QA score, brand context, references thumbnails, custom prompt, final prompt) |
Auto-preview (GLOBAL RULE для всех creative-* скиллов)
После каждой успешной генерации gen.py автоматически логирует в creative_posters таблицу и открывает HTML preview-страницу с:
- Сгенерированный постер (кликабельно → fullscreen lightbox)
- Payload sidebar с full provenance:
- Production: model used, aspect, style, preset, locale, cost, QA score, timestamp
- Brand context: name, palette swatches, fonts
- Text payload: offer / bullets / profit (как цветные карточки)
- References: thumbnails + роли для каждого
--reference - Custom prompt (user input) + Final prompt (что ушло в модель)
Отключить — --no-present. Вручную: present.py --output-image X.png --output preview.html --open
Архитектура папки
~/.claude/skills/creative-poster/
├── SKILL.md ← spec + commands cheat-sheet
├── presets/ ← 16 aesthetic-family recipes
│ ├── tech_minimal.yaml
│ ├── premium_luxury.yaml
│ ├── ugc_authentic.yaml
│ ├── editorial_magazine.yaml
│ ├── b2b_corporate.yaml
│ ├── visual_hook_bold.yaml
│ ├── infographic_data.yaml
│ ├── product_hero_clean.yaml
│ ├── terminal_core.yaml ← May 2026
│ ├── warm_editorial.yaml ← May 2026
│ ├── cinematic_dark.yaml ← May 2026
│ ├── playful_color.yaml ← May 2026
│ ├── glass_futurism.yaml ← May 2026
│ ├── neon_brutalist.yaml ← May 2026
│ ├── cult_indie.yaml ← May 2026
│ └── swiss_minimal.yaml ← May 2026
└── scripts/
├── gen.py ← главный
├── refine.py
├── multi_aspect.py
├── variants.py
├── qa_review.py
├── ocr.py
├── brand.py
├── db.py
└── present.py ← GR-1 preview
Зависимости и env
pip install google-genai pillow pyyaml export GOOGLE_API_KEY=<key>
API-key auto-resolution: --api-key > --project-dir/api_keys.db > $GOOGLE_API_KEY.
Gotchas и tips
₸ glyph rendering ненадёжен (~50% failure rate). Тенге заменяется на Cyrillic Т. Митигации: (a) принять подмену (в KZ-контексте Т читается как тенге), (b) заменить ₸ словом «тенге» в исходнике, (c) post-process через Pillow overlay (auto-fix-pass в qa_review.py — TODO).
gen.py обрабатывает transient 429 переключением на gemini-2.5-flash-image автоматически.
gen.py требует brand colors/fonts/voice в --custom-prompt. С ним — auto-injection из проекта.
creative-poster/scripts/db.py init один раз. Идемпотентно — создаёт 3 таблицы (creative_posters, creative_performance, project_creative_posters) если их нет.
suggested_fix в каждом issue. Это форматированная строка которая сразу идёт в refine.py --change. Можно автоматизировать loop: generate → QA → if score < 7 → refine → QA → ... Останов на score ≥ 7 или max-iter.
variants.py --count 6 --explore-angles math,emotion,fear,curiosity,authority,benefit — даёт 6 разных подходов к одному и тому же офферу. Дешёвый способ за $0.24 + $0.0006 (rewrite) сразу получить материал на неделю Meta-тестов.
Pairs with
- creative-orchestrator — top-level batch pipeline (variants × aspects + QA loop)
- video-copywriter — генерит
textover_hookтексты, фидятся в--offer/--bullets/--profits - video-clipgen — управляет
references/папкой +reference_imagesтаблицей (общие refs) - creative-carousel — карусели надстроены над poster, переиспользуют brand, presets, multi-aspect, QA
🎬 Примеры работы
Место в пайплайне
Parallel к видео-пайплайну. Та же multi-project структура, та же brand library, та же
director.db. Над всем этим — creative-orchestrator для batch-пайплайна.