/use-brand — turn a brand kit into any deliverable
The back end of the pipeline: brand → anything. Given a finished kit under brand/<id>/ (produced by
/make-brand) and a request, this skill renders the deliverable in the brand's own palette, type, logos,
backgrounds, signature devices, and voice — a website, a deck, a PDF, social/OG cards, marketing copy, dev
tokens, or a video brief. The kit is the single source of truth; nothing here re-decides the brand.
$SKILL_DIR = this skill's directory. Deterministic work runs through bundled scripts in
$SKILL_DIR/scripts/; the template library lives in $SKILL_DIR/assets/ (web · social · deck · pdf · copy +
the shared _brand.mjs loader and _bake.mjs rasteriser). The skill is self-contained — it reads the
kit's vendored assets and its own bundled templates, never the network at render, never a reference kit.
Inputs
- A kit —
brand/<id>/(or a path to itsbrand.json, or just the<id>). If the request names none and exactly one kit exists underbrand/, use it; otherwise ask which. - A request — plain language describing the deliverable ("a landing page", "an investor deck", "a brand guidelines PDF", "an OG image for the launch", "tokens for my Next.js app", "a launch tweet thread", "a 30s promo video"). You route it to one or more surfaces (below).
Phase 0 — Preflight (before any creative spend)
node "$SKILL_DIR/scripts/doctor.mjs" # general; add --bake to require Chrome + playwright-core
- FAIL aborts.
playwright-core+pptxgenjsare this skill's only deps — install once withnpm i -D playwright-core pptxgenjsin$SKILL_DIR(playwright drives your installed Google Chrome, no browser download). They are needed only for bakes (PNG/PDF/PPTX); tokens, copy, video-brief, and all.htmloutputs work with zero deps. - Decide the output root: default
out/<id>/at the project root (per-surface subfolders below). Refuse to clobber a non-empty target without confirming.
Phase 1 — Load the kit (the contract)
Steward preamble (read before any render). The kit is the single source of truth — it out-ranks
anything you remember about the brand from earlier in this conversation. Before rendering ANY branded
asset, re-read the primary spec (brand.json — or brand.spec.json / design.md when that's what
exists), design.md, and craft/anti-slop.md. Never render from conversational memory of the palette,
type, voice, or copy — memory drifts, the files don't. If a value isn't in the kit, it isn't a brand
value; go get it, don't fill it in from vibes.
Missing / partial kit protocol. If brand.json (or a referenced asset — a font, a logo, an
editorial file, the anti-slop list) is absent, announce exactly which file/asset is missing,
then offer two paths and STOP for a choice: (a) best-effort from what exists (name what you'll infer
and from where — e.g. palette scraped from design.md), or (b) regenerate the kit via /make-brand.
Never silently fill a gap or substitute a default.
Enforcement strictness (strict | balanced | flexible, default balanced). This dial governs
stylistic guideline adherence only — how hard you hold tone dials, layout preferences, device
placement, and copy conventions. The anti-slop G1 gate stays hard at every level — banned fonts,
banned hues, eyebrow pills, 3-card rows, "It's not X. It's Y.", stock metaphors never pass, strictness
regardless. Only style flexes: strict = follow the kit's stated conventions to the letter; balanced
= follow them, adapt when the surface genuinely needs it (state the adaptation); flexible = treat them
as strong defaults, deviate freely with a one-line trace. Conflict protocol — when the request fights
a guideline: (1) name the conflict in one line, (2) recommend the on-brand resolution with a reason,
(3) offer follow / adapt / override and let the user pick. Don't quietly override a stated convention.
node "$SKILL_DIR/scripts/load-kit.mjs" --kit brand/<id> # writes brand/<id>/brandContext.json + prints a summary
brandContext.json is the normalized contract every generator reads — palette (bg/bg2/panel/fg/dim +
accent roles + gradient/accentMode), fonts (families + vendored woff2 + fonts.css), logos, stickers,
backgrounds, mockups, voice lock, editorial files, signature devices. Read its summary; the warnings tell you
what the kit lacks (e.g. no fonts → system fallback) so you can set expectations. If the kit has no
brand.json/brand.spec.json, the loader best-effort reconstructs from design.md + the asset folders and
says so — sanity-check the palette before rendering.
Also read brand/<id>/craft/anti-slop.md when present — it is a hard gate for every surface, visual and
copy alike. Older kits without it: fall back to this skill bundle's own copy at
skills/make-brand/assets/craft/anti-slop.md if resolvable, else the editorial.noSlop list in
brand.spec.json.
openQuestions register. When brand.json carries openQuestions[] (deferred brand decisions, each
with a recommendation), check whether the deliverable touches one. If it does: flag the open
question to the user in one line and apply the recorded recommendation as the working default —
unless the user tells you otherwise. Don't re-litigate a deferred decision silently, and don't leave it
unmade; the recommendation is the provisional answer until the brand resolves it.
Phase 2 — Route the request → surface(s)
| If the user wants… | Surface | Generator |
|---|---|---|
| a website / landing page / hero / docs page | web | web.mjs |
| a social post / OG image / Twitter card / story | social | social.mjs |
| a slide deck / pitch / investor deck | deck | deck.mjs |
| a brand-guidelines PDF, or any document → PDF | pdf.mjs |
|
| taglines / launch post / thread / ad / email / landing copy / UI microcopy | copy | copy.mjs |
| CSS variables / Tailwind theme / design tokens for a codebase | tokens | tokens.mjs |
| a video / promo / TikTok / Reel / explainer | video | video-brief.mjs → /make-video |
One request can fan out to several (a launch = landing + OG card + tweet thread). Ask only when genuinely ambiguous (which surface, which platform/size, which background) — use the office-hours decision-brief discipline below; otherwise pick the sensible default, state it, and proceed.
Phase 3 — Generate (per surface)
Every generator takes --kit brand/<id> and --out <dir>; baking surfaces also take --bake. After running,
open/verify the output (see Phase 4). Standard runs:
S="$SKILL_DIR/scripts"; K="brand/<id>"
# WEB — self-contained .html (+ fullpage PNG with --bake)
node "$S/web.mjs" --kit "$K" --kind landing|hero|page --out out/<id>/web \
--headline "…" --subhead "…" --cta "…" --eyebrow "…" [--bake]
# SOCIAL — exact-size card → PNG
node "$S/social.mjs" --kit "$K" --size og|square|story|twitter|<WxH> \
--title "…" --subtitle "…" --kicker "…" --badge "…" [--bg bg-<name>] --bake
# DECK — HTML deck (+ PDF/PPTX). Edit the sample outline, then rerun with --in.
node "$S/deck.mjs" --kit "$K" [--in out/<id>/deck/outline.json] --out out/<id>/deck [--pdf] [--pptx]
# PDF — auto brand-guidelines, or wrap a doc
node "$S/pdf.mjs" --kit "$K" --kind guidelines --out out/<id>
node "$S/pdf.mjs" --kit "$K" --kind doc --in path/to/doc.md --title "…" --out out/<id>
# TOKENS — tokens.css + Tailwind theme/config + tokens.json (+ fonts copy)
node "$S/tokens.mjs" --kit "$K" --out out/<id>/tokens
# COPY — scaffold a voice-locked message, then AUTHOR it (creative, below)
node "$S/copy.mjs" --kit "$K" --kind taglines|launch-post|tweet-thread|landing-copy|ad-variations|email|ui-microcopy \
--topic "…" --out out/<id>/copy
# VIDEO — assemble a /make-video brief from the kit, then hand off
node "$S/video-brief.mjs" --kit "$K" --platform tiktok|reels|shorts|youtube|square \
--story "…" --duration 30 --out out/<id>/video/brief.json
The creative parts (yours to author — scripts scaffold, you supply taste):
- web / social headlines & body — write real, specific copy in the brand voice; never ship lorem. Deploy a
signature device or the punctuation signature where it lands naturally. The
--eyebrow/--kicker/--badgeslots are opt-in — populate them only when the kit's signature devices include a label/pill device; otherwise omit the flag. - deck outline — when
--inis omitted,deck.mjswritesoutline.sample.json; rewrite it into the real narrative (cover → sections → content/quote → closing), then rerun with--in. - copy —
copy.mjscopies a scaffold and injects the brand + the paths of the editorial voice files to read. Readeditorial/03-VOICE-STORYTELLING.md+00-EDITORIAL-LINE.md+04-LLM-PLAYBOOK.md+voice/voice.lock.json— pluseditorial/EXEMPLARS.md(the ✅/❌ calibration pairs) when present, and forui-microcopyalsoeditorial/05-MICROCOPY.md(the kit's own per-element formulas) — fill the{{SLOT}}markers in the brand voice, then run the scaffold's VALIDATE checklist (on-voice · no AI-slop / no banned words · claims true · length fits channel · signature used). - video —
video-brief.mjswiresstyle.design_md(the brand's visual source of truth) +brand.json+ the voice lock + editorial into a brief, then prints/make-video <brief>. Hand off;/make-videoadoptsdesign.mdverbatim andeditorial/for motion + voice.
Phase 4 — Verify + report
- Render-check every visual deliverable (open the
.html, or the baked PNG/PDF, via/browseorplaywright): fonts load (no system fallback), it reads as the same identity as the brand board, color comes only from the kit's palette, the logo is crisp, the background sits behind content. Fix what you see. - Anti-slop gate (visual, against the kit's
craft/anti-slop.md): no eyebrow pill unless it is a kit signature device; no default 3-up card row — feature count/layout follows the brand board (2–4 allowed); no gradient-wash hero unlessaccentModeis gradient; no glassmorphism. - Determinism for bakes: re-bake and confirm byte-stability; grep generated HTML for no
Math.random/Date.now/ infinite gradient animation — and for slop tells:font-familyInter|Space Grotesk|Geist|Instrument Serif|Roboto|Arial (normalize spaces/hyphens before matching), hex#6366f1|#8b5cf6|#7c3aed,backdrop-filter. - Conformance lint (post-render — verify the finished deliverable back against the kit; closes the loop
the creation-side gates leave open). Check and print a short pass / revisions report:
- Fonts — every
font-familyused is a kit face (⊆ctx.fonts), no system fallback, no banned default. - Colors — every hex/color used is in the kit palette (⊆
ctx.paletteroles + gradient), no stray hue. - Contrast — text over its background clears WCAG AA (≥ 4.5:1 body, ≥ 3:1 large/UI); flag any pair below.
- Banned terms absent — zero hits on the kit lexicon
prohibited[]+ the anti-slop verbal list (buzzwords, "It's not X. It's Y.", "Find Your …") across all copy in the deliverable. - Visual anti-slop — zero G1 hits (eyebrow pill / 3-card row / gradient-wash / glassmorphism / sparkle glyph).
- Voice matches the exemplars — when the kit ships
editorial/EXEMPLARS.md, read its ✅/❌ pairs and check the deliverable's copy sits on the ✅ side of each annotated rule. - Multi-script text — when the kit declares non-Latin
languages, carry the Noto fallback chain documented in the kit'sfonts.cssinto every renderedfont-familystack (no tofu). If anything fails, fix it and re-lint — don't ship with open revisions.
- Fonts — every
- Report: the kit used, each deliverable + its path, the surfaces you chose, and the next hop (e.g. for
video, the exact
/make-videocommand; for tokens, which file to import). Include a "Brand constraints applied" line — 2–5 bullets naming the exact spec fields that shaped this deliverable (e.g. "palette.accents.focal#…→ CTA", "fonts.display…→ headline", "signatureDevices…→ hero label", "voice.lock mode…→ error tone", "logo.clearSpace…→ header padding") so the user sees the trace.
Render-safety contract (every generated asset obeys)
- Self-contained by default — fonts inlined as data-URI woff2 (
faceCSS(ctx,{mode:'inline'})), logo inlined as SVG (logoSvg), background inlined as data-URI PNG (bgUri). The opened file needs no network. (Use--link/copied assets only for a multi-file site where bundle size matters.) - Theme purely from variables —
:root{ rootVars(ctx) }thenvar(--bg/--fg/--acc/--panel/--line/--grad)+font-family:var(--fd|--fm|--fh). No hardcoded hex or font name → any kit themes the same template. - Motion (if any): transform/opacity only, finite, no
Math.random/Date.now. Deliverables are screenshot/print targets — static-first. - Bakes are CPU raster (
--disable-gpu, sRGB), fonts awaited, animations frozen → repeatable. - Naming + size budgets — name outputs by a slugged scheme
<kind>-<brand-id>[-variant].<ext>(e.g.og-acme-launch.png,landing-acme.html) so a folder of deliverables self-describes. Keep bakes in budget: PNG ≤ 1 MB recommended, 5 MB hard max; SVG ≤ 500 KB. Over budget → compress to slot (re-bake at the target size, not a giant canvas scaled down). - No live CSS filters on photos in baked surfaces — bake the grade into the raster instead. Chromium
rasterizes a
filter:/backdrop-filterelement to a lossless bitmap, which bloats the PDF/PNG far past budget and is non-deterministic across GPUs. Apply color grades/LUTs to the source image, then embed the already-graded raster. (Live filters are fine in.htmlyou'll never bake.)
Asking questions (office-hours discipline — self-contained)
When you must ask, use AskUserQuestion and frame each as a decision brief: a short title; 1–3 plain
sentences on what's being decided; one option marked (recommended) with a one-line reason; 2–4 options each
with a real upside + downside. If AskUserQuestion is unavailable, render the same brief as prose ("reply with a
letter") and STOP. Never silently auto-decide a creative call (which surface, platform/size, voice direction).
How a generator reads the kit (for authoring/extending)
All scripts import the shared loader + helpers from $SKILL_DIR/assets/_brand.mjs
(resolveKit, rootVars, faceCSS, fontsCss, logoSvg, pickLogo, dataUri, bgUri, abs, copyInto,
slug, parseArgs) and the rasteriser from _bake.mjs (screenshot, pdf). brandContext paths are
kit-relative; ctx.dir is absolute; read kit files via abs(ctx, rel). A new surface = a new
scripts/<surface>.mjs + (optionally) assets/<surface>/*.tmpl.html with {{TOKEN}} markers — nothing else
to wire.
File map (a /use-brand run)
out/<id>/
web/ landing|hero|page.html (+ .png with --bake)
social/ <id>-<size>.html (+ <id>-<size>.png with --bake)
deck/ deck.html · outline.json (or outline.sample.json) (+ deck.pdf / deck.pptx)
copy/ <kind>.md (scaffold → you author in voice)
tokens/ tokens.css · theme.css · tailwind.config.cjs · tokens.json · fonts/ · README.md
video/ brief.json (→ /make-video)
brand-guidelines.pdf (+ guidelines.html) # pdf --kind guidelines
brand/<id>/brandContext.json # normalized contract (load-kit)