Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

banner-builder — an HTML5 display banner toolkit: GSAP templates, clickTag wiring, and a 150 KB compliance gate

quick start gate deps license

HTML5 display banners break in boring ways: the zip is 4 KB over, clickTag was declared with const so the click goes nowhere, a background glow loops forever and the platform rejects the whole flight. You find out days later, from a moderator.

This toolkit is two things that stop that: animation templates that already follow the rules, and a script that fails the build when they are broken.

git clone https://github.com/komilovsg/banner-builder.git
cd banner-builder
bash scripts/check.sh examples          # see the gate run on a real size set
open examples/preview.html              # watch all three banners animate

No npm, no build step, no toolchain. Bash, zip, and a browser.

Quick start

Build one banner:

mkdir -p out/300x250
cp templates/banner.html out/300x250/index.html
# edit: copy, colors, and the clickTag URL near the bottom of the file
bash scripts/check.sh out/              # must pass before you send anything
bash scripts/backup.sh out/             # renders backup.jpg from the end frame
cd out/300x250 && zip -rX ../300x250.zip .   # index.html must sit at the zip root

That zip is what you upload to Google Ads, Yandex Direct, or MyTarget.

What it produces

Real output from examples/, rendered end frames:

300x250 rectangle banner, end frame 160x600 skyscraper banner, end frame

728x90 leaderboard banner, end frame

Each size is re-laid out, not scaled: the rectangle stacks, the leaderboard runs logo → message → CTA horizontally, the skyscraper reads top-down. That difference is the single most common reason a client sends a size set back.

out/
├── 300x250/
│   ├── index.html     # markup + CSS + JS inline, self-contained
│   └── backup.jpg     # static fallback, exact dimensions
├── 728x90/
└── 160x600/

The gate

A banner is not done when it looks good. It is done when it passes:

$ bash scripts/check.sh examples
SIZE             ZIPPED      CAP   RESULT
------------------------------------------------------------
160x600             18K     150K   PASS
300x250             20K     150K   PASS
728x90              17K     150K   PASS
------------------------------------------------------------
3 banner(s), 0 failed, 3 warning(s).

check.sh zips every banner directory it finds and exits non-zero on:

check why it exists
zipped weight over cap Google Ads and Yandex Direct both reject over 150 KB
no global var clickTag ad servers rewrite that literal — let/const/concatenation break the click
location.href = clickTag navigates the ad iframe instead of opening the landing page
repeat: -1, animation: infinite endless creatives fail automated policy review
runtime code evaluation, cookies, localStorage scanned for and rejected
ad.size meta missing or mismatched the ad server sizes the slot from it
missing backup image, no visible border warnings — both are required for delivery

Comments are stripped before scanning, so a file that documents a banned pattern does not fail for mentioning it. Point it at any banner folder — it does not care whether these templates produced it:

bash scripts/check.sh ~/clients/acme/creatives 150

Templates

template when
templates/banner.html default. GSAP timeline, 3 scenes, ?frame=end, ~20 KB zipped with the CDN
templates/banner-nogsap.html hard weight caps or a platform that blocks every external host. Pure CSS @keyframes, ~4 KB zipped, zero requests

Both are one self-contained file: markup, styles, and script inline. Copy, rewrite the copy blocks, change the CSS variables at the top, set clickTag. Nothing to compile.

Reference

Two documents that carry the parts people get wrong:

  • reference/platforms.md — Google Ads / DV360, Yandex Direct and MyTarget specs, the exact shape clickTag must have and why, and a pre-flight checklist.
  • reference/layouts.md — layout recipes and type scale per IAB size family: rectangle, leaderboard, skyscraper, mobile.

How a set gets built

Pipeline: brief, master size, port to the set, check.sh gate, ship

Design the master size first — usually 300×250, because that is where the timeline gets settled. Then re-lay-out for the rest of the set, run the gate, capture backups, zip.

Use it with Claude Code

The repository doubles as a Claude Code skill: SKILL.md carries the output contract, the build procedure, and the motion rules, so an agent produces the same structure the templates and the gate expect.

bash scripts/install.sh          # symlink into ~/.claude/skills — git pull keeps it current

Restart Claude Code, then:

/banner-builder 300x250 728x90 160x600
variant effect
bash scripts/install.sh symlink into ~/.claude/skills/banner-builder — available in every project
bash scripts/install.sh --copy copy instead of symlink
bash scripts/install.sh --project install into ./.claude/skills of the current project only

Entirely optional. Everything above works from a plain terminal.

Details worth stealing

  • ?frame=end. Every template jumps its timeline to the last frame on that query string. Headless Chrome does not reliably advance requestAnimationFrame under --virtual-time-budget, so waiting N seconds screenshots scene 1 instead of the end frame. This makes backup capture deterministic.
  • Reset in onRepeat, not at the tail of the timeline. Then the timeline's end state is the end frame, which is what the backup image and QA depend on.
  • Finite ambient tweens. A drifting background glow set to repeat: -1 is still an infinite animation to a policy scanner.
  • Everything in CSS. Gradients, glows, shine sweeps — no rasters means the weight budget goes to the parts that need it.
  • Overlap, never queue. tl.to(a, {...}).from(b, {...}, '-=0.35'). Sequential fades read as a slideshow; overlapping ones read as motion design.

No dependencies

Bash, zip, and a browser. backup.sh also wants Chrome or Chromium, which you already have. GSAP loads from a CDN in the templates; vendor gsap.min.js into the bundle (~25 KB zipped) whenever the platform does not whitelist the host — Yandex effectively does not.

Русский

Тулкит для HTML5-баннеров: шаблоны с анимацией и скрипт-гейт, который валит сборку до того, как креатив уедет на модерацию.

git clone https://github.com/komilovsg/banner-builder.git
cd banner-builder
bash scripts/check.sh examples     # гейт на реальном сете размеров
open examples/preview.html         # три баннера в браузере

Собрать свой: скопировать templates/banner.html в out/300x250/index.html, поменять тексты, цвета в CSS-переменных и clickTag, прогнать check.sh, снять подложку backup.sh, запаковать в zip так, чтобы index.html лежал в корне архива.

check.sh архивирует каждую папку и валит сборку на: превышении 150 КБ, отсутствии глобального var clickTag, объявлении через let/const, бесконечных циклах (repeat: -1, animation: infinite), запрещённых API и несовпадении ad.size с именем папки. Работает на любых чужих баннерах, не только на этих шаблонах.

Спецификации площадок (Google Ads, Яндекс.Директ, MyTarget) — reference/platforms.md, раскладки и типошкала по размерам — reference/layouts.md.

Опционально ставится как скилл для Claude Code: bash scripts/install.sh, дальше /banner-builder 300x250 728x90.

Contributing

Useful additions, in rough order of value: platform specs that have actually caused a rejection, layout recipes for sizes not covered yet, additional checks for check.sh. Keep the repository dependency-free — that constraint is the point.

License

MIT — see LICENSE.

About

HTML5 display banner toolkit: GSAP + pure-CSS templates, clickTag wiring, and a compliance gate that fails the build on weight, infinite loops, and broken clicks. No build step. Optional Claude Code skill.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages