Skills · UGC niches
fb-creatives
/fb-creativesHow to make an N-creative FB / Meta / IG static ad pack for a real brand — generalized niche know-how, not one specific ad.
SKILL.mdTrigger
FIRES on a generic N-creative ad-pack brief: "make 32 FB creatives for <brand>", "ad pack for <site>", "set of Meta ads", "creative matrix", "8-10 static ads for IG feed", "performance creatives for our cold-traffic campaign". Any brand, any vertical — the skill is brand-agnostic.
DO NOT FIRE when:
- The brief is for ONE still (poster, drop graphic, hero image) → use
/posterinstead. - The brief is for a moving video (UGC / unboxing / talking-head) → match the matching
/ralphy-ugc-*skill. - The user points at one specific ad to reproduce (
@template:<slug>, "remix this exact ad") → that is the remix path. Seedocs/skills-vs-templates.md. - The user pasted
@guideline:<slug>for a register the pack sits in (photoreal humans, anti-AI-slop) → runralphy guideline show <slug>first and fold its rules into the A-set portrait prompts.
What this skill is
A generalized matrix overlay, not a finished ad pack. It does not name a brand, a hero, a price, or a number — it tells the art-director HOW a multi-register static ad pack is built so a strong one comes out for whatever the user is promoting. It runs through ralphy generate image; it does not bypass the reference-required gate or the site-grounding invariant.
Hard invariants
- All generation routes through
ralphy generate image(no raw API). ReadMODELS.mdbefore naming any model id — the stack below is a default, not a hardcode. - Real-brand pre-flight: site-grounding before ANY prompt. When the brief names a real brand URL, dispatch a Playwright sub-agent to crawl home +
/docs+/pricing+/features+/examplesBEFORE drafting brand-DNA. Readartifacts/refs/research.md(the sub-agent's digest), not a singleWebFetchof the home page. Every palette hex in a prompt must trace toartifacts/refs/tokens.json; every named API symbol in code-creative slots must trace to "Documented API surfaces" inresearch.md. Skipping this costsotaocr-fb-001$1.20 (wrong-palette v1 burn) + 5/32 hallucinated-Python-SDK creatives. Full discipline:docs/playbooks/site-grounding.md. --ref artifacts/refs/hero.pngon EVERY gen. Once captured, pass the live-site hero screenshot as--refon all N creatives. Brand-palette + type drift across the pack drops to near zero. Without it, each prompt re-interprets "blue CTA" slightly differently — at 32 concepts the drift compounds.- Verify SDK / API surface before any code-creative. If the C / E sets render code on screen, the named API symbol (
import foo,foo.parse()) must exist on the brand's docs. If the landing only documents curl, the ad shows curl — not an invented Python wrapper. Curl is the strictly-safe fallback for HTTP APIs. - Append-only on regen. Re-rolling a slot writes
.v2.png, never overwrites. Failed / dark-bg v1 generations stay on disk as A/B reference. - The reference-required gate still fires for named real persons / IPs in the A or D set — refuse without a ref or logged
--no-ref-consent. - The quality gate refuses, not warns — two failed
scoreImagein a row → stop and report options.
The niche, in one paragraph
An N-creative FB pack lives or dies on brand consistency across distinct registers. Ads-Manager wants 8-32 visually-distinct creatives to feed its A/B engine, but every one must read as the same brand at thumb-stop speed. The 5-set matrix gives the campaign 5 register-buckets (real people, typography, proof / data-viz, meme, niche-audience), each with 2-8 concepts inside; site-grounding + a --ref hero.png glue holds the brand together across all of them. The pack ships as numbered PNGs + a ads-copy.md (primary text / headline / description / CTA per creative) + an Ads-Manager-grouping README.md.
The 5-set creative matrix
| Set | Register | Default concepts | Model |
|---|---|---|---|
| A — real people | photoreal candid portraits / testimonials with pull-quote | 4-9 diverse personas (age / ethnicity / wardrobe / setting); each is a pull-quote card layout: photo block + slate-900 quote + blue accent + emerald supporting-stat + CTA pill | openai/gpt-5.4-image-2 |
| B — graphic / typography | wordmark posters, price-stack with strikethrough, data-viz bar chart, code-card | 4-8 visual hooks anchored on a specific number from the lander ("$0.003", "5× cheaper", "13 points more accurate") | openai/gpt-5.4-image-2 |
| C — proof / dashboard | screenshot-flavored proof shots: dashboard tile, code-card output, before-after | 4-6 receipts: "we tested all of them", "1 PDF → 1 API call → clean markdown" | openai/gpt-5.4-image-2 |
| D — meme | meme-header on a brand-tinted canvas, dunk-on-competitor, "POV: …" | 2-4; meme should ladder back to one product claim, not generic | openai/gpt-5.4-image-2 |
| E — niche audience | targeted to one persona segment (indie hacker, AI engineer, ops lead, finance ops) | 2-6 segment-specific concepts; can reuse A / B / C templates with niche copy | openai/gpt-5.4-image-2 |
The matrix scales: 8-12 starter A/B pack → 24-32 full matrix → 40+ broad-spectrum. Default mix for a 32-pack: A=9, B=8, C=7, D=4, E=4.
Site-grounding (the T1 step)
Before writing any prompt:
- Dispatch sub-agent (via
Agenttool,subagent_type: "general-purpose") to crawl home +/docs+/pricing+/features+/examples+/blog. Sub-agent returnsartifacts/refs/research.md(the digest),artifacts/refs/tokens.json(CSS hex),artifacts/refs/hero.png(Playwright screenshot), and an enumerated "Documented API surfaces" list (curl / Python / TS / GUI). - Read
artifacts/refs/research.md— never sketch brand-DNA from memory. - Write
brand-dna.mdwith REAL hex values fromartifacts/refs/tokens.json, the real type stack, the real CTA color, the real hero claims. - Lock the voice register at intake (dev-honest / marketing-punchy / mix). Anchor every prompt on a specific number from the lander.
Workflow
- Intake. Run the creative-pack branch of intake (aspect for placements: 4:5 FB feed / 1:1 IG feed / 9:16 Stories / mix; pack size; sets to cover; brand site URL — REQUIRED; voice register; hard no's).
- Site-grounding. Dispatch the Playwright sub-agent (see above). Read
artifacts/refs/research.md. Writebrand-dna.md. - Concept matrix. Draft the 5-set scaffold; pick the N concepts the user wants. Surface the matrix in chat; get explicit "go".
- Prompt scaffold. One
prompts/<slot>.txtper concept. Each cites brand-DNA hex verbatim, names a specific photographic spec (camera/lens/grain for A-set, syntax-color spec for code-cards in B/C), includes a ban-negative for known failure modes (beauty filter, plastic skin, missing strikethrough, dark background when site is light). - Generate — TRUE PARALLEL via bash
&.gpt-5.4-image-2validated for 23-concurrent (sotaocr-fb-001, 2026-05-29). NOTralphy queue— the daemon was idle on 13 jobs that session. Each gen passes--ref artifacts/refs/hero.png. - Review + iterate. Read all PNGs inline. Re-roll only mis-rendered slots (not the whole batch). Auto-versioning preserves v1.
- Deliverable.
final/with numbered prefix,ads-copy.md(primary text · headline · description · CTA × N),README.mdwith the concept-by-concept table + Ads-Manager ad-set grouping (real-people / diverse-personas / numbers / editorial-graphic / proof-dashboard / code / meme). - Hand off to
/evaluatorif the user wants a quality gate before delivery.
Default model stack (verify against MODELS.md)
- Default —
openai/gpt-5.4-image-2. Production-grade parallel (validated 23-concurrent at $0.20/img). Crisp typography (the wordmarks, price stacks, code-cards, syntax coloring). Use for all 5 sets. Aspect via--size(FB feed--size 1080x1350, IG feed--size 1080x1080, Stories--size 1080x1920). - Fallback —
google/gemini-3-pro-image-preview. Faster, cheaper, tolerates ≥4 concurrent, but smudges small embedded typography. Use ONLY for fast palette/composition exploration; finalize on gpt-image.
Failure modes
- Brand-DNA invented from memory (dark-bg + orange when site is white + blue). Cost on sotaocr-fb-001: $1.20 + 12 min. Prevention: site-grounding sub-agent +
artifacts/refs/hero.pngon T1. - Believing stale "cap=1 concurrent" memory on gpt-image → 25 min wasted on a serial loop. Prevention: 2× parallel probe before architecting any batch shape; gpt-5.4-image-2 is production-grade parallel as of 2026-05-29.
ralphy queuedaemon idle on pending jobs. Use bash&fan-out, not--queue, for ad-hoc N-image batches until the daemon is reliable.- Hallucinated SDK in code-creatives. Model auto-completes Python ergonomics from training prior even when brand only ships curl. Verify every named symbol against
artifacts/refs/research.md"Documented API surfaces"; fall back to curl when SDK unverified. - Generic "Better X for Y" copy. Cold-traffic FB copy lands when anchored on a specific lander number. Always anchor each headline on one verifiable claim from
brand-dna.md. - A-set portraits going beauty-filter editorial. Without "naturalistic, NOT glossy" + camera/lens spec + named imperfection in the body, gpt-image defaults to fashion-magazine glaze. See the A-set cookbook below.
- Missing strikethrough policy in price stack. Without an explicit anti-token, gpt-image sometimes applies the strikethrough uniformly across rows. Always state row-by-row policy + negative "strikethrough on the brand row".
Aspect ratio
--size is honored by gpt-image as of loud-kids-poster-001 (lands on nearest native bucket). Defaults:
- FB feed →
--size 1080x1350(4:5) - IG feed →
--size 1080x1080(1:1) - Stories →
--size 1080x1920(9:16) - Mix → fan out separately per placement, do not auto-crop.
Cookbook
A-set — real-people testimonial (validated on sotaocr-fb-001 A2/A6/A7/A9)
LAYOUT (top to bottom):
1. PHOTO BLOCK (52% height): Rounded 24px-radius photograph filling width with 5% margin.
CONTENTS: a photoreal candid portrait of <persona> — <2-3 specific features:
age, ethnicity, hair, wardrobe>. Natural skin texture with visible pores,
<named imperfection: mole / asymmetry / stubble>, slight facial asymmetry.
<Setting + lighting>. Sony A7 IV, Sigma 85mm at f/2.0, Kodak Portra 400 grain,
naturalistic, NOT glossy.
2. QUOTE CARD (30% height): Pure white panel, 88% width, thin border, soft shadow.
- Pull-quote slate-900 Inter Medium ~52pt, slight italic, blue <ACCENT> open-quote glyph
- Attribution slate-400 Inter Regular ~26pt
- Below, emerald #10B981 Inter SemiBold supporting stat
3. CTA + URL FOOTER (18%): Blue <ACCENT> pill + slate-400 sub-line.
Negative: dark background, orange accent, plastic skin, beauty filter, AI fingers,
perfect teeth, frozen expression, fashion-editorial pose.
Key tokens: "naturalistic, NOT glossy" + camera + lens + grain spec + named imperfection in the body.
B-set — price-stack with strikethrough (validated on B4/B8)
PRICE STACK (50% height): Four large rows stacked vertically with generous spacing.
Each row: vendor name (left, slate-900 Inter Medium ~36pt), large price
(right, Inter Black ~64pt). Vendors with strikethrough have a 4px red #DC2626
line running cleanly through the ENTIRE row (label + price) horizontally at
vertical center. The <BRAND> row has NO strikethrough and uses emerald #10B981
for the price.
Row 1: "<Competitor 1>" — "<price>" (with red strikethrough through both)
...
Row 4: "<BRAND>" — "<price>" (NO strikethrough, emerald price, small "←" arrow)
Negative: strikethrough on the <BRAND> row, missing strikethrough on the
competitor rows, broken/wavy/dashed strikethrough lines.
Key tokens: explicit row-by-row spec + explicit anti-token "strikethrough on the BRAND row".
B / C / E — code-card (validated on B3/C7/E3)
CODE CARD: A floating window-chrome card centered, ~88% canvas width, 25px corner
radius, soft drop shadow. macOS-style window-chrome header with three small
circles (red/amber/emerald), centered title "<file>.py" in JetBrains Mono.
Card body deep navy #0F172A background. Inside, 3-4 lines of crisp monospace
code (JetBrains Mono ~30pt) with line numbers in muted #475569.
Syntax: keywords blue #60A5FA, strings emerald #34D399, comments slate-400 #94A3B8,
variables cream #F1F5F9.
Line 1 (comment): # <one-line value claim>
Line 2: <curl OR import — must match the brand's documented surface>
...
Key tokens: macOS chrome description verbatim + explicit syntax-color-per-token mapping + line numbers gutter spec. Verify the named API surface against artifacts/refs/research.md.
C-set — horizontal bar chart (validated on B2)
HORIZONTAL BAR CHART: Four horizontal bars stacked vertically.
Each row has three columns:
- LEFT: brand label, slate-900 Inter Medium ~32pt, left-aligned
- MIDDLE: bar — rounded ends, height ~64px, track #F3F4F6, fill in row color
- RIGHT: percentage, large Inter Bold ~48pt, right-aligned
Rows (top to bottom):
- "<BRAND>" · bar filled emerald #10B981, length 95% · "95%" in emerald
- "<Competitor>" · bar filled slate-400 #9CA3AF, length 82% · "82%" in slate-400
...
Key tokens: explicit three-column spec per row + named track + fill colors + named bar length as % of canvas.
CLI cookbook
# Site-grounding sub-agent (dispatched via Agent tool — see site-grounding.md
# for the full prompt template). Output lands at artifacts/refs/research.md + artifacts/refs/hero.png.
# Per-creative generation — TRUE parallel via bash & fan-out
for slot in a1 a2 a3 b1 b2 b3 c1 c2 c3 d1 d2 e1 e2; do
ralphy generate image --project <id> --slot "$slot" \
--model openai/gpt-5.4-image-2 --size 1080x1350 \
--ref artifacts/refs/hero.png \
--prompt "$(cat prompts/$slot.txt)" &
done
wait
# Re-roll a single mis-rendered slot (writes .v2.png — append-only)
ralphy generate image --project <id> --slot a5 \
--model openai/gpt-5.4-image-2 --size 1080x1350 \
--ref artifacts/refs/hero.png \
--prompt "$(cat prompts/a5.txt)"
# Quality gate
ralphy project score <id> --strict
At ~$0.20/creative on gpt-image, a 32-pack ≈ $6.40 / ~25 min (with site-grounding done first); the sotaocr-fb-001 reference ran $8.00 / ~30 min because of the wrong-palette v1 burn.
See also
docs/skills-vs-templates.md— why this is a skill and not a template.docs/playbooks/site-grounding.md— the Playwright sub-agent prompt template (mandatory T1 step).docs/playbooks/intake.md— the creative-pack branch of intake.docs/playbooks/art-director.md— model picks + ref-anchor flow.MEMORY.md— anti-ai-slop image prompts, OR parallel gpt-image OK, verify SDK before code-creative, site-grounding before brand-DNA.- Reference postmortem:
.ralphy/workspaces/<ws>/projects/sotaocr-fb-001/postmortem/— the lessons + matrix this skill codifies.
