@struq/skill 0.0.0-stage → 0.2.2
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/LICENSE +21 -0
- package/README.md +141 -2
- package/cli/struq.mjs +132 -0
- package/package.json +41 -4
- package/skills/struq/SKILL.md +237 -0
- package/skills/struq/cinematic/README.md +409 -0
- package/skills/struq/cinematic/checklists/01-preproduction.md +15 -0
- package/skills/struq/cinematic/checklists/02-implementation.md +17 -0
- package/skills/struq/cinematic/checklists/03-polish.md +17 -0
- package/skills/struq/cinematic/examples/code/nextjs/README.md +13 -0
- package/skills/struq/cinematic/examples/code/nextjs/app/cinematic-experience.tsx +13 -0
- package/skills/struq/cinematic/examples/code/nextjs/app/components/LenisRoot.tsx +42 -0
- package/skills/struq/cinematic/examples/code/nextjs/app/page.tsx +6 -0
- package/skills/struq/cinematic/examples/code/shared/CameraRig.tsx +65 -0
- package/skills/struq/cinematic/examples/code/shared/ExperienceCanvas.tsx +20 -0
- package/skills/struq/cinematic/examples/code/shared/ExperienceDirector.tsx +57 -0
- package/skills/struq/cinematic/examples/code/shared/ExperienceOverlay.tsx +37 -0
- package/skills/struq/cinematic/examples/code/shared/ExperiencePage.tsx +52 -0
- package/skills/struq/cinematic/examples/code/shared/GsapFrameLoop.tsx +32 -0
- package/skills/struq/cinematic/examples/code/shared/InteriorRoot.tsx +30 -0
- package/skills/struq/cinematic/examples/code/shared/README.md +20 -0
- package/skills/struq/cinematic/examples/code/shared/SubjectRig.tsx +58 -0
- package/skills/struq/cinematic/examples/code/shared/build-experience-timeline.ts +237 -0
- package/skills/struq/cinematic/examples/code/shared/direction.ts +52 -0
- package/skills/struq/cinematic/examples/code/shared/gsap-client.ts +32 -0
- package/skills/struq/cinematic/examples/code/shared/math.ts +12 -0
- package/skills/struq/cinematic/examples/code/shared/registry.ts +58 -0
- package/skills/struq/cinematic/examples/code/shared/runtime.ts +52 -0
- package/skills/struq/cinematic/examples/code/shared/styles.css +127 -0
- package/skills/struq/cinematic/examples/code/shared/useExperienceInput.ts +42 -0
- package/skills/struq/cinematic/examples/code/vite/README.md +14 -0
- package/skills/struq/cinematic/examples/code/vite/src/App.tsx +11 -0
- package/skills/struq/cinematic/examples/code/vite/src/LenisRoot.tsx +37 -0
- package/skills/struq/cinematic/examples/code/vite/src/main.tsx +9 -0
- package/skills/struq/cinematic/examples/concise/01-chapter-spec-example.md +42 -0
- package/skills/struq/cinematic/examples/concise/02-handoff-example.md +25 -0
- package/skills/struq/cinematic/examples/concise/03-audit-finding-example.md +13 -0
- package/skills/struq/cinematic/examples/verbose/01-full-experience-direction.md +687 -0
- package/skills/struq/cinematic/examples/verbose/02-full-audit-example.md +362 -0
- package/skills/struq/cinematic/references/01-core-mental-model.md +221 -0
- package/skills/struq/cinematic/references/02-vocabulary.md +384 -0
- package/skills/struq/cinematic/references/03-experience-architecture.md +302 -0
- package/skills/struq/cinematic/references/04-timeline-choreography.md +264 -0
- package/skills/struq/cinematic/references/05-handoff-contracts.md +241 -0
- package/skills/struq/cinematic/references/06-three-rig-architecture.md +286 -0
- package/skills/struq/cinematic/references/07-stack-integration.md +228 -0
- package/skills/struq/cinematic/references/08-gsap-plugin-patterns.md +218 -0
- package/skills/struq/cinematic/references/09-tuning-harness.md +202 -0
- package/skills/struq/cinematic/references/10-quality-systems.md +206 -0
- package/skills/struq/cinematic/references/11-agent-workflows.md +246 -0
- package/skills/struq/cinematic/references/12-audit-rubric.md +176 -0
- package/skills/struq/cinematic/references/13-official-docs.md +53 -0
- package/skills/struq/cinematic/templates/01-experience-brief.md +105 -0
- package/skills/struq/cinematic/templates/02-experience-contract.md +80 -0
- package/skills/struq/cinematic/templates/03-chapter-spec.md +103 -0
- package/skills/struq/cinematic/templates/04-handoff-contract.md +102 -0
- package/skills/struq/cinematic/templates/05-ownership-matrix.md +29 -0
- package/skills/struq/cinematic/templates/06-shot-presets.md +59 -0
- package/skills/struq/cinematic/templates/07-implementation-slice.md +66 -0
- package/skills/struq/cinematic/templates/08-tuning-register.md +36 -0
- package/skills/struq/cinematic/templates/09-acceptance-tests.md +57 -0
- package/skills/struq/references/anti-patterns.md +265 -0
- package/skills/struq/references/baseline-prompt.md +118 -0
- package/skills/struq/references/brand.md +143 -0
- package/skills/struq/references/brief-router.md +219 -0
- package/skills/struq/references/composition.md +191 -0
- package/skills/struq/references/depth-parallax.md +235 -0
- package/skills/struq/references/direction.md +188 -0
- package/skills/struq/references/feel-layer.md +107 -0
- package/skills/struq/references/gsap-api.md +293 -0
- package/skills/struq/references/iconography.md +255 -0
- package/skills/struq/references/imagery.md +144 -0
- package/skills/struq/references/loaders.md +287 -0
- package/skills/struq/references/micro-interactions.md +270 -0
- package/skills/struq/references/mobile-composition.md +70 -0
- package/skills/struq/references/nav-header.md +296 -0
- package/skills/struq/references/page-architecture.md +134 -0
- package/skills/struq/references/page-entrances.md +198 -0
- package/skills/struq/references/performance.md +235 -0
- package/skills/struq/references/pinning-scrub.md +341 -0
- package/skills/struq/references/pitfalls.md +290 -0
- package/skills/struq/references/route-transitions.md +281 -0
- package/skills/struq/references/scaling.md +151 -0
- package/skills/struq/references/scroll-reveals.md +280 -0
- package/skills/struq/references/seo.md +219 -0
- package/skills/struq/references/setup.md +397 -0
- package/skills/struq/references/showcase.md +87 -0
- package/skills/struq/references/stack-targets.md +78 -0
- package/skills/struq/references/struq-imagery.md +107 -0
- package/skills/struq/references/svg-motion.md +390 -0
- package/skills/struq/references/transitions.md +160 -0
- package/skills/struq/references/triage.md +71 -0
- package/skills/struq/references/typography.md +720 -0
- package/skills/struq/references/vibe-presets.md +287 -0
- package/skills/struq/references/webgl-r3f.md +274 -0
- package/skills/struq/references/webgl-scenes.md +593 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
# Vocabulary for Cinematic Web Experiences
|
|
2
|
+
|
|
3
|
+
Use these terms to make direction specific. Each definition includes the practical question it answers.
|
|
4
|
+
|
|
5
|
+
## Experience structure
|
|
6
|
+
|
|
7
|
+
### Experience thesis
|
|
8
|
+
A one-paragraph statement of what the viewer does, how the world responds, and how the emotional intensity develops. It prevents the project from becoming an effect collection.
|
|
9
|
+
|
|
10
|
+
### Persistent stage
|
|
11
|
+
A viewport-bound visual layer that remains alive while several narrative chapters manipulate its state.
|
|
12
|
+
|
|
13
|
+
### Chapter
|
|
14
|
+
A controlled interval of experience state with a purpose, local progress, key poses, interaction envelope, and handoff.
|
|
15
|
+
|
|
16
|
+
### Sequence
|
|
17
|
+
A group of related beats that produces one perceptual action, such as entering a product interior.
|
|
18
|
+
|
|
19
|
+
### Beat
|
|
20
|
+
A meaningful event the viewer can perceive: a word lands, the camera settles, a shape locks into place, or a light reveals a feature.
|
|
21
|
+
|
|
22
|
+
### Cue
|
|
23
|
+
A named timeline position or condition that starts a beat.
|
|
24
|
+
|
|
25
|
+
### Key pose
|
|
26
|
+
A deliberately authored state of camera, subject, type, lighting, and atmosphere. Timelines interpolate between key poses.
|
|
27
|
+
|
|
28
|
+
### Hold
|
|
29
|
+
An interval where major motion reduces so the viewer can understand, read, or feel the composition.
|
|
30
|
+
|
|
31
|
+
### Accent
|
|
32
|
+
A brief increase in motion, contrast, sound, scale, or deformation used to emphasize a beat.
|
|
33
|
+
|
|
34
|
+
### Anticipation
|
|
35
|
+
A preparatory motion that signals an upcoming action, such as a small pullback before a fast push-through.
|
|
36
|
+
|
|
37
|
+
### Overshoot
|
|
38
|
+
A motion passing slightly beyond its final value before resolving. It creates energy but should match the material and tone.
|
|
39
|
+
|
|
40
|
+
### Resolution
|
|
41
|
+
The settling state after a transformation or handoff.
|
|
42
|
+
|
|
43
|
+
### Scroll-distance budget
|
|
44
|
+
The physical amount of scroll allocated to a chapter or sequence, commonly expressed in viewport heights.
|
|
45
|
+
|
|
46
|
+
### Progress segmentation
|
|
47
|
+
Dividing local progress into named phase windows, for example entrance `0.00 to 0.18`, development `0.18 to 0.65`, and handoff `0.82 to 1.00`.
|
|
48
|
+
|
|
49
|
+
### Narrative density
|
|
50
|
+
The number of meaningful visual changes per unit of scroll or time. Excess density produces fatigue and weakens emphasis.
|
|
51
|
+
|
|
52
|
+
### Rhythm
|
|
53
|
+
The pattern of motion, holds, accents, and changes in intensity across the experience.
|
|
54
|
+
|
|
55
|
+
### Pacing
|
|
56
|
+
How quickly narrative information and visual transformations progress.
|
|
57
|
+
|
|
58
|
+
## Continuity and transitions
|
|
59
|
+
|
|
60
|
+
### Handoff
|
|
61
|
+
The interval in which state ownership transfers from one chapter to another.
|
|
62
|
+
|
|
63
|
+
### Handoff contract
|
|
64
|
+
The written specification for outgoing state, incoming state, shared properties, overlap, ownership, occlusion, reverse behavior, and completion.
|
|
65
|
+
|
|
66
|
+
### Bridge element
|
|
67
|
+
An object, word, line, mask, light, texture, or camera relationship that exists on both sides of a transition.
|
|
68
|
+
|
|
69
|
+
### State continuity
|
|
70
|
+
The requirement that a shared property's outgoing final state equals the incoming initial state.
|
|
71
|
+
|
|
72
|
+
### Spatial carry
|
|
73
|
+
Continuing an object's trajectory while its context changes.
|
|
74
|
+
|
|
75
|
+
### Match cut
|
|
76
|
+
Aligning shape, composition, scale, direction, or motion between outgoing and incoming states.
|
|
77
|
+
|
|
78
|
+
### Occlusion wipe
|
|
79
|
+
Passing an object or surface in front of the camera so a state change can occur behind it.
|
|
80
|
+
|
|
81
|
+
### Foreground wipe
|
|
82
|
+
Using a DOM or WebGL foreground layer to cover and reveal the viewport.
|
|
83
|
+
|
|
84
|
+
### Camera pass-through
|
|
85
|
+
Moving the camera through or extremely close to geometry to hide a scene change or create spatial continuity.
|
|
86
|
+
|
|
87
|
+
### Portal transition
|
|
88
|
+
Displaying another state or scene through a mask, aperture, material, or render target.
|
|
89
|
+
|
|
90
|
+
### Morphological handoff
|
|
91
|
+
Transforming one vector or mesh form into the principal form of the next chapter.
|
|
92
|
+
|
|
93
|
+
### Typography bridge
|
|
94
|
+
Using a word, glyph, line, or typographic block as the persistent transition object.
|
|
95
|
+
|
|
96
|
+
### Light bridge
|
|
97
|
+
Beginning the incoming chapter's lighting before its geometry or content is fully revealed.
|
|
98
|
+
|
|
99
|
+
### Texture bridge
|
|
100
|
+
Using the outgoing render or visual surface as a texture in the incoming state.
|
|
101
|
+
|
|
102
|
+
### World-space continuity
|
|
103
|
+
Maintaining an object's spatial relationship in the 3D world across a transition.
|
|
104
|
+
|
|
105
|
+
### Screen-space continuity
|
|
106
|
+
Maintaining a visual element's position or trajectory relative to the viewport, even if its world transform changes.
|
|
107
|
+
|
|
108
|
+
### Transition cover
|
|
109
|
+
A visual condition that makes a discontinuous state change invisible, such as full occlusion, motion blur, darkness, or a fast macro pass.
|
|
110
|
+
|
|
111
|
+
## Timeline language
|
|
112
|
+
|
|
113
|
+
### Master timeline
|
|
114
|
+
The high-level timeline that composes chapter and handoff timelines. It should coordinate rather than contain every raw tween.
|
|
115
|
+
|
|
116
|
+
### Chapter timeline
|
|
117
|
+
A timeline responsible for the authored state changes within one chapter.
|
|
118
|
+
|
|
119
|
+
### Handoff timeline
|
|
120
|
+
A timeline responsible specifically for ownership transfer and bridge continuity between chapters.
|
|
121
|
+
|
|
122
|
+
### Child timeline
|
|
123
|
+
A reusable timeline inserted into a parent timeline.
|
|
124
|
+
|
|
125
|
+
### Semantic label
|
|
126
|
+
A named timeline point such as `camera:commit` or `handoff:occluded`.
|
|
127
|
+
|
|
128
|
+
### Relative positioning
|
|
129
|
+
Placing a tween relative to a label or previous action instead of at an unexplained absolute time.
|
|
130
|
+
|
|
131
|
+
### Overlap
|
|
132
|
+
Starting one beat before another has fully resolved.
|
|
133
|
+
|
|
134
|
+
### Stagger
|
|
135
|
+
Offsetting related elements. A stagger should communicate reading order, direction, hierarchy, or material behavior rather than being applied by default.
|
|
136
|
+
|
|
137
|
+
### Scrub
|
|
138
|
+
Mapping scroll progress to a timeline playhead.
|
|
139
|
+
|
|
140
|
+
### Smoothing
|
|
141
|
+
Reducing abrupt changes in a signal. Lenis smoothing, ScrollTrigger scrub smoothing, and manual damping should be assigned intentionally rather than stacked without control. Pair them the way the main skill does in [`../../references/feel-layer.md`](../../references/feel-layer.md): lower the Lenis lerp, lower the scrub number, and use `scrub: true` for attached layers and a small number for floating ones.
|
|
142
|
+
|
|
143
|
+
### Easing
|
|
144
|
+
The mathematical shape of a known transition between values.
|
|
145
|
+
|
|
146
|
+
### Damping
|
|
147
|
+
Continuous convergence toward a moving target, commonly used for pointer and camera reaction.
|
|
148
|
+
|
|
149
|
+
### Dead zone
|
|
150
|
+
An input range that produces no visual response, useful for preventing jitter.
|
|
151
|
+
|
|
152
|
+
### Hysteresis
|
|
153
|
+
Different thresholds for entering and leaving a state, preventing rapid state flicker around a boundary.
|
|
154
|
+
|
|
155
|
+
### Snap point
|
|
156
|
+
A target progress or chapter state toward which the scroll position may settle.
|
|
157
|
+
|
|
158
|
+
### Critical interval
|
|
159
|
+
A phase where the authored narrative must dominate and reactive effects should attenuate.
|
|
160
|
+
|
|
161
|
+
## Camera and composition
|
|
162
|
+
|
|
163
|
+
### Blocking
|
|
164
|
+
Planning where the camera and subjects exist and how they move through space.
|
|
165
|
+
|
|
166
|
+
### Staging
|
|
167
|
+
Directing attention using composition, depth, scale, light, type, and movement.
|
|
168
|
+
|
|
169
|
+
### Establishing shot
|
|
170
|
+
A shot that gives spatial or conceptual context.
|
|
171
|
+
|
|
172
|
+
### Hero shot
|
|
173
|
+
The clearest, most iconic presentation of the principal subject.
|
|
174
|
+
|
|
175
|
+
### Insert shot
|
|
176
|
+
A focused detail shot used to reveal a feature or clue.
|
|
177
|
+
|
|
178
|
+
### Macro shot
|
|
179
|
+
An extreme close-up that emphasizes texture, material, or transition geometry.
|
|
180
|
+
|
|
181
|
+
### Resolution shot
|
|
182
|
+
The final composition that settles the chapter or experience.
|
|
183
|
+
|
|
184
|
+
### Dolly
|
|
185
|
+
Moving the camera forward or backward.
|
|
186
|
+
|
|
187
|
+
### Truck
|
|
188
|
+
Moving the camera horizontally.
|
|
189
|
+
|
|
190
|
+
### Pedestal
|
|
191
|
+
Moving the camera vertically.
|
|
192
|
+
|
|
193
|
+
### Pan
|
|
194
|
+
Rotating the camera left or right.
|
|
195
|
+
|
|
196
|
+
### Tilt
|
|
197
|
+
Rotating the camera up or down.
|
|
198
|
+
|
|
199
|
+
### Roll
|
|
200
|
+
Rotating around the camera's forward axis.
|
|
201
|
+
|
|
202
|
+
### Orbit
|
|
203
|
+
Moving around a subject while maintaining a target relationship.
|
|
204
|
+
|
|
205
|
+
### Crane move
|
|
206
|
+
A composed vertical and spatial camera movement.
|
|
207
|
+
|
|
208
|
+
### Push-in
|
|
209
|
+
A deliberate move toward the subject to increase attention or intensity.
|
|
210
|
+
|
|
211
|
+
### Pull-out
|
|
212
|
+
A move away from the subject to reveal context or release tension.
|
|
213
|
+
|
|
214
|
+
### Zoom
|
|
215
|
+
Changing focal length or field of view. It is visually different from moving the camera.
|
|
216
|
+
|
|
217
|
+
### Dolly zoom
|
|
218
|
+
Combining camera movement with an opposing field-of-view change to alter perceived depth.
|
|
219
|
+
|
|
220
|
+
### Rack focus
|
|
221
|
+
Changing focus distance between depth planes.
|
|
222
|
+
|
|
223
|
+
### Parallax reveal
|
|
224
|
+
Using relative movement between near and far layers to reveal depth or content.
|
|
225
|
+
|
|
226
|
+
### Camera target
|
|
227
|
+
The point or target rig the camera aims toward. Author it alongside position.
|
|
228
|
+
|
|
229
|
+
### Look-ahead
|
|
230
|
+
A target offset based on movement direction or velocity that anticipates where the viewer is going.
|
|
231
|
+
|
|
232
|
+
### Composition safe area
|
|
233
|
+
A screen region reserved for type, controls, or responsive cropping.
|
|
234
|
+
|
|
235
|
+
### Visual axis
|
|
236
|
+
The dominant directional line through a composition or sequence.
|
|
237
|
+
|
|
238
|
+
### Vanishing point
|
|
239
|
+
The perspective convergence point that can be used to guide camera and typography motion.
|
|
240
|
+
|
|
241
|
+
## Three.js and transform systems
|
|
242
|
+
|
|
243
|
+
### Scene graph
|
|
244
|
+
The hierarchy of objects whose local transforms combine into world transforms.
|
|
245
|
+
|
|
246
|
+
### Rig
|
|
247
|
+
A parent transform created to own one category of movement.
|
|
248
|
+
|
|
249
|
+
### Narrative rig
|
|
250
|
+
A rig controlled by authored chapter or handoff timelines.
|
|
251
|
+
|
|
252
|
+
### Interaction rig
|
|
253
|
+
A child rig controlled by pointer, hover, drag, or device input.
|
|
254
|
+
|
|
255
|
+
### Procedural rig
|
|
256
|
+
A rig controlled by elapsed time, noise, simulation, or idle animation.
|
|
257
|
+
|
|
258
|
+
### Placement rig
|
|
259
|
+
A rig used for chapter-level positioning and composition.
|
|
260
|
+
|
|
261
|
+
### Model root
|
|
262
|
+
The imported asset root. Keep authored placement separate from internal model animation whenever possible.
|
|
263
|
+
|
|
264
|
+
### Camera rig
|
|
265
|
+
A transform hierarchy that separates narrative movement, interaction, shake, and the physical camera.
|
|
266
|
+
|
|
267
|
+
### Local space
|
|
268
|
+
Coordinates relative to an object's parent.
|
|
269
|
+
|
|
270
|
+
### World space
|
|
271
|
+
Coordinates after the full scene-graph hierarchy is resolved.
|
|
272
|
+
|
|
273
|
+
### Screen space
|
|
274
|
+
Coordinates relative to the viewport.
|
|
275
|
+
|
|
276
|
+
### Anchor
|
|
277
|
+
A named transform or point used for camera targets, DOM alignment, attachments, or transitions.
|
|
278
|
+
|
|
279
|
+
### Proxy object
|
|
280
|
+
A plain JavaScript object whose numeric values are animated by GSAP and then applied to WebGL uniforms or composed state.
|
|
281
|
+
|
|
282
|
+
### Render target
|
|
283
|
+
A texture destination for rendered output, used for portals, cross-scene transitions, feedback, reflections, and compositing.
|
|
284
|
+
|
|
285
|
+
### Post-processing pass
|
|
286
|
+
A full-screen effect applied after scene rendering, such as bloom, depth of field, distortion, color grading, or grain.
|
|
287
|
+
|
|
288
|
+
### Shader uniform
|
|
289
|
+
A value passed to shader code, commonly used for time, progress, pointer, velocity, color, and transition state.
|
|
290
|
+
|
|
291
|
+
## Input and interaction
|
|
292
|
+
|
|
293
|
+
### Input ownership
|
|
294
|
+
The rule that assigns each input to a category of behavior.
|
|
295
|
+
|
|
296
|
+
### Input arbitration
|
|
297
|
+
Resolving conflicts when several inputs could affect the same experience state.
|
|
298
|
+
|
|
299
|
+
### Interaction envelope
|
|
300
|
+
The states or progress range in which an interaction is available and how its influence fades in or out.
|
|
301
|
+
|
|
302
|
+
### Interaction gating
|
|
303
|
+
Reducing or disabling an interaction during a critical narrative interval.
|
|
304
|
+
|
|
305
|
+
### Macro interaction
|
|
306
|
+
An input that changes chapter or primary state, usually scroll, click, drag, or route navigation.
|
|
307
|
+
|
|
308
|
+
### Micro interaction
|
|
309
|
+
A local response that supports feedback or tactility without changing the narrative state.
|
|
310
|
+
|
|
311
|
+
### Magnetic response
|
|
312
|
+
A controlled attraction toward a pointer or target.
|
|
313
|
+
|
|
314
|
+
### Inertial response
|
|
315
|
+
Continued movement after input changes.
|
|
316
|
+
|
|
317
|
+
### Velocity mapping
|
|
318
|
+
Converting input velocity into a visual parameter using clamping, normalization, easing, and decay.
|
|
319
|
+
|
|
320
|
+
### Intent detection
|
|
321
|
+
Distinguishing deliberate navigation from incidental input.
|
|
322
|
+
|
|
323
|
+
### Gesture lock
|
|
324
|
+
Temporarily assigning control to one direction or interaction mode after intent is detected.
|
|
325
|
+
|
|
326
|
+
## Quality and implementation
|
|
327
|
+
|
|
328
|
+
### Direction data
|
|
329
|
+
Centralized, editable values that describe shots, timings, transforms, materials, and interaction strengths.
|
|
330
|
+
|
|
331
|
+
### Tuning harness
|
|
332
|
+
Development controls used to inspect, scrub, isolate, slow, and capture experience states.
|
|
333
|
+
|
|
334
|
+
### Vertical slice
|
|
335
|
+
One complete chapter and handoff implemented across DOM, WebGL, interaction, responsive behavior, and cleanup.
|
|
336
|
+
|
|
337
|
+
### Performance tier
|
|
338
|
+
A capability category used to select effects and asset quality.
|
|
339
|
+
|
|
340
|
+
### Graceful degradation
|
|
341
|
+
Replacing an expensive mechanism while preserving the intended composition and narrative.
|
|
342
|
+
|
|
343
|
+
### Reduced-motion choreography
|
|
344
|
+
An intentionally authored version that reduces spatial travel, velocity, and parallax while retaining hierarchy and continuity.
|
|
345
|
+
|
|
346
|
+
### Frame budget
|
|
347
|
+
The available processing time per frame. At 60 Hz, the total frame duration is approximately 16.7 ms, including browser work.
|
|
348
|
+
|
|
349
|
+
### Draw call
|
|
350
|
+
A rendering submission to the GPU. Excessive draw calls can limit performance even when geometry is simple.
|
|
351
|
+
|
|
352
|
+
### Overdraw
|
|
353
|
+
Rendering multiple layers over the same pixels, common with transparent particles and full-screen post effects.
|
|
354
|
+
|
|
355
|
+
### Lifecycle cleanup
|
|
356
|
+
Killing timelines and ScrollTriggers, removing ticker callbacks and listeners, disposing WebGL resources, and restoring document state on unmount or route change.
|
|
357
|
+
|
|
358
|
+
## Better direction phrases
|
|
359
|
+
|
|
360
|
+
Replace vague wording with observable behavior.
|
|
361
|
+
|
|
362
|
+
Instead of:
|
|
363
|
+
|
|
364
|
+
> Make the hero more cinematic.
|
|
365
|
+
|
|
366
|
+
Use:
|
|
367
|
+
|
|
368
|
+
> Hold the subject in a low-contrast silhouette for the first 12% of progress. Between 0.12 and 0.28, push the camera from `heroWide` to `heroThreeQuarter`, raise the key light from 0.2 to 1.0, and reveal the title by line with an 80 ms directional stagger. Let the camera settle 150 ms before the final line reaches full opacity.
|
|
369
|
+
|
|
370
|
+
Instead of:
|
|
371
|
+
|
|
372
|
+
> Add a smooth transition.
|
|
373
|
+
|
|
374
|
+
Use:
|
|
375
|
+
|
|
376
|
+
> Use the circular product aperture as a bridge. From 0.78 to 0.90, align it to the viewport center and reduce pointer influence. From 0.86 to 1.00, dolly through the aperture while the incoming environment begins rendering behind it. Swap the environment only after the aperture covers at least 94% of the viewport.
|
|
377
|
+
|
|
378
|
+
Instead of:
|
|
379
|
+
|
|
380
|
+
> Pin every section.
|
|
381
|
+
|
|
382
|
+
Use:
|
|
383
|
+
|
|
384
|
+
> Keep the visual stage viewport-locked across chapters 1 to 4. Use semantic document regions as scroll ranges, but preserve the same canvas, camera rig, central subject, lighting hierarchy, and transition state throughout.
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# Experience Architecture
|
|
2
|
+
|
|
3
|
+
## Architectural goals
|
|
4
|
+
|
|
5
|
+
The architecture must make these operations easy:
|
|
6
|
+
|
|
7
|
+
- define a new chapter without rewriting the orchestrator,
|
|
8
|
+
- inspect the active state,
|
|
9
|
+
- scrub any chapter independently,
|
|
10
|
+
- combine narrative and reactive motion without property conflicts,
|
|
11
|
+
- reverse through a transition safely,
|
|
12
|
+
- switch responsive choreography,
|
|
13
|
+
- cleanly unmount a route,
|
|
14
|
+
- tune values without hunting through components.
|
|
15
|
+
|
|
16
|
+
A useful architecture separates **direction data**, **runtime state**, **visual systems**, and **timeline construction**.
|
|
17
|
+
|
|
18
|
+
## Suggested project structure
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
src/
|
|
22
|
+
├── app/ or routes/
|
|
23
|
+
├── experience/
|
|
24
|
+
│ ├── direction/
|
|
25
|
+
│ │ ├── chapters.ts
|
|
26
|
+
│ │ ├── shots.ts
|
|
27
|
+
│ │ ├── handoffs.ts
|
|
28
|
+
│ │ ├── motion.ts
|
|
29
|
+
│ │ └── responsive.ts
|
|
30
|
+
│ ├── runtime/
|
|
31
|
+
│ │ ├── ExperienceProvider.tsx
|
|
32
|
+
│ │ ├── experience-state.ts
|
|
33
|
+
│ │ ├── experience-registry.ts
|
|
34
|
+
│ │ ├── progress-router.ts
|
|
35
|
+
│ │ ├── input-system.ts
|
|
36
|
+
│ │ └── lifecycle.ts
|
|
37
|
+
│ ├── timelines/
|
|
38
|
+
│ │ ├── build-master-timeline.ts
|
|
39
|
+
│ │ ├── build-intro.ts
|
|
40
|
+
│ │ ├── chapters/
|
|
41
|
+
│ │ └── handoffs/
|
|
42
|
+
│ ├── stage/
|
|
43
|
+
│ │ ├── ExperienceCanvas.tsx
|
|
44
|
+
│ │ ├── CameraRig.tsx
|
|
45
|
+
│ │ ├── LightingRig.tsx
|
|
46
|
+
│ │ ├── SubjectRig.tsx
|
|
47
|
+
│ │ ├── environments/
|
|
48
|
+
│ │ └── effects/
|
|
49
|
+
│ ├── dom/
|
|
50
|
+
│ │ ├── ExperienceOverlay.tsx
|
|
51
|
+
│ │ ├── ChapterCopy.tsx
|
|
52
|
+
│ │ ├── SvgBridges.tsx
|
|
53
|
+
│ │ └── InterfaceLayer.tsx
|
|
54
|
+
│ ├── debug/
|
|
55
|
+
│ │ ├── ExperienceHUD.tsx
|
|
56
|
+
│ │ ├── TimelineScrubber.tsx
|
|
57
|
+
│ │ └── PerformancePanel.tsx
|
|
58
|
+
│ └── types.ts
|
|
59
|
+
└── styles/
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Do not enforce this tree mechanically. Preserve the separation of responsibilities even when the project uses a different naming scheme.
|
|
63
|
+
|
|
64
|
+
## Direction data
|
|
65
|
+
|
|
66
|
+
Direction data describes the intended experience without containing component logic.
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
export type ShotPreset = {
|
|
70
|
+
camera: {
|
|
71
|
+
position: [number, number, number];
|
|
72
|
+
target: [number, number, number];
|
|
73
|
+
fov: number;
|
|
74
|
+
roll?: number;
|
|
75
|
+
};
|
|
76
|
+
subject?: {
|
|
77
|
+
position: [number, number, number];
|
|
78
|
+
rotation: [number, number, number];
|
|
79
|
+
scale: number | [number, number, number];
|
|
80
|
+
};
|
|
81
|
+
focus?: {
|
|
82
|
+
distance: number;
|
|
83
|
+
aperture: number;
|
|
84
|
+
};
|
|
85
|
+
exposure?: number;
|
|
86
|
+
notes: string;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export type ChapterDirection = {
|
|
90
|
+
id: string;
|
|
91
|
+
scrollVh: number;
|
|
92
|
+
phases: Record<string, [number, number]>;
|
|
93
|
+
incomingShot: string;
|
|
94
|
+
heroShot: string;
|
|
95
|
+
outgoingShot: string;
|
|
96
|
+
interactionEnvelope: [number, number];
|
|
97
|
+
copyCues: string[];
|
|
98
|
+
bridgeToNext?: string;
|
|
99
|
+
};
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Direction data should be serializable when possible. That makes it easier to inspect, expose in controls, save presets, and let an agent update values safely.
|
|
103
|
+
|
|
104
|
+
## Runtime state
|
|
105
|
+
|
|
106
|
+
Use mutable runtime state for values that change every frame. Do not push every pointer or progress update through React state.
|
|
107
|
+
|
|
108
|
+
A simple state object can be enough:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
export type ExperienceRuntime = {
|
|
112
|
+
globalProgress: number;
|
|
113
|
+
activeChapterId: string;
|
|
114
|
+
chapterProgress: number;
|
|
115
|
+
elapsedTime: number;
|
|
116
|
+
deltaTime: number;
|
|
117
|
+
scrollVelocity: number;
|
|
118
|
+
scrollDirection: -1 | 0 | 1;
|
|
119
|
+
pointer: { x: number; y: number; speed: number };
|
|
120
|
+
transition: {
|
|
121
|
+
id: string | null;
|
|
122
|
+
progress: number;
|
|
123
|
+
phase: 'idle' | 'entering' | 'active' | 'leaving';
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
React state remains appropriate for semantic UI state, accessibility state, route state, and values that must trigger a render. Refs, external stores, or mutable objects are more appropriate for high-frequency visual values.
|
|
129
|
+
|
|
130
|
+
## Registry pattern
|
|
131
|
+
|
|
132
|
+
Timelines often need to animate objects owned by different React components. Avoid global DOM selectors and brittle imports. Use a registry of named targets.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
export type ExperienceTargets = {
|
|
136
|
+
cameraNarrativeRig?: THREE.Group;
|
|
137
|
+
cameraTarget?: THREE.Object3D;
|
|
138
|
+
subjectPlacementRig?: THREE.Group;
|
|
139
|
+
subjectMaterial?: THREE.ShaderMaterial;
|
|
140
|
+
heroTitle?: HTMLElement;
|
|
141
|
+
bridgePath?: SVGPathElement;
|
|
142
|
+
};
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Components register targets when mounted and unregister them when disposed. Timeline builders receive the registry rather than querying the entire document.
|
|
146
|
+
|
|
147
|
+
Benefits:
|
|
148
|
+
|
|
149
|
+
- clear dependencies,
|
|
150
|
+
- easier testing,
|
|
151
|
+
- fewer selector collisions,
|
|
152
|
+
- safer route cleanup,
|
|
153
|
+
- direct Three.js object animation,
|
|
154
|
+
- more useful missing-target errors.
|
|
155
|
+
|
|
156
|
+
## Progress router
|
|
157
|
+
|
|
158
|
+
The progress router converts global or scroll-based progress into local chapter and handoff progress.
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
export function rangeProgress(
|
|
162
|
+
value: number,
|
|
163
|
+
start: number,
|
|
164
|
+
end: number,
|
|
165
|
+
): number {
|
|
166
|
+
if (end <= start) return value >= end ? 1 : 0;
|
|
167
|
+
return Math.min(1, Math.max(0, (value - start) / (end - start)));
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
For large experiences, store chapter ranges centrally:
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
const narrativeRanges = {
|
|
175
|
+
arrival: [0.00, 0.18],
|
|
176
|
+
reveal: [0.18, 0.42],
|
|
177
|
+
transform: [0.42, 0.72],
|
|
178
|
+
resolve: [0.72, 1.00],
|
|
179
|
+
} as const;
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
ScrollTrigger can also own each chapter's local progress. Choose one model and document the source of truth.
|
|
183
|
+
|
|
184
|
+
### Global master mapping
|
|
185
|
+
|
|
186
|
+
Use when:
|
|
187
|
+
|
|
188
|
+
- the experience is one uninterrupted scroll narrative,
|
|
189
|
+
- many systems need a common global progress,
|
|
190
|
+
- transitions overlap deeply,
|
|
191
|
+
- a global scrubber is important.
|
|
192
|
+
|
|
193
|
+
### Per-chapter ScrollTriggers
|
|
194
|
+
|
|
195
|
+
Use when:
|
|
196
|
+
|
|
197
|
+
- chapters have independent semantic sections,
|
|
198
|
+
- lazy activation matters,
|
|
199
|
+
- chapters can be mounted separately,
|
|
200
|
+
- content height is dynamic.
|
|
201
|
+
|
|
202
|
+
A hybrid is common: per-chapter triggers feed local progress into a route-level state model.
|
|
203
|
+
|
|
204
|
+
## Timeline builder pattern
|
|
205
|
+
|
|
206
|
+
Timeline builders should be pure enough to recreate safely.
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
export function buildChapterReveal({
|
|
210
|
+
gsap,
|
|
211
|
+
targets,
|
|
212
|
+
direction,
|
|
213
|
+
}: BuildTimelineArgs) {
|
|
214
|
+
const tl = gsap.timeline({ paused: true });
|
|
215
|
+
|
|
216
|
+
tl.addLabel('chapter:enter', 0)
|
|
217
|
+
.fromTo(
|
|
218
|
+
targets.heroTitle,
|
|
219
|
+
{ autoAlpha: 0, yPercent: 120 },
|
|
220
|
+
{ autoAlpha: 1, yPercent: 0, duration: 0.18, ease: 'power3.out' },
|
|
221
|
+
'chapter:enter+=0.04',
|
|
222
|
+
)
|
|
223
|
+
.to(
|
|
224
|
+
targets.cameraNarrativeRig.position,
|
|
225
|
+
{
|
|
226
|
+
x: direction.heroShot.camera.position[0],
|
|
227
|
+
y: direction.heroShot.camera.position[1],
|
|
228
|
+
z: direction.heroShot.camera.position[2],
|
|
229
|
+
duration: 0.32,
|
|
230
|
+
ease: 'power2.inOut',
|
|
231
|
+
},
|
|
232
|
+
'chapter:enter',
|
|
233
|
+
)
|
|
234
|
+
.addLabel('subject:established', 0.32)
|
|
235
|
+
.addLabel('handoff:armed', 0.82)
|
|
236
|
+
.addLabel('chapter:resolved', 1);
|
|
237
|
+
|
|
238
|
+
return tl;
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Use a normalized timeline duration of `1` for scroll-driven chapters when that makes phase reasoning easier. For time-driven intros and route transitions, use natural seconds.
|
|
243
|
+
|
|
244
|
+
## DOM and WebGL coordination
|
|
245
|
+
|
|
246
|
+
DOM and WebGL should share semantic cues, not necessarily the same implementation layer.
|
|
247
|
+
|
|
248
|
+
Example:
|
|
249
|
+
|
|
250
|
+
```text
|
|
251
|
+
cue: subject:established
|
|
252
|
+
- camera reaches hero shot
|
|
253
|
+
- subject key light reaches 80%
|
|
254
|
+
- title line 1 settles
|
|
255
|
+
- metadata becomes interactive
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
A GSAP timeline can animate DOM and Three.js objects directly. Alternatively, it can animate proxy values consumed by R3F. Use direct animation for simple object transforms and proxy/state channels for shader values or composed effects.
|
|
259
|
+
|
|
260
|
+
## Route lifecycle
|
|
261
|
+
|
|
262
|
+
A route-level experience must define:
|
|
263
|
+
|
|
264
|
+
- when scroll is locked or unlocked,
|
|
265
|
+
- when assets are ready enough to begin,
|
|
266
|
+
- intro timeline behavior,
|
|
267
|
+
- route-leave transition,
|
|
268
|
+
- ScrollTrigger creation and refresh,
|
|
269
|
+
- Lenis start/stop behavior,
|
|
270
|
+
- history restoration,
|
|
271
|
+
- timeline and ticker cleanup,
|
|
272
|
+
- WebGL resource disposal,
|
|
273
|
+
- document class and style restoration.
|
|
274
|
+
|
|
275
|
+
A route transition should not leave the previous experience's scroll spacers, ticker functions, event listeners, or render targets alive.
|
|
276
|
+
|
|
277
|
+
## Error handling and readiness
|
|
278
|
+
|
|
279
|
+
Do not silently build timelines against missing targets. Validate the registry:
|
|
280
|
+
|
|
281
|
+
```ts
|
|
282
|
+
function requireTarget<T>(value: T | undefined, name: string): T {
|
|
283
|
+
if (!value) throw new Error(`Missing experience target: ${name}`);
|
|
284
|
+
return value;
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Create timelines only after required assets and targets are ready. For partial readiness, define which elements are optional and which are blockers.
|
|
289
|
+
|
|
290
|
+
## Architecture acceptance tests
|
|
291
|
+
|
|
292
|
+
The architecture is healthy when:
|
|
293
|
+
|
|
294
|
+
- a chapter can be scrubbed independently,
|
|
295
|
+
- a handoff can be reversed repeatedly without jumping,
|
|
296
|
+
- pointer movement cannot overwrite camera narrative movement,
|
|
297
|
+
- a mobile shot can be swapped without changing timeline logic,
|
|
298
|
+
- route unmount removes all animation and frame callbacks,
|
|
299
|
+
- tuning values are discoverable in direction files,
|
|
300
|
+
- the current chapter, cue, and owners can be inspected,
|
|
301
|
+
- disabling post-processing does not break the narrative,
|
|
302
|
+
- reduced motion retains hierarchy and continuity.
|