Skip to content

Commit 4a43da9

Browse files
authored
Merge pull request #991 from heygen-com/feat/skill-hyperframes-core
feat(skill): hyperframes core — remove prescriptive tables, bundle text-effects
2 parents 08283e7 + 8acc71b commit 4a43da9

35 files changed

Lines changed: 1617 additions & 150 deletions

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Thumbs.db
2020
# non-generated assets (logos, svgs) that should stay in the repo.
2121
docs/images/
2222

23+
videos/
24+
2325
# IDE
2426
.vscode/
2527
.idea/
@@ -74,6 +76,7 @@ examples/*
7476
!examples/k8s-jobs
7577
!examples/k8s-jobs/**
7678
packages/studio/data/
79+
7780
.desloppify/
7881
.worktrees/
7982

@@ -103,10 +106,22 @@ captures/
103106
cursor-tests/
104107
basecamp-video/
105108
launch-video*/
109+
!skills/launch-video/
106110
ab-test/
107111
compositions/
108112
video-6-2-patched/
109113
claude-design-hyperframes-video/
114+
# Per-site video work at the repo root (huly-*, raycast-*, etc.)
115+
# Anything under videos/ is already covered above, but agents sometimes write
116+
# project dirs to the repo root when iterating. Catch the common per-brand
117+
# patterns and any *-demo-N variants the *-demo/ rule above misses.
118+
huly-*/
119+
raycast-*/
120+
*-demo-*/
121+
test-runs/
122+
test-outputs/
123+
124+
# Claude Code worktrees + superpowers docs
110125
.claude/worktrees/
111126
.claude/
112127
docs/superpowers/

skills/hyperframes/SKILL.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,8 @@ Skip on small edits (fixing a color, adjusting one duration). Run on new composi
473473
- **[references/beat-direction.md](references/beat-direction.md)** — Beat planning: concept, mood, choreography verbs, rhythm templates, transition decisions, depth layers. **Always read for multi-scene compositions.**
474474
- **[references/typography.md](references/typography.md)** — Typography: font pairing, OpenType features, dark-background adjustments, font discovery script. **Always read** — every composition has text.
475475
- **[references/motion-principles.md](references/motion-principles.md)** — Motion design principles, image motion treatment, load-bearing GSAP rules. **Always read** — every composition has motion.
476-
- **[references/techniques.md](references/techniques.md)** — 11 visual techniques with code patterns: SVG drawing, Canvas 2D, CSS 3D, kinetic type, Lottie, video compositing, typing effect, variable fonts, MotionPath, velocity transitions, audio-reactive. Read when planning techniques per beat.
476+
- **[references/techniques.md](references/techniques.md)** — 13 primitive animation techniques with code patterns: SVG drawing, Canvas 2D, CSS 3D, kinetic type, Lottie, video compositing, typing, variable fonts, MotionPath, velocity transitions, audio-reactive, clip-path reveals, WebGL shaders. Adapt the patterns — don't copy-paste. (For pre-built UI templates — terminal chrome, device mockups, moodboard layouts — see `registry/blocks/`.)
477+
- **[references/html-in-canvas-patterns.md](references/html-in-canvas-patterns.md)** — HTML-in-Canvas patterns: live DOM as GPU texture via `drawElementImage` + `layoutsubtree`. Shared boilerplate + ~6 effect recipes (iPhone/MacBook mockups, liquid glass, magnetic, portal, shatter, text cursor). Use for 1–3 hero beats per video.
477478
- **[references/narration.md](references/narration.md)** — Pacing, tone, script structure, number pronunciation, opening line patterns. Read when the composition includes voiceover or TTS.
478479
- **[references/design-picker.md](references/design-picker.md)** — Create a design.md via visual picker. Read when no design.md exists and the user wants to create one.
479480
- **[visual-styles.md](visual-styles.md)** — 8 named visual styles with hex palettes, GSAP easing signatures, and shader pairings. Read when user names a style or when generating design.md.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"id": "blur-out-up",
3+
"name": "Blur Out Up",
4+
"description": "Words arrive clean and exit upward with increasing blur. The entrance is matter-of-fact; the exit dissolves into atmosphere. Asymmetric pairing — good when the line should feel like it lingers in the viewer's memory rather than getting decisively dismissed.",
5+
"target": "word",
6+
"enter": {
7+
"durationMs": 360,
8+
"staggerMs": 90,
9+
"easing": "cubic-bezier(0.22, 1, 0.36, 1)",
10+
"from": { "opacity": 0, "y": 6 },
11+
"to": { "opacity": 1, "y": 0 }
12+
},
13+
"exit": {
14+
"durationMs": 520,
15+
"staggerMs": 22,
16+
"easing": "cubic-bezier(0.22, 1, 0.36, 1)",
17+
"from": { "opacity": 1, "y": 0, "filter": "blur(0px)" },
18+
"to": { "opacity": 0, "y": -28, "filter": "blur(12px)" }
19+
},
20+
"swap": { "mode": "crossfade", "overlapMs": 200, "microDelayMs": 0 },
21+
"notes": "The 200ms overlap during swap is intentional — incoming text starts arriving while outgoing text is still mid-blur. Reads as a transition rather than a clean cut."
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"id": "bottom-up-letters",
3+
"name": "Bottom-Up Letters",
4+
"description": "Letters rise from below in a pronounced staircase. Each character takes more visual time than per-character-rise — the motion is larger, slower, and reads as confident punctuation rather than ambient build.",
5+
"target": "char",
6+
"enter": {
7+
"durationMs": 320,
8+
"staggerMs": 65,
9+
"easing": "cubic-bezier(0.18, 1, 0.32, 1)",
10+
"from": { "opacity": 0, "y": 56 },
11+
"to": { "opacity": 1, "y": 0 }
12+
},
13+
"exit": {
14+
"durationMs": 280,
15+
"staggerMs": 14,
16+
"easing": "cubic-bezier(0.7, 0, 0.84, 0)",
17+
"from": { "opacity": 1, "y": 0 },
18+
"to": { "opacity": 0, "y": -22 }
19+
},
20+
"swap": { "mode": "crossfade", "overlapMs": 80, "microDelayMs": 0 },
21+
"notes": "Pair with bold or display-weight headlines. The 65ms stagger creates an audible-feeling rhythm; works well when the headline lands on a beat marker in narration."
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"id": "depth-parallax-words",
3+
"name": "Depth Parallax Words",
4+
"description": "Per-word entrance where each word enters at a different scale and slight vertical offset, simulating depth — back words start smaller and lower, front words larger and at baseline. Reads as a 3D-feeling layered headline without needing a real Z-axis transform.",
5+
"target": "word",
6+
"enter": {
7+
"durationMs": 540,
8+
"staggerMs": 110,
9+
"easing": "cubic-bezier(0.22, 1, 0.36, 1)",
10+
"from": { "opacity": 0, "y": 18, "scale": 0.82 },
11+
"to": { "opacity": 1, "y": 0, "scale": 1 }
12+
},
13+
"exit": {
14+
"durationMs": 360,
15+
"staggerMs": 22,
16+
"easing": "cubic-bezier(0.7, 0, 0.84, 0)",
17+
"from": { "opacity": 1, "y": 0, "scale": 1 },
18+
"to": { "opacity": 0, "y": -8, "scale": 0.92 }
19+
},
20+
"swap": { "mode": "crossfade", "overlapMs": 120, "microDelayMs": 0 },
21+
"notes": "The scale + y combination is what reads as depth. Don't drop scale below 0.7 — at that point the word looks small rather than far. Keep above 0.8 for the parallax illusion to hold."
22+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"id": "fade-through",
3+
"name": "Fade Through",
4+
"description": "Material-style cross-dissolve where the old content fades out completely before the new content fades in. Different from a normal crossfade — there's a brief moment where neither is visible. Reads as a contextual swap rather than a continuous flow.",
5+
"target": "element",
6+
"enter": {
7+
"durationMs": 280,
8+
"easing": "cubic-bezier(0.2, 0, 0, 1)",
9+
"from": { "opacity": 0 },
10+
"to": { "opacity": 1 }
11+
},
12+
"exit": {
13+
"durationMs": 200,
14+
"easing": "cubic-bezier(0.4, 0, 1, 1)",
15+
"from": { "opacity": 1 },
16+
"to": { "opacity": 0 }
17+
},
18+
"swap": { "mode": "sequential", "overlapMs": -60, "microDelayMs": 0 },
19+
"notes": "The -60ms overlap is intentional: outgoing element finishes fading out, then 60ms of empty space, then incoming starts. The empty moment is what distinguishes this from a crossfade. Implementer: timeline puts the new content's enter AFTER the previous content's exit completes."
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"id": "focus-blur-resolve",
3+
"name": "Focus Blur Resolve",
4+
"description": "Heavy blur resolves to sharp clarity on entrance, returns to soft blur on exit. Reads as a camera-focus pull — the element doesn't move; it just comes into focus. Cinematic, attention-pulling.",
5+
"target": "element",
6+
"enter": {
7+
"durationMs": 580,
8+
"easing": "cubic-bezier(0.22, 1, 0.36, 1)",
9+
"from": { "opacity": 0, "filter": "blur(16px)" },
10+
"to": { "opacity": 1, "filter": "blur(0px)" }
11+
},
12+
"exit": {
13+
"durationMs": 420,
14+
"easing": "cubic-bezier(0.7, 0, 0.84, 0)",
15+
"from": { "opacity": 1, "filter": "blur(0px)" },
16+
"to": { "opacity": 0, "filter": "blur(6px)" }
17+
},
18+
"swap": { "mode": "crossfade", "overlapMs": 160, "microDelayMs": 0 },
19+
"notes": "The 16px entrance blur is heavy enough to feel like out-of-focus rather than mild softness. Don't push above 24px — at that point the text is unreadable for too long. Don't drop below 8px — at that point the effect reads as 'gently fades in,' not 'focuses.'"
20+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"id": "kinetic-center-build",
3+
"name": "Kinetic Center Build",
4+
"description": "Each word locks to its center position as the phrase builds right-to-left with a soft blur. Layout-aware — the next word arrives at the previous word's left edge while the line stays centered in frame.",
5+
"target": "word",
6+
"enter": {
7+
"durationMs": 480,
8+
"staggerMs": 220,
9+
"easing": "cubic-bezier(0.22, 1, 0.36, 1)",
10+
"from": { "opacity": 0, "x": 24, "filter": "blur(6px)" },
11+
"to": { "opacity": 1, "x": 0, "filter": "blur(0px)" }
12+
},
13+
"exit": {
14+
"durationMs": 420,
15+
"staggerMs": 40,
16+
"easing": "cubic-bezier(0.7, 0, 0.84, 0)",
17+
"from": { "opacity": 1, "y": 0, "filter": "blur(0px)" },
18+
"to": { "opacity": 0, "y": -10, "filter": "blur(6px)" }
19+
},
20+
"swap": { "mode": "crossfade", "overlapMs": 160, "microDelayMs": 0 },
21+
"layoutAware": true,
22+
"notes": "Layout-aware: the implementer must shift each word's x-position so the whole phrase stays horizontally centered as it grows. Without this, words appended to the right push the line off-center. Computed positions, not just stagger timing — read the layout-aware section of text-effects.md."
23+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"id": "line-by-line-slide",
3+
"name": "Line By Line Slide",
4+
"description": "Each line slides in from the left, exits to the right. Reads as flowing paragraph rhythm — best for multi-line body copy or quotes where the lines build sequentially. Different from mask-reveal-up in that the motion is horizontal, not masked.",
5+
"target": "line",
6+
"enter": {
7+
"durationMs": 640,
8+
"staggerMs": 110,
9+
"easing": "cubic-bezier(0.22, 1, 0.36, 1)",
10+
"from": { "opacity": 0, "x": -40 },
11+
"to": { "opacity": 1, "x": 0 }
12+
},
13+
"exit": {
14+
"durationMs": 480,
15+
"staggerMs": 60,
16+
"easing": "cubic-bezier(0.7, 0, 0.84, 0)",
17+
"from": { "opacity": 1, "x": 0 },
18+
"to": { "opacity": 0, "x": 32 }
19+
},
20+
"swap": { "mode": "crossfade", "overlapMs": 160, "microDelayMs": 0 },
21+
"notes": "Best for 2–4 lines max. Beyond that the cumulative stagger gets noticeably long (110ms × 5 lines = 550ms before the last line starts moving). For long body copy, prefer mask-reveal-up or shorten the stagger."
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"id": "mask-reveal-up",
3+
"name": "Mask Reveal Up",
4+
"description": "Each line of text reveals as a `clip-path` mask wipes upward — the text moves up into a fixed viewport. Reads as contained, intentional, and slightly magazine-like; the masked feel separates this from a plain fade.",
5+
"target": "line",
6+
"enter": {
7+
"durationMs": 580,
8+
"staggerMs": 90,
9+
"easing": "cubic-bezier(0.22, 1, 0.36, 1)",
10+
"from": { "y": 36, "clipPath": "inset(100% 0% 0% 0%)" },
11+
"to": { "y": 0, "clipPath": "inset(0% 0% 0% 0%)" }
12+
},
13+
"exit": {
14+
"durationMs": 420,
15+
"staggerMs": 40,
16+
"easing": "cubic-bezier(0.7, 0, 0.84, 0)",
17+
"from": { "y": 0, "clipPath": "inset(0% 0% 0% 0%)" },
18+
"to": { "y": -12, "clipPath": "inset(0% 0% 100% 0%)" }
19+
},
20+
"swap": { "mode": "crossfade", "overlapMs": 120, "microDelayMs": 0 },
21+
"notes": "Each `.line` element needs `overflow: hidden` on its parent so the clip-path mask reads as a window. Without that the y-translation just shows the text moving below its baseline — the masking effect is lost."
22+
}

0 commit comments

Comments
 (0)