Why is an element invisible in my HyperFrames render but fine in preview?
A render worker seeks straight to a frame and restores the authored state, not whatever the preview last showed. Elements that start hidden need their visible end state stated explicitly, and a fromTo shows its from-state before it starts.
gsap_cold_seek_hidden_fromto_missing_reveal
gsap_timeline_set_initial_hide
This is the single most common authoring mistake in HyperFrames that looks fine until you render. The mechanism is the same each time.
The mechanism
A render worker does not play your video from the start. It seeks straight to a frame, and the element's state at that frame is whatever the authored state was, adjusted by any tweens that cover that time. Your live preview plays or scrubs in order, so it carries state along: the thing that was visible a moment ago is still visible.
Anything whose result depends on when or in what order it ran can render differently.
Pattern 1: reveal the destination, not just the source
An element that starts hidden and is revealed with gsap.fromTo() must state the visible end state, not just the from vars.
// Hidden element, revealed
tl.fromTo("#card",
{ opacity: 0, y: 24 },
{ opacity: 1, y: 0, duration: 0.5 }, // state opacity: 1 explicitly
2
);
Without opacity: 1 (or autoAlpha: 1) in the destination, a cold worker restores the hidden authored state and the element can stay invisible even when the sequential preview looks correct. The lint rule is gsap_cold_seek_hidden_fromto_missing_reveal.
Pattern 2: set the hidden state outside the timeline
Do not rely on a tl.set(...) at position 0 to hide an element at the start. A zero-duration set at exactly frame 0 may not have applied yet when frame 0 renders. Use a bare gsap.set(...) outside the timeline, or author the hidden state in CSS or HTML. The lint rule is gsap_timeline_set_initial_hide.
Pattern 3: a fromTo shows its start pose early
immediateRender back-renders the from vars at every time earlier than the tween's own start. So an element you meant to appear at 3 seconds is already on screen at frame 0, wearing its start pose. Preview hides this because you scrub past frame 0 before the tween exists.
If an element must be absent before its cue, use to() plus keyframes, or a zero-duration tl.set() at the beat boundary.
Pattern 4: anything that depends on order
These all share a root cause and each has a lint rule:
- A relative tween on a property another writer is animating.
"+=50"captures its base when the tween initialises. Sequential playback initialises mid-flight, a cold worker initialises from the end state, and the same frame lands in two places. State absolute end values instead. repeatRefresh: truewith a relative value. The offset accumulates per iteration, so a worker that seeks into iteration N never did the earlier ones. UsefromTo()with absolute endpoints.- Function-valued tween vars. They receive
(index, target, targets), so the first argument is a number, not the element. Do not call an element method on it, and do not read layout from it. - Measuring the DOM in a timeline callback.
getBoundingClientRect(),getTotalLength()andgetComputedStyle()depend on the DOM state at that moment, and callbacks re-fire on every seek. Compute geometry once at build time.
Check it worked
npx hyperframes lint
npx hyperframes snapshot --at 0,3,8
snapshot seeks directly to those times, which is a much better test than scrubbing in Studio. It is not a guarantee, because a full render on a cold worker is the final word, so confirm on a draft render before you ship. If you need to prove a result bit for bit, render with --workers 1.
Scrub to the frame the renderer will draw

GenMotion previews a HyperFrames project by seeking to exact frames with the HyperFrames runtime, and the export drives the same page frame by frame. Scrub to any time in the editor and you are looking at what the renderer will capture there, which is the check that catches an element that only exists when played in sequence.
Related answers
Why does my HyperFrames render look different from the preview?
Preview and render run the same runtime, so a real difference has a specific cause: fonts, remote media, a cold-seek state problem, the wrong entry file, or a variable that never arrived. Here is how to find which.
What are the HyperFrames determinism rules, in one checklist?
Same composition, same video, every time, as long as nothing in a frame reads the clock, an unseeded random number or the network. The rules, the reason for each, and the lint codes that enforce them.
Why is my HyperFrames animation static?
If the render shows your elements frozen in their start state, HyperFrames almost certainly cannot find or seek your timeline. The timeline has to be paused and registered under the exact composition ID.
Why is my HyperFrames render black?
A black HyperFrames video almost always has one of seven causes, from rendering the wrong entry file to a video clip with no timing of its own. Here is how to tell which one you have in a few minutes.
Sources
- HyperFrames rules and anti-patterns: cold-seek visibility and seek-order safety
- HyperFrames: Deterministic Rendering
This answer as plain Markdown, for agents: /answers/hyperframes-element-hidden-in-render-but-visible-in-preview.md