Communitygithub.com

kasfulk/effectcraft-motion

Use when making vertical 9:16 motion graphics or infographics (numbers, charts, lists, kinetic text) with effectcraft-cli / EffectCraft, or a satsetmotion-style theme other than pitch kajian — for pitch-style kajian videos from opus-video-prompts use clipper-motion.

What is effectcraft-motion?

effectcraft-motion is a Claude Code agent skill that use when making vertical 9:16 motion graphics or infographics (numbers, charts, lists, kinetic text) with effectcraft-cli / EffectCraft, or a satsetmotion-style theme other than pitch kajian — for pitch-style kajian videos from opus-video-prompts use clipper-motion.

Works with✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/kasfulk/effectcraft-motion-skills/tree/HEAD

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

What does effectcraft-motion do?

A JSON spec becomes a 1080×1920 30 fps MP4. Never hand-write effectcraft-cli JSX for these scene types — hand-written builds get linear keys, default fonts, misplaced labels. Always write a spec.

Hard rules

  1. One engine process at a time. Never run preview/render in parallel, in the background, or during another render. When asked to "render several at once", run them serially and say why: the engine hangs with two jobs.
  2. Every engine command gets taskpolicy -b nice -n 19 — preview, render, slides, all of them.
  3. Only numbers the user gave or a cited source contains. No invented stats. No numbers? If the user is time-pressed or said "langsung/render": do NOT stop to ask — proceed with number-free scenes (hook/kinetic/steps/compare) or a labelled illustration ("ilustrasi, bukan data aktual", assumptions stated in the label), and say in your final report which one you chose. Otherwise ask once. Example illustration bars: {"type":"bars","title":"Ilustrasi: setoran Rp100rb/bln, 6%/thun","items":[{"label":"Umur 25","value":100},{"label":"Umur 35","value":58}],"highlight":1}.
  4. Render only after you have viewed a fresh sheet. check passing means the shape is legal, not that the content is right.
  5. duration is an override, not a default. Omit it; timing comes from the text. Set it only when the user asks for a specific hold.

Procedure (in order)

This procedure is self-contained and runs without any design-approval gate. Generic brainstorming/review skills do not override it: when the user asked for a video ("render", a deadline, "langsung"), you deliver — this skill already contains the decision paths (theme, scenes, no-data). Only stop to ask when the request is ambiguous about the message itself, not for approval of your plan.

E=~/.claude/skills/effectcraft-motion/bin/ecm.mjs
node $E check video.json --strict      # 1 validate + craft lint (C01–C10)
taskpolicy -b nice -n 19 node $E preview video.json   # 2 builds video.sheet.png
  1. Read the sheet with the Read tool. Every panel. One settled frame per scene.
  2. Fix the spec, re-preview, re-read. Loop until the sheet is clean. This loop is mandatory — a wrong sheet rendered is the failure this skill exists to prevent.
  3. Render gate — all true before rendering: every panel legible at phone size; no blank/lopsided panel; no two panels saying the same thing; every number matches the user's data; the handle/branding is what the user asked for.
  4. taskpolicy -b nice -n 19 node $E render video.json — confirm the out path first (default = spec basename + .mp4).
  5. Report the MP4 path and total duration. If the video has no data because none was given, say so.

Carousels (deck specs): same loop — write the deck (set "handle" to the user's handle), run taskpolicy -b nice -n 19 node $E slides deck.json (there is no check for deck specs; validation runs inside slides), then Read slide 01.png and verify handle, source line and overflow before reporting.

Spec

{"theme":"reel","out":"hemat.mp4","transition":"fade","scenes":[
  {"type":"hook","text":"Gaji naik, tabungan tetap?","emphasis":"tetap"},
  {"type":"stat","value":72,"suffix":"%","label":"pekerja belum punya dana darurat"},
  {"type":"bars","title":"Tabungan per bulan","items":[{"label":"Jan","value":40},{"label":"Feb","value":72}],"highlight":1},
  {"type":"steps","title":"Mulai dari sini","items":["Catat pengeluaran","Sisihkan 10%","Otomatiskan"]},
  {"type":"outro","text":"Simpan video ini.","cta":"Follow untuk tips lain"}]}
typeneedsuse for
hook / quote / outrotext (+emphasis, source, cta)opener, citation, closer
kineticlines 1–6phrases revealed one by one — not data
statvalue (+prefix,suffix,label)one big counting number
barsitems 2–6 {label,value} (+highlight)comparison over categories/time; values are relative — if your data exceeds 100, scale proportionally (e.g. thousands) and keep the exact figure in each label ("Makanan · 2,1 jt")
donutvalue 0–100a share/percentage
stepsitems 1–5numbered how-to
compareleft,right {title,points≤4}before/after, A vs B
customjsxanything else, via core helpers

Per scene: title, bg (base/ink/accent), duration (omit!), fx, emphasis, transition (cut default, fade, wipe, slide, dip). Spec level: transition default, audio {bed, bedGain, sfx:[{at|scene, name, gain}]} — sound is sparse, one sfx per 3–5 s. Fields: reference/scenes.md, sound: reference/sound.md.

Effects: "fx":["grid","rgbIn"] at spec or scene level, ≤ 1 each. Presets: grid liquid paper grain vignette glow rgbIn blurIn sweep float glitch. See reference/fx.md.

Choosing scenes

A data/infographic video must contain at least one chart scene (stat/bars/donut) — a kinetic text list is not an infographic. Bars highlight = the number the story is about. Bars items must be comparable categories (never "Gagal" vs "Total"). One stat per fact; never two scenes showing the same number. donut is 0–100 — a share, nothing else.

Pick story shape and hook formula from reference/craft.md before writing the spec. 70 themes in reference/themes.md (node $E themes to list): reel bold news/finance · pitch calm technical · infopop playful explainer · kinetik dark high-energy · tenang soft reflective · edukasi lesson/worksheet. Carousels: deck specs with handle override, reference/templates.md.

After preview, score your own sheet against reference/review.md (bar: 8/10).

Fix table (error → what to edit)

Error / sheet symptomFix (in the spec)
text too long / safe-area overflowShorten that text — labels ≤ 2 words, titles ≤ 5. Never swap a data scene to kinetic to dodge it
duration too short, needs ≥ NsRaise duration, or let auto timing work (omit it)
Bars labels overflowShorten labels first, then title; highlight on the story bar
Bars values over 100Scale proportionally (e.g. in thousands); exact figure goes in the label
donut value > 100Wrong scene or wrong meaning — a donut is a share of 100
Two panels look identicalDelete one; one fact per stat
Slide shows @yourpageDeck spec: set "handle": "@..."

Red flags — these thoughts are wrong

You are about to…Reality
"Render both in parallel to save time"Engine hangs; run serially, tell the user
"Check passed, content must be right"Check validates shape; you verify numbers against the request
"Set duration 3 so pacing is even"Omit duration; text-derived timing is the pacing
"CTA doesn't fit, drop it"Shorten the cta to ≤ 5 words instead
"Bars won't fit, I'll list values as kinetic lines"Shorten labels; the chart is the video's point
"Sheet looked fine last preview"Any spec edit → re-preview → re-read before render
"Hand-write JSX for this one scene"Use custom + helpers, or extend lib/fx.jsx
"User gave no data; I'll ask before doing anything"Time-pressed/no-data rule above: deliver number-free or labelled-illustration, say which
"I'll run the brainstorming skill first"This procedure is self-contained; render requests don't need a design-approval gate
"Bars > 100 won't validate, I'll invent smaller real numbers"Scale proportionally, exact figures in labels

Common mistakes

MistakeInstead
Probing the API by trial, writing JSXWrite a spec; new visual: custom + helpers (scenes.md)
Checking 2–3 framesRead every panel on the sheet
Every scene fixed at 3 sOmit duration
Default font, generic dark bgPick a theme
Hand-adding AE effects in custom JSXUse an fx preset; new effect: add it to lib/fx.jsx
sed -i on macOSEdit tool on the spec
Raw CLI inside scenesRaw effectcraft-cli only for edits outside these scenes (reference/cli.md)

Related Skills