@editframe/create 0.43.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/index.js +16 -28
- package/dist/index.js.map +1 -1
- package/dist/skills/editframe-brand-video-generator/README.md +155 -0
- package/dist/skills/editframe-brand-video-generator/SKILL.md +207 -0
- package/dist/skills/editframe-brand-video-generator/references/brand-examples.md +178 -0
- package/dist/skills/editframe-brand-video-generator/references/color-psychology.md +227 -0
- package/dist/skills/editframe-brand-video-generator/references/composition-patterns.md +383 -0
- package/dist/skills/editframe-brand-video-generator/references/editing.md +66 -0
- package/dist/skills/editframe-brand-video-generator/references/emotional-arcs.md +496 -0
- package/dist/skills/editframe-brand-video-generator/references/genre-selection.md +135 -0
- package/dist/skills/editframe-brand-video-generator/references/transition-styles.md +611 -0
- package/dist/skills/editframe-brand-video-generator/references/typography-personalities.md +326 -0
- package/dist/skills/editframe-brand-video-generator/references/video-archetypes.md +86 -0
- package/dist/skills/editframe-brand-video-generator/references/video-fundamentals.md +169 -0
- package/dist/skills/editframe-brand-video-generator/references/visual-metaphors.md +50 -0
- package/dist/skills/editframe-composition/SKILL.md +169 -0
- package/dist/skills/editframe-composition/references/audio.md +483 -0
- package/dist/skills/editframe-composition/references/captions.md +844 -0
- package/dist/skills/editframe-composition/references/composition-model.md +73 -0
- package/dist/skills/editframe-composition/references/configuration.md +403 -0
- package/dist/skills/editframe-composition/references/css-parts.md +105 -0
- package/dist/skills/editframe-composition/references/css-variables.md +640 -0
- package/dist/skills/editframe-composition/references/entry-points.md +810 -0
- package/dist/skills/editframe-composition/references/events.md +499 -0
- package/dist/skills/editframe-composition/references/getting-started.md +259 -0
- package/dist/skills/editframe-composition/references/hooks.md +234 -0
- package/dist/skills/editframe-composition/references/image.md +241 -0
- package/dist/skills/editframe-composition/references/r3f.md +580 -0
- package/dist/skills/editframe-composition/references/render-api.md +484 -0
- package/dist/skills/editframe-composition/references/render-strategies.md +119 -0
- package/dist/skills/editframe-composition/references/render-to-video.md +1101 -0
- package/dist/skills/editframe-composition/references/scripting.md +606 -0
- package/dist/skills/editframe-composition/references/sequencing.md +116 -0
- package/dist/skills/editframe-composition/references/server-rendering.md +753 -0
- package/dist/skills/editframe-composition/references/surface.md +329 -0
- package/dist/skills/editframe-composition/references/text.md +627 -0
- package/dist/skills/editframe-composition/references/time-model.md +99 -0
- package/dist/skills/editframe-composition/references/timegroup-modes.md +102 -0
- package/dist/skills/editframe-composition/references/timegroup.md +457 -0
- package/dist/skills/editframe-composition/references/timeline-root.md +398 -0
- package/dist/skills/editframe-composition/references/transcription.md +47 -0
- package/dist/skills/editframe-composition/references/transitions.md +608 -0
- package/dist/skills/editframe-composition/references/use-media-info.md +357 -0
- package/dist/skills/editframe-composition/references/video.md +506 -0
- package/dist/skills/editframe-composition/references/waveform.md +327 -0
- package/dist/skills/editframe-editor-gui/SKILL.md +152 -0
- package/dist/skills/editframe-editor-gui/references/active-root-temporal.md +657 -0
- package/dist/skills/editframe-editor-gui/references/canvas.md +947 -0
- package/dist/skills/editframe-editor-gui/references/controls.md +366 -0
- package/dist/skills/editframe-editor-gui/references/dial.md +756 -0
- package/dist/skills/editframe-editor-gui/references/editor-toolkit.md +587 -0
- package/dist/skills/editframe-editor-gui/references/filmstrip.md +460 -0
- package/dist/skills/editframe-editor-gui/references/fit-scale.md +772 -0
- package/dist/skills/editframe-editor-gui/references/focus-overlay.md +561 -0
- package/dist/skills/editframe-editor-gui/references/hierarchy.md +544 -0
- package/dist/skills/editframe-editor-gui/references/overlay-item.md +634 -0
- package/dist/skills/editframe-editor-gui/references/overlay-layer.md +429 -0
- package/dist/skills/editframe-editor-gui/references/pan-zoom.md +568 -0
- package/dist/skills/editframe-editor-gui/references/pause.md +397 -0
- package/dist/skills/editframe-editor-gui/references/play.md +370 -0
- package/dist/skills/editframe-editor-gui/references/preview.md +391 -0
- package/dist/skills/editframe-editor-gui/references/resizable-box.md +749 -0
- package/dist/skills/editframe-editor-gui/references/scrubber.md +588 -0
- package/dist/skills/editframe-editor-gui/references/thumbnail-strip.md +566 -0
- package/dist/skills/editframe-editor-gui/references/time-display.md +492 -0
- package/dist/skills/editframe-editor-gui/references/timeline-ruler.md +489 -0
- package/dist/skills/editframe-editor-gui/references/timeline.md +604 -0
- package/dist/skills/editframe-editor-gui/references/toggle-loop.md +618 -0
- package/dist/skills/editframe-editor-gui/references/toggle-play.md +526 -0
- package/dist/skills/editframe-editor-gui/references/transform-handles.md +924 -0
- package/dist/skills/editframe-editor-gui/references/trim-handles.md +725 -0
- package/dist/skills/editframe-editor-gui/references/workbench.md +453 -0
- package/dist/skills/editframe-motion-design/SKILL.md +101 -0
- package/dist/skills/editframe-motion-design/references/0-editframe.md +299 -0
- package/dist/skills/editframe-motion-design/references/1-intent.md +201 -0
- package/dist/skills/editframe-motion-design/references/2-physics-model.md +405 -0
- package/dist/skills/editframe-motion-design/references/3-attention.md +350 -0
- package/dist/skills/editframe-motion-design/references/4-process.md +418 -0
- package/dist/skills/editframe-vite-plugin/SKILL.md +75 -0
- package/dist/skills/editframe-vite-plugin/references/file-api.md +111 -0
- package/dist/skills/editframe-vite-plugin/references/getting-started.md +96 -0
- package/dist/skills/editframe-vite-plugin/references/jit-transcoding.md +91 -0
- package/dist/skills/editframe-vite-plugin/references/local-assets.md +75 -0
- package/dist/skills/editframe-vite-plugin/references/visual-testing.md +136 -0
- package/dist/skills/editframe-webhooks/SKILL.md +126 -0
- package/dist/skills/editframe-webhooks/references/events.md +382 -0
- package/dist/skills/editframe-webhooks/references/getting-started.md +232 -0
- package/dist/skills/editframe-webhooks/references/security.md +418 -0
- package/dist/skills/editframe-webhooks/references/testing.md +409 -0
- package/dist/skills/editframe-webhooks/references/troubleshooting.md +457 -0
- package/dist/templates/html/AGENTS.md +13 -0
- package/dist/templates/react/AGENTS.md +13 -0
- package/dist/utils.js +15 -16
- package/dist/utils.js.map +1 -1
- package/package.json +2 -2
- package/tsdown.config.ts +4 -0
- package/dist/detectAgent.js +0 -89
- package/dist/detectAgent.js.map +0 -1
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Composition Patterns
|
|
3
|
+
description: Video composition patterns where motion is structural — not decorative. Each pattern includes the animation that makes it work.
|
|
4
|
+
type: reference
|
|
5
|
+
order: 3
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Composition Patterns
|
|
9
|
+
|
|
10
|
+
Each pattern below includes the motion that earns it. A pattern without motion is a layout, not a video pattern.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Word-by-Word Title Reveal
|
|
15
|
+
|
|
16
|
+
Text that builds itself word by word focuses attention on the message as it forms. Each word arriving at a slightly different moment creates rhythm that a static title cannot.
|
|
17
|
+
|
|
18
|
+
```html live
|
|
19
|
+
<ef-timegroup mode="fixed" duration="4s" class="w-[720px] h-[400px] bg-black flex items-center justify-center">
|
|
20
|
+
<ef-text
|
|
21
|
+
split="word"
|
|
22
|
+
class="text-white text-5xl font-bold text-center max-w-2xl"
|
|
23
|
+
style="animation: 0.5s word-in both; animation-delay: calc(var(--ef-word-index) * 120ms)"
|
|
24
|
+
>The fastest way to ship video</ef-text>
|
|
25
|
+
</ef-timegroup>
|
|
26
|
+
<style>
|
|
27
|
+
@keyframes word-in {
|
|
28
|
+
from { transform: translateY(20px) scale(0.92); opacity: 0; }
|
|
29
|
+
to { transform: translateY(0) scale(1); opacity: 1; }
|
|
30
|
+
}
|
|
31
|
+
</style>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**What motion adds:** Rhythm. The sequence of arrival directs reading order and emphasis. You can accelerate or decelerate the stagger to change the emotional register — tight spacing feels urgent, wide spacing feels deliberate.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Scene with Animated Entry
|
|
39
|
+
|
|
40
|
+
Every element that appears should have a reason for how it arrives. A video background with text that enters from below reads as natural and alive. The same elements placed statically read as a screenshot.
|
|
41
|
+
|
|
42
|
+
```html live
|
|
43
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[400px] bg-black">
|
|
44
|
+
<ef-video src="https://assets.editframe.com/bars-n-tone.mp4" class="absolute inset-0 size-full object-cover"></ef-video>
|
|
45
|
+
<div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
|
|
46
|
+
<ef-text class="absolute bottom-8 left-8 text-white text-4xl font-bold"
|
|
47
|
+
style="animation: 0.7s enter-up both 0.3s">Your headline here</ef-text>
|
|
48
|
+
<ef-text class="absolute bottom-8 right-8 text-white/70 text-lg"
|
|
49
|
+
style="animation: 0.5s enter-up both 0.6s">supporting context</ef-text>
|
|
50
|
+
</ef-timegroup>
|
|
51
|
+
<style>
|
|
52
|
+
@keyframes enter-up {
|
|
53
|
+
from { transform: translateY(16px); opacity: 0; }
|
|
54
|
+
to { transform: translateY(0); opacity: 1; }
|
|
55
|
+
}
|
|
56
|
+
</style>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**What motion adds:** The staggered entrances sequence the viewer's attention — headline first, then context. The delay prevents information overload at frame one.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Crossfade Sequence
|
|
64
|
+
|
|
65
|
+
Scenes that share a visual or tonal relationship crossfade naturally. The overlap period — when both scenes are simultaneously visible — is where the transition does its narrative work.
|
|
66
|
+
|
|
67
|
+
```html live
|
|
68
|
+
<ef-timegroup mode="sequence" overlap="1s" class="w-[720px] h-[400px] bg-black">
|
|
69
|
+
<ef-timegroup mode="contain" class="absolute w-full h-full"
|
|
70
|
+
style="animation: 1s fade-out var(--ef-transition-out-start) both">
|
|
71
|
+
<ef-video src="https://assets.editframe.com/bars-n-tone.mp4" sourcein="0s" sourceout="3s" class="absolute inset-0 size-full object-cover"></ef-video>
|
|
72
|
+
<ef-text class="absolute bottom-8 left-8 text-white text-3xl font-bold"
|
|
73
|
+
style="animation: 0.6s enter-up both">Before</ef-text>
|
|
74
|
+
</ef-timegroup>
|
|
75
|
+
<ef-timegroup mode="contain" class="absolute w-full h-full"
|
|
76
|
+
style="animation: 1s fade-in both">
|
|
77
|
+
<ef-video src="https://assets.editframe.com/bars-n-tone.mp4" sourcein="5s" sourceout="8s" class="absolute inset-0 size-full object-cover"></ef-video>
|
|
78
|
+
<ef-text class="absolute bottom-8 left-8 text-white text-3xl font-bold"
|
|
79
|
+
style="animation: 0.6s enter-up 0.4s both">After</ef-text>
|
|
80
|
+
</ef-timegroup>
|
|
81
|
+
</ef-timegroup>
|
|
82
|
+
<style>
|
|
83
|
+
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
|
|
84
|
+
@keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }
|
|
85
|
+
@keyframes enter-up {
|
|
86
|
+
from { transform: translateY(16px); opacity: 0; }
|
|
87
|
+
to { transform: translateY(0); opacity: 1; }
|
|
88
|
+
}
|
|
89
|
+
</style>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**What motion adds:** The overlap creates a moment of co-presence where both states are simultaneously true. Use this for before/after, problem/solution, or any narrative transition where the relationship between scenes matters.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Ken Burns (Kinetic Image)
|
|
97
|
+
|
|
98
|
+
Still photography becomes temporal through slow motion. A 0.8% scale change per second, over 8 seconds, creates a sense of time passing and attention drifting into the image.
|
|
99
|
+
|
|
100
|
+
```html live
|
|
101
|
+
<ef-timegroup mode="fixed" duration="8s" class="w-[720px] h-[400px] bg-black overflow-hidden">
|
|
102
|
+
<ef-image
|
|
103
|
+
src="https://assets.editframe.com/bars-n-tone.mp4"
|
|
104
|
+
class="absolute inset-0 size-full object-cover"
|
|
105
|
+
style="animation: 8s ken-burns both; transform-origin: center bottom"
|
|
106
|
+
></ef-image>
|
|
107
|
+
<ef-text
|
|
108
|
+
split="word"
|
|
109
|
+
class="absolute bottom-8 left-8 text-white text-4xl font-bold"
|
|
110
|
+
style="animation: 0.8s enter-up both 1s; animation-delay: calc(1s + var(--ef-word-index) * 120ms)"
|
|
111
|
+
>The place they built it</ef-text>
|
|
112
|
+
</ef-timegroup>
|
|
113
|
+
<style>
|
|
114
|
+
@keyframes ken-burns {
|
|
115
|
+
from { transform: scale(1) translate(0, 0); }
|
|
116
|
+
to { transform: scale(1.12) translate(-1%, -1%); }
|
|
117
|
+
}
|
|
118
|
+
@keyframes enter-up {
|
|
119
|
+
from { transform: translateY(16px); opacity: 0; }
|
|
120
|
+
to { transform: translateY(0); opacity: 1; }
|
|
121
|
+
}
|
|
122
|
+
</style>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**What motion adds:** Documentary weight. The imperceptible drift prevents the eye from settling, creating a sense of contemplation. The text arrives late — after the viewer has settled into the image.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Procedural Canvas (frameTask)
|
|
130
|
+
|
|
131
|
+
**CRITICAL: Canvas Completeness Requirements**
|
|
132
|
+
|
|
133
|
+
A `<canvas>` element without a complete `addFrameTask` script is a broken composition that renders nothing.
|
|
134
|
+
|
|
135
|
+
**Before including ANY canvas element:**
|
|
136
|
+
1. Write the COMPLETE script first, including the full `addFrameTask` callback with all closing braces
|
|
137
|
+
2. Verify the script is not truncated — check that it ends with `});` and `</script>`
|
|
138
|
+
3. If approaching output length limits, STOP and either: (a) simplify the canvas animation, (b) replace with CSS animation, or (c) merge the scene's content into an adjacent scene
|
|
139
|
+
4. Never leave a canvas scene with placeholder or incomplete code — delete the scene entirely rather than ship broken motion
|
|
140
|
+
5. **Output token awareness**: If you have generated more than 3,000 tokens of HTML/script content, STOP before adding any new canvas scene. Canvas scripts average 400–600 tokens. Incomplete scripts render as blank screens.
|
|
141
|
+
6. **Verification step**: Before outputting the closing `</script>` tag, confirm the `addFrameTask` callback has: (a) a complete function body, (b) closing `});` for the callback, (c) closing `});` for the addFrameTask call. **Run this verification IMMEDIATELY after writing each canvas script, before starting the next scene.** Do not batch-verify at the end—by then, output limits may already be exceeded.
|
|
142
|
+
|
|
143
|
+
**Scene 1 canvas completion rule:** Scene 1 establishes the video's visual authority. If Scene 1 contains a canvas element, its `addFrameTask` script MUST be verified complete (all closing braces, full function body) before writing ANY subsequent scene. A truncated Scene 1 canvas breaks the entire video's argument. If approaching output limits before Scene 1's canvas is complete, simplify the canvas animation or replace it with CSS animation—do not proceed to Scene 2 with incomplete Scene 1 code.
|
|
144
|
+
|
|
145
|
+
For concepts that can't be shown with video — data, systems, processes, abstractions — `addFrameTask` gives access to the canvas for per-frame generative graphics. The animation is a pure function of time, so it's fully scrubbable and renderable.
|
|
146
|
+
|
|
147
|
+
**The motion must demonstrate something true about this product that is false about competitors.** Ask: what unit does this product operate on? Show that unit moving. These examples illustrate the thinking pattern — apply the same logic to the brand you're working with:
|
|
148
|
+
|
|
149
|
+
### Brand visual vocabulary extraction
|
|
150
|
+
|
|
151
|
+
**Before generating any visual element, extract and document:**
|
|
152
|
+
1. **Typography**: The brand's actual typefaces (not system fonts). If unknown, note 'typography unverified' and use only the brand name in a neutral sans-serif.
|
|
153
|
+
2. **Product shapes**: Iconic silhouettes the audience recognizes (e.g., a specific bottle shape, packaging form, device outline). These become the visual primitives for canvas animations.
|
|
154
|
+
3. **Photography style**: The brand's tonal register (dewy/matte, warm/cool, high-contrast/soft).
|
|
155
|
+
4. **Community artifacts**: Specific touchpoints the audience would recognize (a signature mirror, a named platform, recurring phrases from their content).
|
|
156
|
+
|
|
157
|
+
**If you cannot identify at least two of these four elements, stop and ask the user before proceeding.** Generic brand colors + abstract shapes is never acceptable—even a correct hex code applied to dots or gradients fails the substitute test. Generic 'chaos' or 'frustration' imagery (tangled curves, scattered nodes, visual noise) fails the specificity test just as badly as generic solution imagery. If you cannot identify a brand-specific visual element to animate, use the brand's actual logo as the animated element.
|
|
158
|
+
|
|
159
|
+
For problem/pain scenes specifically:
|
|
160
|
+
- Do NOT use abstract representations of chaos (bezier tangles, particle explosions, visual noise)
|
|
161
|
+
- DO reference the specific predecessor products or workflows this brand replaced
|
|
162
|
+
- Example (browser-native design tool): Show filename-versioning hell ('Final_v3_FINAL_real.psd'), the email-attachment-feedback loop, or the 'someone overwrote my artboard' moment that users recognize
|
|
163
|
+
- Example (opinionated issue tracker): Show the legacy project tool's 47-field issue creation form, the 'which board is this on?' confusion across 12 open tabs, notification spam from issue references, or the exact moment a sprint ceremony produces no actionable output
|
|
164
|
+
- The test: would a user of the OLD workflow immediately recognize this as their specific pain? If the pain could apply to any tool in the category, it's not specific enough.
|
|
165
|
+
|
|
166
|
+
**For environmental/waste problem scenes:**
|
|
167
|
+
- Do NOT show abstract shapes or particles representing waste
|
|
168
|
+
- DO show recognizable objects being discarded: garment silhouettes with visible textures (fleece, denim, puffer quilting), product shapes the audience owns
|
|
169
|
+
- The visual must create discomfort, not aesthetic abstraction. A beautiful gradient with text saying 'gear ends up here' creates no emotional weight. Show the actual pile, the actual landfill texture, the actual garment being thrown away.
|
|
170
|
+
- Example (repair-first outdoor apparel brand): Show the brand's recognizable garment silhouette (the distinctive shoulder yoke, the chest pocket placement) crumpled or falling into a heap. The viewer should think 'that's my jacket.'
|
|
171
|
+
- The test: does the viewer feel a pang of recognition/guilt, or do they observe an information graphic? If the latter, the scene fails.
|
|
172
|
+
|
|
173
|
+
**CRITICAL: Visual specificity is non-negotiable.**
|
|
174
|
+
|
|
175
|
+
1. **Logo requirement**: Never use placeholder shapes (rectangles, circles, generic icons) for logos. If you cannot access the actual logo, describe it textually and leave a `<!-- TODO: Replace with actual logo SVG -->` comment. Three horizontal lines, generic app icons, or geometric approximations are prohibited.
|
|
176
|
+
|
|
177
|
+
2. **UI requirement**: For software products, canvas animations must depict recognizable UI patterns from the actual product. Research the product's distinctive interface elements: command palettes, card designs, navigation patterns, specific iconography. Generic 'keyboard keys and circles' could represent any software product.
|
|
178
|
+
|
|
179
|
+
**The substitute test**: Replace the brand name. Could this exact visual appear in a competitor's video unchanged? If yes, the visual fails and must be redesigned with brand-specific elements.
|
|
180
|
+
|
|
181
|
+
- Payments API (unified object model): the same core object threads through every product in the suite → show one object that every system touches simultaneously rather than a pipeline. Speed is generic; the shared object is the differentiator. **Name the actual objects**: PaymentIntent, Customer, Subscription, Price. Show the real field structure (`payment_intent.id`, `customer.id`) appearing identically across Checkout, Billing, Connect. Generic 'unified object' claims without the actual API vocabulary fail the specificity test—a developer should recognize their daily tooling. **Scale metrics must be earned by first showing the mechanism. Show the object flowing through checkout → risk → connect → billing in one continuous motion, THEN reveal the scale that architecture enabled. A metric stated before the architecture is demonstrated is an unsupported claim.**
|
|
182
|
+
|
|
183
|
+
**Beyond unification — what THIS payments API does differently:** Unification is table stakes. Every aggregator claims it. The canvas must show what happens INSIDE the unified layer that competitors cannot replicate:
|
|
184
|
+
- Fraud/risk: Show the risk scoring happening in real-time as the object flows — not a label, a live computation
|
|
185
|
+
- Developer experience: Show the actual CLI commands, webhook events, or dashboard UI that developers recognize as belonging to this specific API
|
|
186
|
+
- Reliability: Visualize what failover looks like at the object level — not abstract "99.99% uptime" text
|
|
187
|
+
- Growth trajectory: Show the same integration scaling from startup to enterprise without code changes
|
|
188
|
+
|
|
189
|
+
The test: swap in a competing payments brand. Would the animation still work? If yes, it's not specific enough.
|
|
190
|
+
|
|
191
|
+
**Problem-state specificity for payments APIs**: Do NOT show generic fintech pain points (payment processing, payouts, fraud detection, reporting). These describe every competitor. Instead show the specific pre-API architecture with **real field name conflicts**: Square's `transaction_id` vs PayPal's `capture_id` vs Braintree's `sale_id`—the actual naming inconsistencies developers must map between. Show the middleware translation layer: `if (provider === 'square') { id = resp.transaction_id } else if (provider === 'paypal') { id = resp.capture_id }`. The pain must be code a developer has actually written, not abstract 'different object models' language.
|
|
192
|
+
|
|
193
|
+
**Solution-state visual requirements for payments APIs**: The solution scene MUST include at least one of: (1) actual code showing the API's syntax elegance (the brand's actual SDK method calls and object names vs. competitor verbosity), (2) the distinctive Dashboard UI aesthetic (the specific card layouts, the typography, the data visualization style), (3) recognizable customer logos that this specific API powers, or (4) the branded visual identity beyond just colors (the brand's particular visual treatments, illustration style, or documentation aesthetic). Generic API response JSON or abstract 'unified platform' diagrams fail the substitute test — any payments company could use them.
|
|
194
|
+
|
|
195
|
+
- Opinionated issue tracker: issues that enter triage exit resolved — no ambiguous state, no "in review forever" → a tangled graph that snaps to a clean DAG; the removal of ambiguity *is* the product. **Content specificity requirement:** Issue titles, labels, and states shown in animations must reference the product's own domain concepts (its named workflow constructs, keyboard shortcuts, specific queue types) or show the product being used to build itself. Generic placeholder text ('API refactor', 'Dashboard bug') fails the substitute test — it could appear in any issue tracker's demo.
|
|
196
|
+
- Browser-native design tool (URL-as-file, multiplayer cursors): There are no files — just URLs. The canvas shows multiple named cursors (with real names like 'Sarah', 'Marcus') moving simultaneously on the same frame. The visual metaphor is the cursor cluster, not abstract collaboration dots. Show the actual component structure: frames nested in frames, the layers panel hierarchy, the distinctive component instance icon. Generic rectangles could be any design tool; the nested frame structure with component instances is this tool's.
|
|
197
|
+
- Backend-as-a-service built on an existing database: The differentiator is not 'unified platform' (every BaaS claims this) but that you retain full database access — row-level security policies written in standard SQL, realtime via database replication (not a proprietary protocol), queryable with any standard client. Show: a single RLS policy that replaces 200 lines of middleware, or the same table queried from browser JS, a mobile app, and a CLI simultaneously. The visual must be impossible to attribute to any competing BaaS product.
|
|
198
|
+
|
|
199
|
+
The pattern: identify the brand's core mechanic (not its marketing position), then find the simplest motion that demonstrates that mechanic in action. The motion should be impossible to misattribute to a different brand.
|
|
200
|
+
|
|
201
|
+
If you could swap the brand name and the canvas animation would still make sense, the animation is decoration.
|
|
202
|
+
|
|
203
|
+
**When showing chaos or pain, make it viscerally uncomfortable — not aesthetically pleasing.** A beautiful tangle of purple bezier curves communicates "elegant complexity." To communicate "I live in this every day and it's exhausting," the visual needs to be overwhelming: too many elements, too fast, overlapping in a way that makes the eye unable to rest. Chaos animations that look designed signal that the problem is aesthetic, not real.
|
|
204
|
+
|
|
205
|
+
**CRITICAL: Canvas animations MUST use addFrameTask, never requestAnimationFrame.** The `requestAnimationFrame` API runs on wall-clock time and will not sync with the composition timeline during rendering. All procedural animation must be driven by `ownCurrentTimeMs` from the addFrameTask callback.
|
|
206
|
+
|
|
207
|
+
**Canvas animations must evolve to match narrative phases.** A canvas that looks the same at second 1 and second 25 is not supporting the story — it's decoration. Before writing any canvas `addFrameTask`, map the narrative phases to distinct visual states:
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
Narrative phase | Time range | Canvas visual state
|
|
211
|
+
-------------------|------------|--------------------
|
|
212
|
+
Problem/isolation | 0-8s | Single element, muted, sparse
|
|
213
|
+
Transition | 8-12s | Elements begin appearing
|
|
214
|
+
Resolution/energy | 12-25s | Full activity, vibrant
|
|
215
|
+
CTA | 25-30s | Resolve to final state
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The `addFrameTask` callback receives `ownCurrentTimeMs` — use it to branch visual behavior:
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
tg.addFrameTask((info) => {
|
|
222
|
+
const { ownCurrentTimeMs, durationMs } = info;
|
|
223
|
+
const progress = ownCurrentTimeMs / durationMs;
|
|
224
|
+
|
|
225
|
+
// Phase 1: Isolation (0-27%)
|
|
226
|
+
if (progress < 0.27) {
|
|
227
|
+
// Draw single cursor, muted colors
|
|
228
|
+
}
|
|
229
|
+
// Phase 2: First companion appears (27-40%)
|
|
230
|
+
else if (progress < 0.40) {
|
|
231
|
+
// Add second cursor
|
|
232
|
+
}
|
|
233
|
+
// Phase 3: Full collaboration (40-83%)
|
|
234
|
+
else if (progress < 0.83) {
|
|
235
|
+
// All cursors active, vibrant
|
|
236
|
+
}
|
|
237
|
+
// Phase 4: Resolve (83-100%)
|
|
238
|
+
else {
|
|
239
|
+
// Settle into final composition
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Anti-pattern:** A canvas animation where all elements are present from frame 1, contradicting a narrative that claims transformation. If the text says 'you start alone,' the canvas must show alone first.
|
|
245
|
+
|
|
246
|
+
```html
|
|
247
|
+
<ef-timegroup mode="fixed" duration="6s" id="canvas-scene" class="w-[720px] h-[400px] bg-slate-900">
|
|
248
|
+
<canvas id="particles" class="absolute inset-0 size-full"></canvas>
|
|
249
|
+
<ef-text class="absolute bottom-8 left-8 text-white text-3xl font-bold"
|
|
250
|
+
style="animation: 0.6s enter-up 1s both">Energy in motion</ef-text>
|
|
251
|
+
</ef-timegroup>
|
|
252
|
+
|
|
253
|
+
<script>
|
|
254
|
+
const tg = document.getElementById('canvas-scene');
|
|
255
|
+
const canvas = document.getElementById('particles');
|
|
256
|
+
const ctx = canvas.getContext('2d');
|
|
257
|
+
|
|
258
|
+
tg.addFrameTask((info) => {
|
|
259
|
+
const { ownCurrentTimeMs, durationMs } = info;
|
|
260
|
+
canvas.width = canvas.offsetWidth;
|
|
261
|
+
canvas.height = canvas.offsetHeight;
|
|
262
|
+
const progress = ownCurrentTimeMs / durationMs;
|
|
263
|
+
|
|
264
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
265
|
+
|
|
266
|
+
// 80 particles whose speed and radius scale with progress
|
|
267
|
+
for (let i = 0; i < 80; i++) {
|
|
268
|
+
const seed = i * 137.5;
|
|
269
|
+
const x = (Math.sin(seed + ownCurrentTimeMs * 0.0008) * 0.5 + 0.5) * canvas.width;
|
|
270
|
+
const y = (Math.cos(seed * 0.7 + ownCurrentTimeMs * 0.0006) * 0.5 + 0.5) * canvas.height;
|
|
271
|
+
const r = 2 + Math.sin(seed + progress * Math.PI) * 2;
|
|
272
|
+
const alpha = 0.3 + progress * 0.5;
|
|
273
|
+
|
|
274
|
+
ctx.beginPath();
|
|
275
|
+
ctx.arc(x, y, r, 0, Math.PI * 2);
|
|
276
|
+
ctx.fillStyle = `rgba(99, 179, 237, ${alpha})`;
|
|
277
|
+
ctx.fill();
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
</script>
|
|
281
|
+
<style>
|
|
282
|
+
@keyframes enter-up {
|
|
283
|
+
from { transform: translateY(16px); opacity: 0; }
|
|
284
|
+
to { transform: translateY(0); opacity: 1; }
|
|
285
|
+
}
|
|
286
|
+
</style>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
**What motion adds:** The particle system is the argument. The concept being communicated — energy, activity, distributed processing, whatever — is visible in the form of the animation, not just stated in text over a stock video.
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## Progress-Driven Animation
|
|
294
|
+
|
|
295
|
+
`--ef-progress` is a CSS variable that holds the current playback progress (0–1) for any timegroup. It updates every frame. This makes it possible to drive any CSS property as a pure function of time — without keyframes.
|
|
296
|
+
|
|
297
|
+
```html live
|
|
298
|
+
<ef-timegroup mode="fixed" duration="5s" class="w-[720px] h-[200px] bg-slate-900 flex flex-col items-center justify-center gap-4 p-8">
|
|
299
|
+
<div class="w-full bg-slate-700 rounded-full h-3 overflow-hidden">
|
|
300
|
+
<div class="h-full bg-blue-400 rounded-full transition-none"
|
|
301
|
+
style="width: calc(var(--ef-progress) * 100%)"></div>
|
|
302
|
+
</div>
|
|
303
|
+
<ef-text class="text-white text-2xl">Processing your request</ef-text>
|
|
304
|
+
</ef-timegroup>
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**What motion adds:** The progress bar is not decorating a static message — it is the message. The viewer watches time pass as a spatial event. Any numeric or proportional concept can be represented this way.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Persistent Background with Entering Foreground
|
|
312
|
+
|
|
313
|
+
A continuous background (music, ambient video, or canvas) while foreground content animates in and out creates the feeling of a coherent world being revealed in stages, rather than a series of disconnected slides.
|
|
314
|
+
|
|
315
|
+
```html
|
|
316
|
+
<ef-timegroup mode="fixed" duration="15s" class="absolute w-full h-full">
|
|
317
|
+
<ef-video src="background.mp4" class="absolute inset-0 size-full object-cover opacity-60"></ef-video>
|
|
318
|
+
<ef-audio src="music.mp3" volume="0.2"></ef-audio>
|
|
319
|
+
|
|
320
|
+
<ef-timegroup mode="sequence" class="absolute inset-0">
|
|
321
|
+
<ef-timegroup mode="fixed" duration="4s" class="absolute inset-0 flex items-center justify-center"
|
|
322
|
+
style="animation: 0.5s fade-in both, 0.5s fade-out var(--ef-transition-out-start) both">
|
|
323
|
+
<ef-text split="word" class="text-white text-5xl font-bold text-center"
|
|
324
|
+
style="animation: 0.5s enter-up both; animation-delay: calc(var(--ef-word-index) * 80ms)">
|
|
325
|
+
One thing at a time
|
|
326
|
+
</ef-text>
|
|
327
|
+
</ef-timegroup>
|
|
328
|
+
<ef-timegroup mode="fixed" duration="4s" class="absolute inset-0 flex items-center justify-center"
|
|
329
|
+
style="animation: 0.5s fade-in both, 0.5s fade-out var(--ef-transition-out-start) both">
|
|
330
|
+
<ef-text split="word" class="text-white text-5xl font-bold text-center"
|
|
331
|
+
style="animation: 0.5s enter-up both; animation-delay: calc(var(--ef-word-index) * 80ms)">
|
|
332
|
+
Each idea earns its place
|
|
333
|
+
</ef-text>
|
|
334
|
+
</ef-timegroup>
|
|
335
|
+
</ef-timegroup>
|
|
336
|
+
</ef-timegroup>
|
|
337
|
+
<style>
|
|
338
|
+
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
|
|
339
|
+
@keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }
|
|
340
|
+
@keyframes enter-up {
|
|
341
|
+
from { transform: translateY(20px); opacity: 0; }
|
|
342
|
+
to { transform: translateY(0); opacity: 1; }
|
|
343
|
+
}
|
|
344
|
+
</style>
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**What motion adds:** The continuous background creates continuity. The foreground entrances and exits create rhythm. Together they produce a sense of a video that lives in one world, not a sequence of separate moments.
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## Visual Language Consistency
|
|
352
|
+
|
|
353
|
+
Once you establish a visual technique (canvas animations, a particular motion style, a color treatment), maintain it through the final scene. Reverting to simpler techniques at the end breaks the viewer's engagement at the moment it should peak.
|
|
354
|
+
|
|
355
|
+
**Anti-pattern:** Three scenes of sophisticated canvas animation followed by a final scene with static text and basic CSS fades. The CTA scene should be a culmination, not a retreat.
|
|
356
|
+
|
|
357
|
+
**Better:** If scenes 1-3 use orbital particle systems, Scene 4 should show those particles converging into the logo or final message. The motion vocabulary established early must resolve, not disappear.
|
|
358
|
+
|
|
359
|
+
```html
|
|
360
|
+
<!-- Wrong: Canvas scenes → static text CTA -->
|
|
361
|
+
<ef-timegroup mode="fixed" duration="7s">
|
|
362
|
+
<ef-text class="text-6xl">Design together</ef-text> <!-- Breaks visual momentum -->
|
|
363
|
+
</ef-timegroup>
|
|
364
|
+
|
|
365
|
+
<!-- Right: Canvas animation continues through CTA -->
|
|
366
|
+
<ef-timegroup mode="fixed" duration="7s" id="finale">
|
|
367
|
+
<canvas id="finale-canvas" class="absolute inset-0"></canvas>
|
|
368
|
+
<ef-text class="absolute bottom-8 text-4xl">Design together</ef-text>
|
|
369
|
+
</ef-timegroup>
|
|
370
|
+
<script>
|
|
371
|
+
// Particles from previous scene converge into logo position
|
|
372
|
+
</script>
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Further Reading
|
|
378
|
+
|
|
379
|
+
- [css-variables.md](../composition/references/css-variables.md) — `--ef-progress`, `--ef-duration`, `--ef-transition-*`
|
|
380
|
+
- [scripting.md](../composition/references/scripting.md) — `addFrameTask` and canvas access
|
|
381
|
+
- [text.md](../composition/references/text.md) — `split`, `--ef-word-index`, `--ef-stagger-offset`, `--ef-seed`
|
|
382
|
+
- [transitions.md](../composition/references/transitions.md) — slide, zoom, dissolve between scenes
|
|
383
|
+
- [editing.md](editing.md) — what to cut and when to stop
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Editing — What to Cut
|
|
3
|
+
description: How to recognize when a scene is not doing work, when a video is complete versus merely finished, and the discipline of omission.
|
|
4
|
+
type: explanation
|
|
5
|
+
order: 5
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Editing — What to Cut
|
|
9
|
+
|
|
10
|
+
Adding scenes is easy. Knowing when to stop, and what to remove, is the actual craft.
|
|
11
|
+
|
|
12
|
+
## The Test for Every Scene
|
|
13
|
+
|
|
14
|
+
A scene earns its place if it changes the viewer's state — what they feel, believe, or know — in a way that the video requires.
|
|
15
|
+
|
|
16
|
+
Ask: **If this scene were removed, what would the viewer miss?**
|
|
17
|
+
|
|
18
|
+
Not "what information would be absent" — information can be stated more efficiently. What *experience* would be absent? What shift in feeling or understanding would not happen?
|
|
19
|
+
|
|
20
|
+
If the answer is "nothing essential," cut the scene.
|
|
21
|
+
|
|
22
|
+
## When a Scene Is Not Working
|
|
23
|
+
|
|
24
|
+
**It restates what the previous scene already established.** Two scenes that leave the viewer in the same emotional state are one scene too many. The second one is emphasizing, not progressing.
|
|
25
|
+
|
|
26
|
+
**It exists to include information, not to change state.** "We serve enterprise customers in 40 countries" is information. It can be a caption, a subtitle, a title card at the end. It does not need to be a scene. If the information doesn't require time to land — if it can be understood in a glance — it doesn't justify a scene.
|
|
27
|
+
|
|
28
|
+
**It fills time rather than using it.** A scene that holds for 4 seconds because "it needs to be readable" but could be cut to 2 without losing comprehension is 2 seconds of hollow. Duration should be earned by what's happening, not assigned by convention.
|
|
29
|
+
|
|
30
|
+
**The motion is decorative.** If you can describe a scene as "logo fades in, holds, fades out" — and the fades exist because videos have fades, not because the fading communicates anything — the motion is decoration. Either give the motion meaning or remove it.
|
|
31
|
+
|
|
32
|
+
## The Compression Test
|
|
33
|
+
|
|
34
|
+
Cut the draft to half its duration. Not in detail — just in structure. Which scenes survive? Those are the video. The rest are padding you added because you were afraid of leaving something out.
|
|
35
|
+
|
|
36
|
+
This doesn't mean the final video is half as long. It means: when you can't cut any further without losing something real, you've found what the video actually is.
|
|
37
|
+
|
|
38
|
+
## Signs You're Done
|
|
39
|
+
|
|
40
|
+
- Removing any remaining scene would leave a gap the viewer would feel
|
|
41
|
+
- Every motion exists because it adds information or changes the viewer's state, not because videos have motion
|
|
42
|
+
- The first scene creates a condition that the last scene resolves — there's an arc, not just a sequence
|
|
43
|
+
- You've watched it 5 times and nothing is invisible — meaning nothing is wasted
|
|
44
|
+
|
|
45
|
+
## Signs You're Not Done
|
|
46
|
+
|
|
47
|
+
- You have scenes you're keeping "just to be safe"
|
|
48
|
+
- Any two adjacent scenes leave the viewer in the same emotional state
|
|
49
|
+
- The video makes sense if you watch it with the sound off and the text replaced with placeholders — this means the form is generic
|
|
50
|
+
- You can't say what the viewer should feel at the final frame that they didn't feel at the first frame
|
|
51
|
+
|
|
52
|
+
## What Omission Creates
|
|
53
|
+
|
|
54
|
+
Every gap you create — a cut that arrives sooner than expected, a title that doesn't fully spell out the implication, a scene that ends before the thought is completed — requires the viewer to participate. Viewers who participate remember what they made. Viewers who are shown everything are passive.
|
|
55
|
+
|
|
56
|
+
The hollow feeling in videos that have everything is often the absence of anything left for the viewer to complete.
|
|
57
|
+
|
|
58
|
+
Leave something out on purpose. Not confusion — gap. The difference: confusion means missing information. A gap means the viewer arrives at the conclusion through their own momentum.
|
|
59
|
+
|
|
60
|
+
## The One-Sentence Test
|
|
61
|
+
|
|
62
|
+
Before finalizing, complete this sentence:
|
|
63
|
+
|
|
64
|
+
> "This video exists because __________, and without it, the viewer would never ____________."
|
|
65
|
+
|
|
66
|
+
Both blanks must be specific and non-transferable. If either can be completed with generic language that would apply to any brand video, the video is not done yet — or not necessary.
|