gsap-animation
GSAP + Remotion integration for professional motion graphics video production. Timeline orchestration, text splitting, SVG morphing, advanced easing, and reusable effect presets.
What this skill does
## When to use
Use this skill when creating Remotion video compositions that need **GSAP's advanced animation capabilities** beyond Remotion's built-in `interpolate()` and `spring()`.
**Use GSAP when you need:**
- Complex timeline orchestration (nesting, labels, position parameters like `"-=0.5"`)
- Text splitting animation (SplitText: chars/words/lines with mask reveals)
- SVG shape morphing (MorphSVG), stroke drawing (DrawSVG), path-following (MotionPath)
- Advanced easing (CustomEase from SVG paths, RoughEase, SlowMo, CustomBounce, CustomWiggle)
- Stagger with grid, center/edges distribution
- Character scramble/decode effects (ScrambleText)
- Reusable named effects via `gsap.registerEffect()`
**Use Remotion native `interpolate()` when:**
- Simple single-property animations (fade, slide, scale) -- do NOT use GSAP for these
- Numeric counters/progress bars -- pure math, no timeline needed
- Standard easing curves
- Spring physics (`spring()`)
**GSAP Licensing:** All plugins are **100% free** since Webflow's 2024 acquisition (SplitText, MorphSVG, DrawSVG, etc.).
---
## Setup
```bash
# In a Remotion project
npm install gsap
```
```tsx
// src/gsap-setup.ts -- import once at entry point
import gsap from 'gsap';
import { SplitText } from 'gsap/SplitText';
import { MorphSVGPlugin } from 'gsap/MorphSVGPlugin';
import { DrawSVGPlugin } from 'gsap/DrawSVGPlugin';
import { MotionPathPlugin } from 'gsap/MotionPathPlugin';
import { ScrambleTextPlugin } from 'gsap/ScrambleTextPlugin';
import { CustomEase } from 'gsap/CustomEase';
import { CustomBounce } from 'gsap/CustomBounce';
import { CustomWiggle } from 'gsap/CustomWiggle';
gsap.registerPlugin(
SplitText, MorphSVGPlugin, DrawSVGPlugin, MotionPathPlugin,
ScrambleTextPlugin, CustomEase, CustomBounce, CustomWiggle,
);
export { gsap };
```
---
## Core Hook: useGSAPTimeline
The bridge between GSAP and Remotion. Creates a paused timeline, seeks it to `frame / fps` every frame.
```tsx
import { useCurrentFrame, useVideoConfig } from 'remotion';
import gsap from 'gsap';
import { useRef, useEffect } from 'react';
function useGSAPTimeline(
buildTimeline: (tl: gsap.core.Timeline, container: HTMLDivElement) => void
) {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const containerRef = useRef<HTMLDivElement>(null);
const tlRef = useRef<gsap.core.Timeline | null>(null);
useEffect(() => {
if (!containerRef.current) return;
const ctx = gsap.context(() => {
const tl = gsap.timeline({ paused: true });
buildTimeline(tl, containerRef.current!);
tlRef.current = tl;
}, containerRef);
return () => { ctx.revert(); tlRef.current = null; };
}, []);
useEffect(() => {
if (tlRef.current) tlRef.current.seek(frame / fps);
}, [frame, fps]);
return containerRef;
}
```
**For SplitText (needs font loading):**
```tsx
import { delayRender, continueRender } from 'remotion';
function useGSAPWithFonts(
buildTimeline: (tl: gsap.core.Timeline, container: HTMLDivElement) => void
) {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const containerRef = useRef<HTMLDivElement>(null);
const tlRef = useRef<gsap.core.Timeline | null>(null);
const [handle] = useState(() => delayRender());
useEffect(() => {
document.fonts.ready.then(() => {
if (!containerRef.current) return;
const ctx = gsap.context(() => {
const tl = gsap.timeline({ paused: true });
buildTimeline(tl, containerRef.current!);
tlRef.current = tl;
}, containerRef);
continueRender(handle);
return () => { ctx.revert(); };
});
}, []);
useEffect(() => {
if (tlRef.current) tlRef.current.seek(frame / fps);
}, [frame, fps]);
return containerRef;
}
```
---
## 1. Text Animations
### SplitText Reveal (chars/words/lines)
```tsx
const TextReveal: React.FC<{ text: string }> = ({ text }) => {
const containerRef = useGSAPWithFonts((tl, container) => {
const split = SplitText.create(container.querySelector('.heading')!, {
type: 'chars,words,lines', mask: 'lines',
});
tl.from(split.chars, {
y: 100, opacity: 0, duration: 0.6, stagger: 0.03, ease: 'power2.out',
});
});
return (
<AbsoluteFill style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div ref={containerRef}>
<h1 className="heading" style={{ fontSize: 80, fontWeight: 'bold' }}>{text}</h1>
</div>
</AbsoluteFill>
);
};
```
**Patterns:**
| Pattern | SplitText Config | Animation |
|---------|-----------------|-----------|
| Line reveal | `type: "lines", mask: "lines"` | `from lines: { y: "100%" }` |
| Char cascade | `type: "chars"` | `from chars: { y: 50, opacity: 0, rotationX: -90 }` |
| Word scale | `type: "words"` | `from words: { scale: 0, opacity: 0 }` |
| Char + color | `type: "chars"` | `.from(chars, { y: 50 }).to(chars, { color: "#f00" })` |
### ScrambleText (decode effect)
> **Determinism warning:** ScrambleText uses internal random character selection. Use `--concurrency=1` when rendering to guarantee frame-perfect reproducibility across renders.
```tsx
const containerRef = useGSAPTimeline((tl, container) => {
tl.to(container.querySelector('.text')!, {
duration: 2,
scrambleText: { text: 'DECODED', chars: '01', revealDelay: 0.5, speed: 0.3 },
});
});
```
**Char sets:** `"upperCase"`, `"lowerCase"`, `"upperAndLowerCase"`, `"01"`, or custom string.
### Text Highlight Box
Colored rectangles scale in behind specific words. Uses SplitText for word-level positioning, then absolutely-positioned `<div>` boxes at lower z-index.
```tsx
const TextHighlightBox: React.FC<{
text: string;
highlights: Array<{ wordIndex: number; color: string }>;
highlightDelay?: number;
highlightStagger?: number;
}> = ({ text, highlights, highlightDelay = 0.5, highlightStagger = 0.3 }) => {
const containerRef = useGSAPWithFonts((tl, container) => {
const textEl = container.querySelector('.highlight-text')!;
const split = SplitText.create(textEl, { type: 'words' });
// Entrance: words fade in
tl.from(split.words, {
y: 20, opacity: 0, duration: 0.5, stagger: 0.05, ease: 'power2.out',
});
// Highlight boxes scale in behind target words
highlights.forEach(({ wordIndex, color }, i) => {
const word = split.words[wordIndex] as HTMLElement;
if (!word) return;
const box = document.createElement('div');
Object.assign(box.style, {
position: 'absolute',
left: `${word.offsetLeft - 4}px`,
top: `${word.offsetTop - 2}px`,
width: `${word.offsetWidth + 8}px`,
height: `${word.offsetHeight + 4}px`,
background: color,
borderRadius: '4px',
zIndex: '-1',
transformOrigin: 'left center',
transform: 'scaleX(0)',
});
textEl.appendChild(box);
tl.to(box, {
scaleX: 1, duration: 0.3, ease: 'power2.out',
}, highlightDelay + i * highlightStagger);
});
});
return (
<AbsoluteFill style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div ref={containerRef}>
<p className="highlight-text" style={{
fontSize: 64, fontWeight: 'bold', color: '#fff',
position: 'relative', maxWidth: '70%', lineHeight: 1.2,
}}>{text}</p>
</div>
</AbsoluteFill>
);
};
```
**Props:** `highlights` is an array of `{ wordIndex, color }` targeting specific words (0-indexed from SplitText).
---
## 2. SVG Animations
### MorphSVG (shape morphing)
```tsx
const containerRef = useGSAPTimeline((tl, container) => {
tl.to(container.querySelector('#path')!, {
morphSVG: { shape: '#target-path', type: 'rotational', map: 'size' },
duration: 1.5, ease: 'power2.inOut',
});
});
```
| Option | Values |
|--------|--------|
| `type` | `"linear"` (default), `"rotational"` |
| `map` | `"size"`, `"position"`, `"complexity"` |
| `shapeIndex` | Integer for point Related in Image & Video
watch
IncludedWatch a video (URL or local path). Downloads with yt-dlp, extracts auto-scaled frames with ffmpeg, pulls the transcript from captions (or Whisper API fallback), and hands the result to Claude so it can answer questions about what's in the video.
physical-ai-defect-image-generation
IncludedUse when the user wants to orchestrate defect image generation, run associated setup, or handle outputs on OSMO. The Day 0 path handles cold-start with USD-to-ROI, image-edit augmentation, and AnomalyGen to create initial PCBA datasets. The Day 1 path performs inference and labeling on real images. This skill helps with first-time asset setup, creation of finetuning checkpoints, and configuring deployment. Trigger keywords: defect image generation, dig workflow, dig pipeline, defect image detection workflow, aoi pipeline, aoi anomalygen, usd2roi anomalygen, day 0 pcba, day 1 pcba, day 1 real-photo alignment, day 1 manual roi, metal surface anomaly, glass defect, anomalygen finetune, setup_pcb, setup_metal, setup_glass, setup_pretrained, dig setup, dig datasets, dig pretrained checkpoint, dig image-edit endpoint.
accelint-react-best-practices
IncludedReact performance optimization and best practices. ALWAYS use this skill when working with any React code - writing components, hooks, JSX; refactoring; optimizing re-renders, memoization, state management; reviewing for performance; fixing hydration mismatches; debugging infinite re-renders, stale closures, input focus loss, animations restarting; preventing remounting; implementing transitions, lazy initialization, effect dependencies. Even simple React tasks benefit from these patterns. Covers React 19+ (useEffectEvent, Activity, ref props). Triggers - useEffect, useState, useMemo, useCallback, memo, inline components, nested components, components inside components, re-render, performance, hydration, SSR, Next.js, useDeferredValue, combined hooks.
elevenlabs-agents
IncludedBuild conversational AI voice agents with ElevenLabs Platform using React, JavaScript, React Native, or Swift SDKs. Configure agents, tools (client/server/MCP), RAG knowledge bases, multi-voice, and Scribe real-time STT. Use when: building voice chat interfaces, implementing AI phone agents with Twilio, configuring agent workflows or tools, adding RAG knowledge bases, testing with CLI "agents as code", or troubleshooting deprecated @11labs packages, Android audio cutoff, CSP violations, dynamic variables, or WebRTC config. Keywords: ElevenLabs Agents, ElevenLabs voice agents, AI voice agents, conversational AI, @elevenlabs/react, @elevenlabs/client, @elevenlabs/react-native, @elevenlabs/elevenlabs-js, @elevenlabs/agents-cli, elevenlabs SDK, voice AI, TTS, text-to-speech, ASR, speech recognition, turn-taking model, WebRTC voice, WebSocket voice, ElevenLabs conversation, agent system prompt, agent tools, agent knowledge base, RAG voice agents, multi-voice agents, pronunciation dictionary, voice speed control, elevenlabs scribe, @11labs deprecated, Android audio cutoff, CSP violation elevenlabs, dynamic variables elevenlabs, case-sensitive tool names, webhook authentication
humanizer
IncludedHumanize AI-generated text by detecting and removing patterns typical of LLM output. Rewrites text to sound natural, specific, and human. Uses 28 pattern detectors, 560+ AI vocabulary terms across 3 tiers, and statistical analysis (burstiness, type-token ratio, readability) for comprehensive detection. Use when asked to humanize text, de-AI writing, make content sound more natural/human, review writing for AI patterns, score text for AI detection, or improve AI-generated drafts. Covers content, language, style, communication, and filler categories.
generating-mermaid-diagrams
IncludedSalesforce architecture diagrams using Mermaid with ASCII fallback. Use this skill when generating text-based diagrams for Salesforce architecture, OAuth flows, ERDs, integration sequences, or Agentforce structure. TRIGGER when: user says "diagram", "visualize", "ERD", or asks for sequence diagrams, flowcharts, class diagrams, or architecture visualizations in Mermaid. DO NOT TRIGGER when: user wants PNG/SVG image output (use generating-visual-diagrams), or asks about non-Salesforce systems.