Skip to content
Machine Learning
Skill

/listing-media

Author and generate Civitai App store listing MEDIA — icons, covers and titled banners — through the measured author→light→normalise pipeline, and attach them (including for offsite apps, which the CLI refuses). Use when the user asks to brand a new app, re-do or improve an

BOOST
From plugin
civitai
7.3k48 skills15 agents3 commands
Install
$ npx -y skills add civitai/civitai --skill listing-media --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/listing-media

Context preview

The summary Claude sees to decide when to auto-load this skill.

Author and generate Civitai App store listing MEDIA — icons, covers and titled banners — through the measured author→light→normalise pipeline, and attach them (including for offsite apps, which the CLI refuses). Use when the user asks to brand a new app, re-do or improve an

SKILL.md

listing-media.SKILL.md
name: listing-media
description: Author and generate Civitai App store listing MEDIA — icons, covers and titled banners — through the measured author→light→normalise pipeline, and attach them (including for offsite apps, which the CLI refuses). Use when the user asks to brand a new app, re-do or improve an app's icon / cover / banner, extend the brand system to more apps, judge listing-media quality, or asks why generated store art looks wrong. Screenshots of a RUNNING app are the sibling `app-capture` skill.
argument-hint: "[brand <slug> | icon <slug> | cover <slug> | attach <slug> | audit]"
allowed-tools: Bash, Read, Edit, Write, Glob, Grep

listing-media — authoring store icons, covers and banners

**This skill owns AUTHORING. `app-capture` owns capture + attach.** The split:

| | this skill | `app-capture` | |---|---|---| | generate an icon / cover / banner | ✅ | ✗ | | screenshot a running app | ✗ | ✅ | | attach to a listing, bounds-gated | defer to it | ✅ `.claude/skills/app-capture/scripts/attach.sh` | | attach for an **offsite** app | ✅ (the CLI refuses) | ✗ |

🔴 **Never hand-roll an attach.** `attach.sh` is dry-run by default, gates every asset against `.claude/skills/app-capture/scripts/store-bounds.json`, and already knows the shadow-revision and re-keyed-id traps. Two attach paths would drift.

🔴 Read first — four things that void the text below

1. **Bounds live in `store-bounds.json`, never here.** Aspect/size/px limits move. 2. **A hue table here is a snapshot.** Read the live values from `brand-assets-rev5-2026-08-13/scripts/emit-svg.py` (private infra repo). 3. **"Live" claims decay.** Every asset below was submitted, and a submission is not a listing — see *Nothing ships on push*. 4. **The cover grammar CHANGED on 2026-08-17** from untitled analogy photographs to titled banners. If you find an untitled cover, it predates that decision.

The two icon grammars

| | plate | mark | |---|---|---| | **onsite** apps | brand hue | light tint | | **offsite** apps | **graphite `#24262B`** | brand hue |

🔴 **The onsite hue wheel is FULL and this is why the offsite grammar exists.** Seven hues at ≥42° separation already consume 294° of 360°; nine needs 378° and eleven needs 462°, and there are four offsite apps. Squeezing two into the widest gaps caps minimum separation at 28.5° and hits the wall again at four. Putting a neutral plate behind a hue mark makes hue **non-scarce** for that family instead. Do not "simplify" the two grammars into one.

The pipeline — author, light, normalise

Generation cannot meet the icon spec and authoring cannot do lighting. Each half is used only for what it is good at:

| | authored flat | generated | |---|---|---| | meaning | **exact** | unreliable — 3 of 7 motifs wrong after two prompt rounds | | colour | **impossible** — flat fills 0/20, exact hex 1/10, alpha 0/20 | **exact** after normalisation |

1. **Author** the mark flat — `.claude/skills/listing-media/scripts/author-marks.py`. Zero Buzz. Exact geometry, exact hex. This is where motifs are chosen and rejected. 2. **Light** it with img2img, which preserves composition: `--ecosystem NanoBanana --checkpoint 2725610 --image <authored.png> --aspect-ratio 1:1` (covers `16:9`). ~208 Buzz at `--quantity 2`. 3. **Normalise** the plate — `.claude/skills/listing-media/scripts/finish-icons.py`. Applies a per-channel gain ONLY where saturation is low, so the plate lands without dulling the mark.

🔴 **`finish-icons.py` runs BOTH mask controls and aborts if either fails** — an on-target neutral must survive (plate branch) and a pure mark colour must pass through unchanged (mark branch). One control proves half a mask. Measured 2026-08-16: both dE 0.000, which is what makes the per-candidate numbers readings.

**Gate**: plate dE ≤3.0, mark hue ≤8°, mark saturation kept ≥95%, aspect 0.9–1.1.

🔴 **Always `--quantity 2` and read BOTH.** Composition drift is the known img2img failure and it is not rare: one comfy candidate invented a backing panel and turned round sockets into squares, scoring 12.45° hue / 232.7% saturation while its sibling passed. The gate caught it independently of the eye. One render is a coin flip.

Motifs — judge at 320px, by what a stranger says it depicts

Authoring is free, so draw every candidate and rule on it BEFORE any Buzz moves. Judge at **320 px**, the size the store serves an icon at, not at 1024.

🔴 **Escaping one wrong prior does not mean you landed on the right one.** The catalogue of priors that have actually bitten, all of them plausible on paper:

| motif | what it actually read as | |---|---| | dial with ticks OUTSIDE the ring | a **sun** (the "outward triangles + warm dot" prior) | | the same dial with ticks INSIDE | a **clock** — the fix created a new wrong prior | | ON AIR sign without text | a card, or a text input | | a restyle of the placeholder's own motif | the placeholder |

**Generation is good at real-world objects and bad at abstract constructions** — "a disc with a wedge cut out" came back a cone twice. That is the test for whether a motif is promptable at all; an authored mark has no such limit.

Covers — titled banners (current grammar)

Left: title on ONE line, tagline beneath. Right: product imagery. Dark ground with the app's brand hue as a gradient glow. The literal prompt template and every per-app scene string: `.claude/skills/listing-media/reference/prompt-library.md`.

Copy comes from the LIVE `/api/v1/apps` name + tagline. 🔴 **Check both before writing them into a prompt** — one app's tagline is `null`, another's stored name is a name and a descriptor jammed together, and a third contains a `°` that generation mangles.

🔴 The failure class is text VOLUME, not text

NanoBanana renders a headline reliably and a field of small labels not at all. Measured across one suite:

| scene shape | outcome | |---|---| | no text in the scene | clean every time | | a few row/column labels | mostly right,

Read more
Ships withcivitai

A repository of models, textual inversions, and more

Get the whole plugin

Other skills on civitai.