Scope and repository structure
Bang Motion (bangtutorial/bang-motion) is a motion graphics skill and Claude Code plugin for coding agents. Supply a product topic, brand color and font sources, voice-over audio, or reference pacing; the skill produces a single double-clickable index.html that autoplays and loops without npm install or a local web server.
The skill renders directly in the browser with HTML, inline CSS, SVG filters, and GSAP plus Three.js loaded from HTTPS CDNs. When you need a video file, the bundled Puppeteer scripts render PNG sequences frame by frame for ffmpeg MP4 encoding, or build layers directly inside Adobe After Effects through the Higgsfield MCP bridge.
| Path or file | Verified count | Purpose |
|---|---|---|
SKILL.md | 1 main specification | Defines 4 core laws, 8 structural prohibitions, 10 style directions, workflow steps numbered 0 through 7, and a 39-item pre-handoff checklist |
.claude-plugin/ | 2 manifest files | plugin.json and marketplace.json for Claude Code plugin marketplace installation |
assets/ | 7 HTML starters | starter-opener.html plus 6 explainer starter architectures |
references/ | 8 technical reference docs | Covers anti-PPT rules, 19 opener concepts, stage architecture, motion techniques, cartoon stage rigging, and the AE MCP bridge |
scripts/ | 5 utilities and 3 AE scripts | Includes snap.mjs, export-frames.mjs, serve.py, vo-pauses.html, kepala-ekspresi.py, and scripts/ae/bridge/ |
Installation and verification
- Not completed:
Install an agent environment that reads
SKILL.md(Claude Code, Codex, Cursor, Windsurf, Antigravity, Cline, or Aider). - Not completed:
Use a desktop browser with WebGL and ES Module support, with internet access during playback to load CDN libraries and fonts.
- Not completed:
Optional: install Node.js and
puppeteerforscripts/snap.mjskey-second screenshot checks andscripts/export-frames.mjsframe-by-frame export. - Not completed:
Optional: install
ffmpegto encode PNG sequences to MP4, and Python 3 to run thescripts/serve.pyno-cache development server or character expression script.
Install directly inside Claude Code with the plugin marketplace commands:
/plugin marketplace add bangtutorial/bang-motion
/plugin install bang-motion@bang-motionFor a manual installation, choose one target path below. Use either the plugin or a manual copy to avoid duplicate skills. A single Claude Code project can use .claude/skills/bang-motion:
git clone https://github.com/bangtutorial/bang-motion.git ~/.claude/skills/bang-motion
git clone https://github.com/bangtutorial/bang-motion.git ~/.codex/skills/bang-motionIn Cursor, Windsurf, Antigravity, Cline, or Aider, clone the repository into the workspace and point the project rule or skill configuration to SKILL.md. For screenshot checks and MP4 export, install Puppeteer in the skill root so Node.js can resolve the package from the script path. This example uses the Claude Code manual installation path; adjust --prefix for another location:
npm install --prefix ~/.claude/skills/bang-motion puppeteer
ffmpeg -versionStage architecture and anti-PPT rules
Bang Motion prevents layout drift and dropped frames with a fixed-resolution stage and a single master timeline. #stage stays locked at 1920×1080 pixels and scales proportionally through Math.min(innerWidth / 1920, innerHeight / 1080), so relative coordinates stay identical across monitor sizes and export runs.
The #world camera rig wraps the WebGL <canvas>, the .bgfx gradient overlay, and #dom text and UI elements together. Lens overlays (.leak, .vignette, and .grain) sit outside #world. When the camera pushes or pans, the 3D background and typography move as one space instead of scaling text alone like a slide deck.
| Specification | Mandatory constraint | Engineering purpose |
|---|---|---|
No <section> fade decks | Do not toggle full-bleed <section> blocks via opacity or autoAlpha | Stops the output from turning into an autoplaying slide deck |
| Single source of time | Every DOM and Three.js state is a deterministic function of tl.time(); do not call Math.random(), Date.now(), or pos += v * dt accumulation inside the render loop | Supports arbitrary timeline scrubbing and zero-drop frame export with identical pixel output on every run |
| Absolute timestamps | Write absolute timestamps in GSAP tweens (such as 8.10) without chained relative offsets | Matches the scene rundown table directly so retiming one scene leaves later scenes untouched |
| Text hierarchy and minimum size | At most 2 text hierarchy levels per frame; minimum 30px font size on the 1080p stage (body >= 44px, labels >= 34px, credits >= 30px) | Keeps text readable on phones and prevents crowded slide layouts |
| Text-pocket contrast | Luminance directly behind text must be <= 25% (dark pocket) or >= 80% (light pocket), with background element opacity <= 0.35; apply bloom only to objects, keeping headline text clean | Prevents glowing particles or mid-tone backgrounds from washing out letterforms |
window.OPENER export contract | Pages must expose { W, H, ready, seek(t) } (plus seekFrame(t) and clipsReady() when video clips are present), and ?clean=1 must hide controls and pause autoplay | Lets snap.mjs and export-frames.mjs lock exact timestamps before capturing frames |
Law #3 in SKILL.md requires submitting a Style Brief and a scene Rundown for user approval before writing code. Extract the primary color from the brand logo or product UI and choose a distinctive display typeface (excluding Inter, Roboto, Poppins, Montserrat, and Arial unless using the native product-UI concept). Pick the structure from 10 style directions and 19 opener concepts in references/opener-konsep.md; do not keep the placeholder grays in starter-opener.html or copy palettes and wording from reference videos.
Starters and utility interfaces
Openers and promos
assets/starter-opener.html
Product opener and kinetic type skeleton
Provides a 1920×1080 stage, #world camera rig, state-driven Three.js scene, and 8 text entrance helpers. Its gray palette and system font are placeholders that must be replaced immediately with brand tokens.
Explainers
assets/starter-explainer*.html
6 explainer starter architectures
Select continuous action, cartoon collage, visual journalism, white catalog, vintage sketch, or cartoon stage; ask one upfront question covering style, aspect ratio (default 16:9), duration, and voice-over source before coding.
VO alignment
scripts/vo-pauses.html
Browser voice-over pause detector
Web Audio utility requiring no ffmpeg install. Double-click to load audio and emit SEG, PARA, and DUR timestamp arrays using a default -30 dB threshold, 0.45 seconds minimum pause, and 0.8 seconds paragraph boundary.
Visual review
scripts/snap.mjs
Key-second screenshot inspection
Opens index.html?clean=1 over file:// in Puppeteer and calls OPENER.seek(t) to capture 6 to 20 key-timestamp PNGs so the agent can check clipping, overlap, and transition timing.
Video export
scripts/export-frames.mjs
Zero-drop frame-by-frame PNG renderer
Steps through the timeline at FPS (default 60) and SCALE (default 1), waits two requestAnimationFrame cycles per frame to write f00000.png sequences, and hands off to ffmpeg for H.264 MP4 encoding.
AE bridge
references/ae-bridge-higgsfield.md
Direct After Effects build workflow
When After Effects is open with Higgsfield ae_* MCP tools connected, scaffolds compositions via a small Lottie payload and uses aset-svg.py plus rig-tokoh.py to build 2× PNG assets and native jointed characters.
Select from the 6 explainer starter templates according to topic and source assets:
| Starter file | Style role | Built-in stage and typography setup |
|---|---|---|
starter-explainer.html | Continuous action (vector) | Flowing world strip, persistent hero present for over 60% of duration, map view, and whip transitions |
starter-explainer-kartun.html | Cartoon collage | Cream paper texture with grain and stains, illustration cutouts, Bricolage with Caveat fonts, colored pill highlights |
starter-explainer-jurnalisme.html | Visual journalism | Dark grained backdrop, archival photos with source tags, Barlow Condensed with Plex Mono, yellow and red highlighter marks |
starter-explainer-katalog.html | White catalog | Subtle grid on white, photo cutouts, Archivo Black with Caveat and Inter, yellow accent highlights |
starter-explainer-sketsa.html | Vintage sketch | CSS sepia paper texture, multiply engraving cutouts, Playfair with Garamond and Cinzel |
starter-explainer-panggung.html | Cartoon stage | Per-scene stage and camera (zoom 1.08–1.95), J() manual joint proxy transforms, character() rig, and 96px slide transitions |
Operating principles
Approve the style brief and rundown before writing code
Rewriting timeline code takes longer than editing a text table. List brand hex colors with their sources, display fonts, background motion language, signature gesture, and a 25 to 40 second timestamp-scene-copy-visual rundown for user approval before copying a starter.
Separate key-second verification from full-video export
A 60 second video at 60 fps produces 3,600 images, which takes minutes without checking composition. After each edit, capture 6 to 20 scene starts and text entrances with snap.mjs to check clipping and contrast; run export-frames.mjs only when the user requests an MP4.
Bind live-action or screen-capture footage with clip()
A raw <video> tag with autoplay and loop runs on its own clock and breaks frame-by-frame export. Starting in v1.18.0, mount video clips through clip(el, { at, in, out, rate, hold }) as timeline-controlled layers and inspect clip timestamps with snap.mjs.
Use a no-cache server during edits, then inline into one file
During multi-file edits, python -m http.server allows browsers to cache stale ES modules; run python3 scripts/serve.py (default port 5178, sending Cache-Control: no-store). For handoff, inline all CSS and <script type="module"> blocks into one index.html to avoid file:// CORS blocks.
Worked example
After assembling a single-file index.html, run serverless key-second screenshot checks from the project directory first, confirm framing and timing, and then start the no-cache server to export a 1920×1080, 60 fps MP4 file.
From the directory containing
index.html, runsnap.mjswith an output folder and target timestamps (it defaults to openingfile:///.../index.html?clean=1in the current working directory).Inspect the PNG screenshots inside
shots/to confirm headlines clear background particles, gray starter placeholders are gone, and text settles after camera moves finish.When MP4 delivery is requested, start
serve.pyin the background or a second terminal (defaulthttp://127.0.0.1:5178), then runexport-frames.mjsandffmpeg.
$ node ~/.claude/skills/bang-motion/scripts/snap.mjs shots 0.5 3.5 8 14.5 22 28
0.5 3.5 8 14.5 22 28
selesai
$ ls shots
t0_50.png t3_50.png t8_00.png t14_50.png t22_00.png t28_00.png
$ python3 ~/.claude/skills/bang-motion/scripts/serve.py 5178 &
serving on http://127.0.0.1:5178 (no-store)
$ FPS=60 OUT=frames SCALE=1 node ~/.claude/skills/bang-motion/scripts/export-frames.mjs
1800 frame @ 60 fps (30s) -> frames/
selesai — 1800 frame di frames/
$ ffmpeg -framerate 60 -i frames/f%05d.png -c:v libx264 -pix_fmt yuv420p -crf 16 opener.mp4For voice-over explainers, open scripts/vo-pauses.html in a browser first, load the recorded .wav or .mp3, and paste the generated const SEG=[...]; const PARA=[...]; const DUR=...; arrays into the timeline so each scene start t0 locks to a spoken paragraph boundary.
Limitations and edge cases
| Edge case | Confirmed limitation | Official workaround |
|---|---|---|
| Clipped SVG motion-blur tails | Default SVG <filter> bounding boxes crop long blur tails on fast text | Widen the filter x, y, width, and height attributes manually |
| Flat 3D objects rotated full-circle on Y | At 90 degrees edge-on, flat elements collapse into a thin line | Use bounded angle wobble instead of a full 360 degree spin |
Cartoon stage joints rotated via GSAP transformOrigin | Combining GSAP rotation and x/y tweens on SVG groups with translate dislocates joints | Use J() manual proxy transforms as specified in kartun-panggung.md |
| After Effects Higgsfield MCP bridge limits | ae_reorder_layers returns layer-not-found errors; new CAM nulls spawn at (960, 540); the bridge cannot save projects or render video | Create layers in back-to-front stacking order; reset CAM anchor and position to [0, 0] before parenting; instruct the user to press Ctrl+S and export MP4 via Render Queue or aerender.exe |
Next steps
Before designing an opener or launch promo, read
references/opener-konsep.mdto shortlist 3 of the 19 structural concepts and record the structural fingerprint (scene count, primary object per scene, opening, and ending) so consecutive products do not share the same skeleton.For character-driven explainers, check
references/kartun-panggung.mdandscripts/kepala-ekspresi.pyto confirm every stage maintains>= 1.08camera zoom and at least 10 moving elements.After exporting a silent or voice-over-only MP4, connect Openverse, MMAudio, and Earshot to add openly licensed recordings, multimodal video-to-audio synthesis, and quantitative loudness and sync verification.