Brand logo kit
Generate a brand logo and a matching, brand-consistent set of visual assets - logo marks, wordmark lockups, monograms, app icons, favicons, social avatars, banners, seamless patterns, spot illustrations, and UI icons. Local-first: it prefers on-device generation via the image-gen skill (FLUX.2 Klein on Apple Silicon) and only falls back to a CLOUD image API (Google Gemini / Nano Banana Pro, or OpenRouter) when local can't run - no API key is bundled, it is auto-discovered from your environment or another installed skill and cached outside the repo. Crisp on-brand text is set from real fonts with wordmark.py (no misspelled diffusion text), `--look` presets steer the visual finish, and a set is kept cohesive via a shared palette and, on the cloud path, the chosen logo as a reference. Use when the user asks to create a logo, brand identity, brand kit, visual identity, brand style, wordmark, app icon, favicon, or a consistent set of on-brand graphics/assets.From its SKILL.md
npx -y skills add puntorigen/skills --skill brand-logo-kitAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
17.4 KB, ~4.7k tokens by cl100k_base, as published. Nobody here has run it
Brand Logo Kit
Generate a logo and a brand-consistent style — a cohesive set of assets that share the logo's shapes, palette, and feel — with Gemini image models. You (the model) shape the brief, generate a few logo candidates, let the user pick, derive a palette, then produce every downstream asset from that winner so the set stays on-brand.
flowchart LR
Brief["brief: name, industry, vibe, colors"] --> Logo["generate.py --style logo<br/>--look modern --count 4 --transparent"]
Logo --> Pick["user picks the winner"]
Pick --> Pal["extract_palette.py<br/>-> brand.json"]
Pick --> Ref{{"logo.png as --ref {image1} (cloud)"}}
Pick --> WM["wordmark.py --text Name<br/>--font Futura --mark logo.png<br/>-> real-font lockup"]
Pal --> Assets["generate.py --style app-icon /<br/>brand-illustration / pattern / banner"]
Ref --> Assets
Local-first, with a cloud fallback. This repo is local-first, so by default each generation runs on-device via the
image-genskill (FLUX.2 Klein, MLX) — no key, no cloud. Local is chosen automatically when it can realistically run: an Apple Silicon Mac withimage-genset up, and either the weights already downloaded or enough free disk to fetch them (~12 GB, one time). When local isn't usable, it falls back to a cloud API (Google Gemini / OpenRouter's Nano Banana Pro) — best quality, reference-based consistency, SynthID-watermarked. SetBRAND_LOGO_KIT_PREFER=cloudto try a key first. No key is ever stored in the repo.Two things make logos look intentional rather than generic:
--lookpresets nudge the finish (e.g.modern,gradient,glow,flow,minimal), andwordmark.pysets the brand name in a real high-quality font (Futura, Avenir Next, Gill Sans, DIN…) instead of relying on the model to draw text — so wordmarks are crisp, correctly spelled, and deterministic.
Prerequisites
- Python 3.9+ (any OS).
uvis used if present for a faster install, otherwise the stdlibvenv+pipare used. - Dependencies installed by setup into a local venv: google-genai, Pillow, numpy, requests.
- For the preferred local path: an Apple Silicon Mac and the local
image-genskill set up (bash ../image-gen/scripts/setup_env.sh). The first local render downloads the FLUX.2 Klein weights (~12 GB free needed, one time). If disk is tight, either free space or provide a key. - For the cloud fallback: a Gemini or OpenRouter API key — you usually don't set one up, it is auto-discovered (see providers).
- For
wordmark.py: real fonts already on the machine (macOS ships Futura, Avenir Next, Gill Sans, DIN, Optima, Didot…). No extra install;--list-fontsshows what's available, or pass any.ttf/.otfpath.
Setup
Resolve the skill directory and run setup once. It creates a self-contained
venv at ~/.brand-logo-kit/.venv, installs the deps, and prints the venv python
on its last line:
SKILL_DIR="<the folder this SKILL.md lives in>" # e.g. .cursor/skills/brand-logo-kit
bash "$SKILL_DIR/scripts/setup_env.sh"
Then set the two handles every command below uses (setup prints PY too):
PY="$HOME/.brand-logo-kit/.venv/bin/python"
SC="$SKILL_DIR/scripts"
See which provider will be used (prints a masked summary; caches any key it finds):
"$PY" "$SC/resolve_key.py" # resolve provider (local-first)
"$PY" "$SC/resolve_key.py" --status # local diagnostics: disk, weights, usability
The venv and any cached key live outside the repo under ~/.brand-logo-kit/
so nothing sensitive is committed.
Providers & key auto-discovery
Because the repo is local-first, resolve_key.py (and every generate call)
picks a provider in this order:
- Local (preferred) — the on-device
image-genskill (FLUX.2 Klein / MLX) is chosen whenever it is usable: Apple Silicon +image-genset up, and either the weights are already downloaded or there's enough free disk (~12 GB) to fetch them. No key, no cloud. - A cloud key — used when local isn't usable. Discovered from, and the first
hit cached to
~/.brand-logo-kit/config.json:- the cached config from a previous run
- env vars — Google:
GEMINI_API_KEY,GOOGLE_API_KEY,GOOGLE_GENAI_API_KEY,GOOGLE_AI_API_KEY; OpenRouter:OPENROUTER_API_KEY config.jsonof other installed skills (e.g.asset-generator) under~/.cursor/skills,~/.claude/skills,~/.config/skills
- Local (last resort) — if no key is found but
image-genis installed, local is used even with low disk (the run may fail mid-download).
The provider is inferred from a key's prefix (AIza… → Google, sk-or-… →
OpenRouter). Env knobs:
export BRAND_LOGO_KIT_PREFER=cloud # try a key BEFORE local
export BRAND_LOGO_KIT_MIN_DISK_GB=8 # lower the free-disk bar for auto-local
export GEMINI_API_KEY=AIza... # Google AI Studio
export OPENROUTER_API_KEY=sk-or-... # OpenRouter (Nano Banana Pro)
"$PY" "$SC/resolve_key.py" --set <KEY> # cache a key manually
Force a provider on any command with --provider google|openrouter|local.
Local path (default): trade-offs
The local model (default FLUX.2 Klein; --model z-image-turbo also works) is
text-to-image only, so vs the cloud path:
- No reference images —
--refis ignored. Keep a set on-brand by repeating the palette hexes and identical style wording /--lookin every prompt (seebrand.json'sprompt_snippet). - Don't let the model draw the brand name — diffusion text is mushy and often
misspelled. Generate the symbol here, then set the wordmark with
wordmark.py(real font) and combine them into a lockup. See Step 6. - Best for symbol marks / icons / patterns / illustrations.
- The default
--lookfor local ismodern(gradient + soft glow + flowing curves), which tests far better than the old plain/abstract output. Override with--look(e.g.minimal,geometric,badge). - Transparent cutout still works (renders on a flat chroma background, then keys it).
Workflow
Copy this checklist and track progress:
- [ ] 1. Capture the brief: name, industry, personality, color hints, mark vs wordmark
- [ ] 2. Setup: run setup_env.sh (first time) + resolve_key.py (see the provider)
- [ ] 3. Generate 3-4 logo candidates (pick a --look); show them; let the user pick
- [ ] 4. Regenerate the winner at higher resolution + clean transparent cutout
- [ ] 5. Extract the brand palette -> brand.json
- [ ] 6. Set the wordmark/lockup with wordmark.py (real font) from the winner
- [ ] 7. Generate the brand-consistent asset set (palette + look; --ref on cloud)
- [ ] 8. Export platform sizes (favicon / app icon) and deliver
Step 1: Nail the brief
Pull these from the user (or infer and state your choices): brand name, industry, personality (e.g. "calm, premium, minimal"), any color preferences, and whether they want a symbol, a wordmark, or both. Fold them into the prompt text.
Step 3: Logo candidates
Generate several transparent marks so the user can choose. Describe a concrete,
recognizable symbol (not "an abstract mark") and pick a --look for the
finish — modern, gradient, glow, flow, minimal, geometric, badge,
line, 3d… (--list-looks). Local defaults to modern; cloud defaults to none.
"$PY" "$SC/generate.py" \
"a mark for 'Northwind', a calm premium sailing club: a stylized wind-and-wave symbol, deep navy" \
--style logo --look modern --transparent --count 4 -o out/northwind_logo.png
Show the candidates inline (read the PNGs) and let the user pick. If results feel
generic/abstract, name the symbol more concretely and/or try a different --look.
Step 4: Winner + cleanup
Regenerate the chosen direction at high resolution:
"$PY" "$SC/generate.py" "<the winning description>" \
--style logo --transparent -r 2K -o out/logo.png
Step 5: Brand palette
Derive a reusable palette from the chosen logo:
"$PY" "$SC/extract_palette.py" out/logo.png --name "Northwind" -o out/brand.json
brand.json holds the palette, role colors (primary / accent / ink / paper), and a
ready prompt_snippet to paste into later prompts for consistency.
Step 6: Wordmark & lockup (real fonts)
Set the brand name with wordmark.py, which renders genuine fonts (crisp,
correctly spelled, transparent) — never rely on the image model to draw the name,
especially on the local path. Optionally combine it with the winning symbol into a
lockup:
# Wordmark only, in the brand ink color from brand.json, airy uppercase tracking:
"$PY" "$SC/wordmark.py" --text "Northwind" --font Futura --case upper \
--tracking 0.12 --brand out/brand.json -o out/wordmark.png
# Horizontal lockup: the symbol on the left, the name on the right:
"$PY" "$SC/wordmark.py" --text "Northwind" --font "Avenir Next" \
--mark out/logo.png --layout horizontal --color "#0B2A4A" -o out/lockup.png
--list-fonts shows curated fonts on this machine; --font also accepts any family
substring or a .ttf/.otf path. Key options: --case upper|lower|title,
--tracking <em>, --layout horizontal|vertical, --mark-scale, --gap, --bg.
Step 7: Brand-consistent assets
Mention the palette (and keep the same --look) so every asset inherits the
logo's DNA. On the cloud path also pass the logo as a reference (--ref,
referenced as {image1}); on the local path drop --ref and lean on the palette
- look wording:
# App icon from the mark (cloud: reference the logo)
"$PY" "$SC/generate.py" "app icon using the mark {image1} on a deep navy background" \
--ref out/logo.png --style app-icon -o out/app_icon.png
# On-brand spot illustration matching the logo
"$PY" "$SC/generate.py" "a sailboat spot illustration in the same style and palette as {image1}" \
--ref out/logo.png --style brand-illustration -o out/illus_boat.png
# Seamless pattern + a social banner with room for a headline
"$PY" "$SC/generate.py" "seamless pattern from simplified motifs of {image1}, navy on off-white" \
--ref out/logo.png --style brand-pattern -o out/pattern.png
"$PY" "$SC/generate.py" "brand banner in the style of {image1}, wind-and-wave motif, space for a headline on the left" \
--ref out/logo.png --style brand-banner -ar 16:9 -o out/banner.png
For a consistent icon set or illustration set, reuse the same reference,
palette, --look, and identical style wording across every call.
Step 8: Export sizes + deliver
Export square sizes for favicons / app icons in one call, then embed/link the files:
"$PY" "$SC/generate.py" "app icon using the mark {image1} on deep navy" --ref out/logo.png \
--style app-icon -o out/app_icon.png --sizes 16,32,180,512,1024
Style presets
| Preset | Best for | Ratio | Transparent |
|---|---|---|---|
logo | Primary symbol mark | 1:1 | Recommended |
logo-wordmark | Brand name lockup | 3:2 | Recommended |
monogram | Initials lettermark | 1:1 | Recommended |
app-icon | Rounded app icon | 1:1 | No |
favicon | 16px-legible mark | 1:1 | Recommended |
social-avatar | Circular profile pic | 1:1 | No |
brand-illustration | On-brand spot illustration | 1:1 | No |
brand-pattern | Seamless background pattern | 1:1 | No |
brand-banner | Social/hero banner | 16:9 | No |
brand-photo | On-brand photography | 16:9 | No |
brand-icon | UI icon in brand style | 1:1 | Recommended |
List them any time: "$PY" "$SC/generate.py" --list-styles.
Looks (visual finish)
A --look appends a consistent finish to any style — steer designs away from
generic/abstract without hand-tuning the prompt. --list-looks prints them all:
| Look | Effect |
|---|---|
auto | Default — modern for local, none for cloud |
modern | Gradient + soft glow + flowing curves (premium tech feel) |
minimal | Flat, restrained, lots of negative space |
geometric | Precise grid construction, symmetry |
gradient / glow / flow | Individual modern finishes |
line | Clean monoline art |
badge | Vintage emblem/crest |
3d / mesh / duotone / corporate | Depth / colorful mesh / two-tone / corporate |
Keep the same look across a set for cohesion.
Key options (generate.py)
| Option | Short | Purpose |
|---|---|---|
--style STYLE | -s | Brand preset (default logo) |
--look LOOK | -l | Visual finish (default auto); --list-looks |
--transparent | -t | Transparent-background PNG (chroma-key cutout) |
--ref PATH | Reference image (repeatable, cloud only). Use {image1}..{imageN} | |
--count N | -n | Number of variations (1-4) |
--aspect-ratio AR | -ar | 1:1, 3:2, 2:3, 16:9, 9:16, 4:3, 3:4, 4:5, 5:4, 21:9 |
--resolution RES | -r | 1K (default), 2K, 4K |
--format FMT | -f | png (default), webp, jpeg |
--sizes LIST | Also export square sizes, e.g. 16,32,180,512 | |
--provider P | Force local (on-device, no key), google, or openrouter | |
--model NAME | Override the model (local: flux2-klein-4b or z-image-turbo) | |
--output PATH | -o | Output file path |
Key options (wordmark.py)
Deterministic real-font wordmark/lockup composer — use it for all brand text.
| Option | Purpose |
|---|---|
--text STR (-T) | The name/text to set (required) |
--font SPEC | Family name, substring, or .ttf/.otf path; --list-fonts |
--color HEX / --brand brand.json | Ink color, or pull it from a brand.json role (--color-role) |
--case | upper / lower / title / as-is |
--tracking EM | Letter-spacing in em (e.g. 0.15) |
--mark PATH | Symbol image to build a lockup with |
--layout | horizontal (default) or vertical |
--mark-scale / --gap | Mark height vs text, and spacing (em) in a lockup |
--bg HEX / --padding N | Background fill (default transparent) / px padding |
--output PATH (-o) | Output PNG path |
Consistency tips
- Set all brand text with
wordmark.py(one chosen font) — never let the image model draw the name. - Repeat the palette (from
brand.json'sprompt_snippet) and keep the same--lookin every prompt across a set. - On the cloud path, reference the winning logo (
--ref logo.png+{image1}) so shapes and construction carry over. On the local path (text-to-image) drop--refand lean harder on palette + look + identical style wording. - Generate a set with
--countand pick the most on-brand result.
Safety
- Disclose AI-generated imagery where the platform or context calls for it; cloud Gemini outputs carry an invisible SynthID watermark (local ones don't).
- Trademark check the final logo before commercial use — a generator can coincidentally reproduce an existing mark. Verify originality and don't imitate a known brand's identity.
- The local path is fully offline. On the cloud path your prompts and reference images are sent to the API provider (Google or OpenRouter) — don't include anything confidential you wouldn't upload.
- The API key never enters the repo — it is cached under
~/.brand-logo-kit/, which is git-ignored.wordmark.pyruns entirely locally.
Anti-patterns
- Letting the image model draw the brand name — diffusion text is mushy and
misspells; set it with
wordmark.py(real font) instead. - Prompting for "an abstract mark" and expecting a strong logo — name a concrete
symbol and pick a
--look; abstract wording yields generic blobs. - Shipping the first logo take — generate
--count 3-4and let the user choose. - Generating each brand asset with a different look/palette — keep them
identical so the set stays cohesive (and
--refthe winner on the cloud path). - Baking a key into
config.jsonin the repo — it belongs in the env or the git-ignored~/.brand-logo-kit/config.jsoncache. - Rendering tiny favicons directly from a detailed mark — use the
faviconstyle (radically simplified) or--sizesto downscale a clean master.
Resources
- Provider details, model slugs, key-resolution internals, prompt formula, and troubleshooting: REFERENCE.md
What ships with it: 9 files
89.0 KB alongside SKILL.md, 6 of them executable
scripts/
- extract_palette.pyruns4.0 KB
- generate.pyruns28.5 KB
- keylib.pyruns12.4 KB
- looks.json1.2 KB
- resolve_key.pyruns4.3 KB
- setup_env.shruns3.5 KB
- styles.json7.6 KB
- wordmark.pyruns12.6 KB
- REFERENCE.md14.8 KB