skillZs
★ LIVE SKILL TAGS ★
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
※ REAL INSTALL DATA ※
← back to all skills
phantomtonyt/motion-design-skills119 installs

data-story-charts

Data-story videos where an animated chart carries the argument - lines that draw as time passes, bars that grow, a big counter that ticks, axes that rescale when the data surprises, annotation pins on the key moments - rendered to MP4 at 9:16 or 16:9 with HyperFrames, SVG and GSAP. Use whenever someone wants to animate statistics, show a trend, growth or cost over time, compare numbers, break down a figure (salary, budget, benchmark), or turn a dataset or table into a short narrated video. Not for architecture or request flows (use system-diagram-animation) or text-only videos (use kinetic-typography).

How do I install this agent skill?

npx skills add https://github.com/phantomtonyt/motion-design-skills --skill data-story-charts
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    This skill provides instructions and code templates for creating animated data-story videos using SVG, GSAP, and the HyperFrames CLI. It relies on standard tools like Node.js and FFmpeg, and fetches libraries from well-known sources. No malicious patterns were identified.

  • Socketpass

    No alerts

  • Snykpass

    Risk: LOW · No issues

What does this agent skill do?

Data Story Charts

One chart, built and revealed in the order of the story. The number is the hero: a big counter at the top, a line or bars that move with it, and annotation pins that say why it changed. It should feel like explanatory journalism: clear, calm, with one or two dramatic moments.

Options

OptionDefaultNotes
formatvertical 1080×1920or landscape 1920×1080
duration15–20 sabout 3–5 s per data beat
chartlineline (change over time), bars (compare), stacked (break down a total), counter (one big number)
toneeditorialeditorial (default, light paper), dark (navy, glowing accent), punchy (faster, colour flips on the big moment)

Brief (answer before planning)

  1. What is the one number or change the viewer should remember?
  2. What is the data (paste or file)? Units, time range, source.
  3. What is the surprise: a spike, a drop, a crossing, a hidden cost?
  4. Which 2–4 moments deserve an annotation pin?
  5. What is the closing line?

Use only real numbers the user gave, or numbers you computed from their data. Never invent data. If something is an estimate, say so on screen.

Reads sheet (write it with the beat list)

For every beat, write the one thing the viewer must understand ("the robot can't fly", "the cache missed") and how long it stays readable. One read at a time. Text floors: a label stays at least 0.8 s, a sentence about 0.3 s per word once fully on screen. If the text won't fit the time, cut words rather than speed up.

Motion discipline

  • Motion is causal: every move has a reason on screen (a click, a fall, a packet arriving), and the next move follows from it.
  • Pick one main direction of travel for the whole video and keep it. Use the other directions for meaning: up for success or conclusion, a zoom out for "here's the whole picture".
  • A scene's exit sets up the next entry: same axis, same direction, similar speed. Carry one object across the change instead of crossfading.
  • No idle filler motion (floating, breathing, wobbling) on diagrams, charts or text. If nothing should move, hold still; one deliberate camera drift is enough.
  • Easing: smooth ease-out for entries (power2.out to power4.out), quicker ease-in for exits (about 75% of the entry time). Entries at most 0.8 s. Total stagger for a group at most 0.5 s. Overshoot (back.out) only for small pops; no elastic or bounce.
  • One thing moves at a time when it matters; the eye can follow only one.
  • Add a 0.3–0.75 s beat of stillness right before the payoff.

Style rules (always)

  1. One chart type per scene and one series in focus. Other series are grey.
  2. The chart is revealed by time or by story: lines draw left to right, bars grow in order, and nothing appears before it is talked about.
  3. A big counter shows the current value and ticks with the chart (tabular numbers).
  4. When the data outgrows the axis, the axis rescales on screen (an eased tween of the scale and its labels). That rescale is usually the best moment in the video.
  5. Pins annotate the 2–4 key points with short labels.
  6. Every label passes 3:1 contrast. Grid and tick labels are a muted dark grey, not pale grey.

Defaults and overrides

Precedence: the user's brand or spec, then the explicit request, then these defaults.

  • Editorial: paper #f7f4ee, ink #16213a, grid #e3ded4, tick labels #5b6270, accent #e4572e, positive #047857, warning #a16207, negative #c2410c.
  • Dark: stage #0f1724, ink #f2f5f9, grid #1f2b3d, labels #9fb0c8, accent #38d6e0.
  • Font: Inter (900 for the counter at 140–170 px, 800 for captions at 56–64 px, 600 for labels at 26–30 px).

Setup (once)

node -v && ffmpeg -version
npx hyperframes init my-video --non-interactive --resolution portrait && cd my-video   # landscape for 16:9

Route

NeedSVG + GSAP in HyperFrames (default)RemotionD3 inside HyperFrames
Lines, bars, counters, pinsyesyesyes
Thousands of points or map projectionsheavyheavyyes (draw from time t)
Runs with only Node and FFmpegyesyesyes

Layout

  • 9:16: kicker label at y 285, counter at y 350 (150 px), chart area x 120–960 by y 520–1000, axis labels below, caption at y 1110–1250.
  • 16:9: counter top-left, chart x 200–1720 by y 260–880, caption bottom-left or right of the chart.
  • Pins sit above their data point with a dashed stem. Keep them clear of the counter and the caption.

How to animate it (seek-safe)

Write the data as a function or an array, and draw the whole chart from one clock value t. One tween drives the clock, and its onUpdate redraws:

const clock = { t: 0 };
tl.to(clock, { t: DURATION, duration: DURATION, ease: "none", onUpdate: () => draw(clock.t) }, 0);
draw(0);

draw(t) rebuilds the line path up to t, moves the marker and the counter, and positions pins and axis labels from the current axis maximum (itself a function of t). Because every pixel comes from t, any frame renders the same whenever HyperFrames seeks to it.

MoveHow
Line revealpath built from samples up to t (about 30 per second of data)
Area under the linethe same path closed to the baseline, accent colour at 12% opacity
Bars growheights tween from 0 with a 0.08 s stagger, power3.out
Countertext from the current value; 1 decimal under 10, whole numbers above
Axis rescaleyMax(t) eases from the old to the new maximum over 1–1.5 s, while tick labels update
Pin popscale 0.5 → 1 with back.out(2.5) at its time
Emphasisthe counter scales 1.12 yoyo on the key number

Make it eye-catching

  • The first frame already has the counter, the axes and the question.
  • The surprise moment gets the rescale, a pin and a caption change all within half a second.
  • A small marker (a dot, an icon or a character) rides the tip of the line, so the eye knows where to look.
  • The area fill and a soft accent glow on the leading point give depth without clutter.
  • Captions are short sentences with the number in the accent colour ("Then: 120 m.").
  • Every frozen frame states a fact on its own.

Starter

<div id="root" data-composition-id="main" data-start="0" data-duration="10" data-width="1080" data-height="1920" style="background:#f7f4ee;font-family:Inter,sans-serif">
<svg viewBox="0 0 1080 1920" width="1080" height="1920" style="position:absolute;inset:0">
  <g id="grid" font-size="26" fill="#5b6270"></g>
  <line x1="120" y1="1000" x2="960" y2="1000" stroke="#16213a" stroke-width="4"/>
  <path id="area" fill="#e4572e" opacity=".12"/><path id="line" fill="none" stroke="#e4572e" stroke-width="9" stroke-linejoin="round" stroke-linecap="round"/>
  <circle id="dot" r="14" fill="#e4572e"/>
</svg>
<div style="position:absolute;left:60px;top:350px;font:900 150px/1 Inter,sans-serif;color:#16213a;font-variant-numeric:tabular-nums"><span id="num">0</span></div>
</div>
<script>
const D = 10, X0 = 120, X1 = 960, Y0 = 1000, Y1 = 520;
const data = (t) => 2 * t + (t > 6 ? 40 * ((t - 6) / 4) ** 2 : 0);          // replace with the user's data
const yMax = (t) => 20 + 60 * Math.min(1, Math.max(0, (t - 6.5) / 1.2));    // axis rescales at the surprise
const px = (t) => X0 + (X1 - X0) * (t / D), py = (v, m) => Y0 - (Y0 - Y1) * (v / m);
const NS = "http://www.w3.org/2000/svg", grid = document.getElementById("grid");
const ticks = [0, 0.5, 1].map((f) => { const l = document.createElementNS(NS, "line"), x = document.createElementNS(NS, "text");
  l.setAttribute("x1", X0); l.setAttribute("x2", X1); l.setAttribute("stroke", "#e3ded4"); x.setAttribute("x", X1); x.setAttribute("text-anchor", "end"); grid.append(l, x); return { f, l, x }; });
function draw(t) {
  const m = yMax(t); let d = "";
  ticks.forEach(({ f, l, x }) => { const y = Y0 - (Y0 - Y1) * f; l.setAttribute("y1", y); l.setAttribute("y2", y); x.setAttribute("y", y - 10); x.textContent = Math.round(m * f); });
  const n = Math.max(2, Math.round(t * 30));
  for (let i = 0; i <= n; i++) { const s = (t * i) / n; d += (i ? "L" : "M") + px(s).toFixed(1) + " " + py(data(s), m).toFixed(1); }
  document.getElementById("line").setAttribute("d", d);
  document.getElementById("area").setAttribute("d", d + "L" + px(t) + " " + Y0 + "L" + X0 + " " + Y0 + "Z");
  const dot = document.getElementById("dot"); dot.setAttribute("cx", px(t)); dot.setAttribute("cy", py(data(t), m));
  document.getElementById("num").textContent = Math.round(data(t));
}
const tl = gsap.timeline({ paused: true }), clock = { t: 0 };
tl.to(clock, { t: D, duration: D, ease: "none", onUpdate: () => draw(clock.t) }, 0);
draw(0);
window.__timelines["main"] = tl;
</script>

Add a <head> with GSAP (https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js), the Inter font from Google Fonts, and html,body{margin:0;width:1080px;height:1920px;overflow:hidden}. Add a kicker, captions and pins on the same timeline.

Parameters to expose

format · duration · chart · tone · data (array or function) · units · pins (time, label, colour) · captions (time, text) · rescaleAt.

Avoid

  • Every number on screen must come from the user's data or a cited source. Keep a small facts list (number, source) next to the composition. Anything illustrative is labelled as such on screen.
  • Invented or "illustrative" numbers presented as real.
  • Several highlighted series at once, or rainbow palettes.
  • Pale grey labels (they fail contrast checks and are unreadable on phones).
  • Chart junk: 3D bars, heavy gridlines, legends when a direct label would do.
  • Axes that jump without easing. Rescale smoothly so the viewer sees the change.
  • Pins or captions covering the line at its key point.

Failure modes

Looks likeCauseFix
Line jumps or flickers on renderdrawn from wall-clock time or per-frame randomnessdraw only from the clock t in onUpdate
Pin labels overflow their pillspill width guessed too smallwidth ≈ 36 + chars × 17 (× 23 for all caps) at 28 px, or measure after fonts load
Kicker and counter overlapboth positioned too closeleave 30+ px between the kicker baseline and the counter top
Surprise lands flatno rescale, no pin, no caption changestack all three within 0.5 s
Counter text wobblesproportional digitsfont-variant-numeric: tabular-nums
Contrast check fails on tickslabel colour too lightticks #5b6270 on light, #9fb0c8 on dark

Validate

npx hyperframes check
npx hyperframes snapshot --at <start, each pin, mid-rescale, end>
npx hyperframes render -o renders/<name>.mp4
  • numbers on screen match the data at those times
  • the rescale is smooth and the labels stay readable during it
  • pins and captions never cover the line's key point
  • all text inside the safe area; contrast check passes
  • the final frame states the takeaway

Self-critique before the final render

Score the snapshot sheet 1–10 on: hook (first second), readability at phone width, motion quality, composition, accuracy, and the "muted test" (can a viewer summarise it in one sentence with no sound?). Fix only what scores 7 or below, re-snapshot, and repeat until everything is 8 or above. If you can, have a separate read-only pass do the scoring, so you aren't grading your own work.

Don'tInstead
Crossfade between two busy layoutsexit the old content, then bring in the new, or carry one object across
Make several things move at oncestagger, one focus per moment
Fill pauses with floating or wobblehold still, or let the character act
Add particles, rainbow gradients or 3D flips for "energy"add a stronger event: a reveal, a hit, a camera move
Rush text to fit the timecut words

Deliver

  • Poster: the settled final chart frame, baked in as frame 0: ffmpeg -ss <t> -i renders/<name>.mp4 -frames:v 1 poster.jpg, then ffmpeg -i renders/<name>.mp4 -i poster.jpg -filter_complex "[0:v][1:v]overlay=enable='eq(n,0)'" -c:a copy renders/<name>-final.mp4.
  • A caption with the key number and the source of the data.
  • Tell the user the data beats and which numbers or pins to change for a revision.

Study these

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/phantomtonyt/motion-design-skills/data-story-charts">View data-story-charts on skillZs</a>