[ CREATIVE ]
/design
Design ad creatives and social visuals matched to a client's OWN brand/website, using a library of named Layouts (e.g.
ACME Agency, <id> and you@example.com mark values that are per-agency — your install fills them with YOUR clients and accounts. If a section references a helper script you don't have yet, it ships with that workflow's install./design — the Layout design system
Produces finished ad creatives / social visuals on a client's own brand, drawn from a Layout library (named, reusable design systems). It is the exact-photo engine: the client's real photo is composited with real typography and the type is placed by a content-aware engine — so the result uses ONLY their photos and looks like their site, not a generic AI generator. (Formerly "edna-design".)
Render paths:
- EXACT-PHOTO (default, the Layouts): the client's real photo is a full-bleed
<img>
and the typography is real text composited over it via headless Chromium — the photo is NEVER sent to a model. [lib/design_layout.mjs](../../../ACME Agency/scripts/lib/design_layout.mjs) reads each photo and places the headline/CTA on the calm band away from the subject, in the right color, with an overlay only where needed. Pick a Layout (e.g. first-layout).
- GENERATIVE (fallback): when no usable real photo exists, nano-banana (Krea) generates
the full creative and the client's real logo is composited on top in code (the model never draws logos — it hallucinates them).
Decision: client has real photos / "use their gallery / match their site" → exact-photo Layout. No usable photo → generative.
This is the visual sibling of /campaign-deck (which writes copy decks in the house deck voice). Same shape: the designer agent makes the design judgment (which Layout, which photos, the on-image copy), a deterministic script (design_generate.mjs) renders + ships it.
Layout library
| Layout | id | What it is |
|---|---|---|
| First Layout | first-layout | Quiet-luxury editorial matched to a client's live site — Playfair serif headline (roman + italic), gold/eyebrow caps labels, ghost-outline LABEL → CTA, cream/navy/photo backgrounds. Best for premium brands with a real website. |
(More Layouts get appended here as we add them. Older single-purpose templates — photo-hero, photo-caption, realestate-spec, event-poster, brand-panel — still exist for their niches.)
When to trigger
- "design for <client>" / "napravi vizual(e) za <klijent>" / "match their site"
- "make a static / creative / social visual for <client>"
- "use THIS exact photo for the ad" / "koristi baš ovu sliku" (→ mode
photo) - "use their gallery photos" / "designs that match their website" (→ a Layout, exact-photo)
- "new client, build the brand look + first designs" (→ mode
new) - "make new designs from <client>'s old ones" (→ mode
clone) - "/design <Client> …"
- NOT for: video ads (cinematic/heygen/motion/video-edit), copy decks (
/campaign-deck,
/copywrite), landing pages (/landing), or batch 40-ad runs where brand fidelity doesn't matter (/static-ad-generator). Prefer this skill whenever the bar is "must look like our designer made it" or "must use the client's exact photo".
Phase 0 — Parse inputs & pick the mode
Extract client (required; if missing, ask once), --mode, --brief, --photo (local path or Drive id), --ref (Drive folder of past designs), --sizes (default 4:5), --lang.
Auto-detect the mode if not given:
- A real photo provided / referenced ("use this photo") → photo.
- Client has past a teammate designs in Drive and the ask is "more like those" → clone.
- Client has no
design-theme.jsonand no design history → new.
Resolve the client via the 3-step cascade (ACME Agency/CLAUDE.md): clients.json → Sheet registry → API discovery. Load CLIENT.md, brand-dna.md, design-theme.json if present.
Phase 1 — Mode-specific context
Mode new (no assets yet)
- Resolve the brand: client logo (Drive/local via
ensureClientLogo, view it with
vision), website (Firecrawl), any questionnaire in the client folder.
- Write
ACME Agency/clients/<Client>/brand-dna.md(voice, audience, colors,
adjectives) if it doesn't exist.
- Write
ACME Agency/clients/<Client>/design-theme.json:
{ brand, accent, accent2, ink, paper, onPhoto, logo, fontDisplay, fontSans, fontsHref }. Verify colors + font from the real source (the site's CSS via Firecrawl/curl + the logo pixels) — never eyeball or invent. The logo: if the supplied file has a baked-in background (unusable for overlay), build a clean code-rendered badge (see the ACME Agency example: an SVG/HTML→PNG of the mark in the real font + colors) and point logo at it. Ask the client for a transparent vector logo.
Mode clone (reuse her past work)
- Find the client's recent designs in Drive (
--reffolder, or search the client
folder / owner you@example.com). Download the best 2–4 and view them (vision).
- Extract the theme (colors, accent usage, fonts feel, recurring layout) → write/
update design-theme.json.
- These designs are also the style reference for generation — note their look so the
agent's scene prompts match her established direction.
Mode photo (exact client photo → HTML render)
- Get the photo(s):
--photolocal path, or a Drive id (download), or a folder. - The photo is used UNCHANGED via
render:"html"+photo:{type:"local"|"drive",…}.
Never route a must-be-exact photo through generation.
Phase 2 — Delegate design judgment to the designer agent
Invoke the designer subagent (Task tool). Pass: the client, the mode, the brief/copy, the resolved theme path, photo source(s), --sizes, --lang, and reference_files = STYLE_GUIDE.md + design.tests.md + the client's CLIENT.md/brand-dna/ design-theme.json. The agent:
- chooses the render mode per concept —
generativeby default (ascene+ the
copy), html only for a must-be-exact client photo,
- writes the on-image copy in a teammate's register (accent word, ≤3 checks, one CTA),
- writes the design spec to
ACME Agency/clients/<Client>/design_spec_<date>.json
and returns its path + a one-line summary per concept.
Do not hand-author the spec yourself — let the agent design. (See the agent file for the spec contract; templates self-document their fields in .claude/skills/design/templates/.)
Phase 3 — Render
node ACME Agency/scripts/design_generate.mjs \
--client "<Client>" --specs ACME Agency/clients/<Client>/design_spec_<date>.json \
--no-upload --no-slack
Renders each concept × size to ACME Agency/clients/<Client>/designs/<date>/. (--list-templates shows valid template ids.) The photo is composited exactly; HR/BS diacritics render perfectly because the type is real text.
Phase 4 — Grade & iterate (quality gate)
Re-invoke designer on the rendered PNGs to grade against design.tests.md (vision). For any concept < 8/10, apply its revised spec and re-render that concept. Loop until all ≥ 8 or you've done 3 passes (then flag the gap — never silently ship off-style).
Phase 5 — Upload & deliver
Re-run Phase 3 WITHOUT --no-upload --no-slack (or once, after grading passes):
node ACME Agency/scripts/design_generate.mjs \
--client "<Client>" --specs <spec.json>
This uploads the finals to the client's Drive (<ClientFolder>/Designs/<date>/) and posts to the client Slack channel. For a richer Slack post, route the summary through the slack-reporter agent. Always output the Drive folder link to the user.
Verification
- [ ] Render mode right per concept —
generativedefault;htmlonly for a must-be-exact client photo - [ ]
design-theme.jsonexists with verified brand colors + font (from site CSS + logo pixels, not eyeballed) - [ ] Logo present + correct on every creative (composited PNG; never model-drawn). Transparent vector logo requested if missing
- [ ] On-image copy correct verbatim; HR/BS diacritics intact; one CTA per creative
- [ ] No gibberish text (don't put real copy in fake in-app screenshots)
- [ ] Grading pass run; every shipped concept ≥ 8/10 (or gap flagged loudly)
- [ ] Finals uploaded to
<ClientFolder>/Designs/<date>/; Drive link surfaced - [ ] Slack posted to the client channel
Key files
| File | Purpose |
|---|---|
.claude/skills/design/STYLE_GUIDE.md | the design system's visual grammar + the generative prompt recipe |
.claude/skills/design/design.tests.md | "Does it match the brand/Layout?" self-test |
.claude/skills/design/templates/ | HTML/CSS templates (exact-photo path) + _base.css + _kit.mjs |
.claude/skills/design/templates/photo_caption.mjs | a teammate's travel/charter caption template (exact photo) — title-case rounded headline w/ bold emphasis, italic subhead, underline rule, >> chevron, top-dark-over-sky OR bottom-white layouts. Use when output must match her Fjord/boat set on the client's own gallery photo. |
.claude/skills/design/templates/first_layout.mjs | First Layout (id first-layout, alias lux-editorial) — quiet-luxury editorial template matched to a client's live SITE (Playfair serif headline roman+*italic*, gold eyebrow, Inter caps labels, ghost-outline LABEL → CTA, cream/navy/photo backgrounds). Supports tone light/dark text + auto directional scrims + center plate. Built for fjord41xl.com. The first entry in the named Layout library. |
ACME Agency/scripts/lib/design_layout.mjs | Content-aware placement — reads the photo, finds the calm band away from the subject (bright hull/wake + edge detection), returns {anchor, tone, plate}. Used when a concept sets place:"auto"; explicit spec values still win. |
.claude/skills/design/fonts/ | bundled brand fonts (per client) — see README |
.claude/agents/designer.md | The persona agent (design judgment + grading) |
ACME Agency/scripts/design_generate.mjs | Renderer/uploader (generative + html) |
ACME Agency/scripts/lib/design_prompt.mjs | Builds the nano-banana prompt from copy + brand |
ACME Agency/scripts/lib/design_logo.mjs | Composites the real logo onto generated creatives |
ACME Agency/scripts/lib/design_render.mjs | HTML→PNG engine (exact-photo path) |
ACME Agency/clients/<Client>/design-theme.json | Per-client brand theme (colors/fonts/logo) |
Notes
- Generative-first. nano-banana renders the full creative (text included — it
handles Croatian diacritics well); the real logo is always composited in code (models hallucinate logos). The pure-HTML brand-panels and the hybrid (generate scene → composite text) lost on quality in testing; generative is the default.
- The exact photo is sacred. A client photo that must stay unchanged uses
render:"html" and is NEVER sent through a model.
- Don't trust generated micro-text (fake app screenshots) — keep real copy in the
headline/checklist/CTA, which the model renders reliably.
- Verify brand truth. Colors + font come from the site CSS + logo, not a guess.
- Diacritics + emojis + given copy are sacred (
ACME Agency/CLAUDE.mdMeta rules).