Repository navigation
Leading comments break motion shots of template scenes #6237
Description
Describe the bug
A valid HTML comment before a template scene makes keyframes --shot treat the scene as a standalone page. It loses the project's GSAP script and leaves the template inert, so the requested element cannot be captured. Removing only the comment makes the same command work.
This affects ordinary scene files with author notes or catalog provenance comments. It is reproducible on current main, fcec26ed5f35ad04154361bde2faa0aa3b014c45, version 0.8.193.
Minimal reproduction
In an empty project directory, create vendor/ and compositions/. Save GSAP 3.15.0 to vendor/gsap.js:
mkdir -p vendor compositions
curl -fsSL https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js -o vendor/gsap.jsindex.html:
<!doctype html><html><head><script src="vendor/gsap.js"></script></head><body>
<div data-composition-id="root" data-width="640" data-height="360" data-duration="3">
<div class="clip" data-composition-id="scene" data-composition-src="compositions/scene.html" data-start="0" data-duration="3"></div>
</div>
<script>
window.__timelines = window.__timelines || {};
window.__timelines.root = gsap.timeline({paused:true});
</script>
</body></html>compositions/scene.html:
<!-- Scene author notes -->
<template><div data-composition-id="scene" data-width="640" data-height="360" data-duration="3">
<style>#title {position:absolute;left:60px;top:80px;width:120px;height:80px;background:#ff5500;color:#fff;font:24px sans-serif;display:grid;place-items:center}</style>
<div id="title">Scene</div>
<script>
const tl = gsap.timeline({paused:true});
tl.to('#title', {x:320,duration:3,ease:'none'});
window.__timelines = window.__timelines || {};
window.__timelines.scene = tl;
</script>
</div></template>Steps to reproduce
- Run
npx hyperframes@0.8.193 keyframes compositions/scene.html --selector '#title' --shot shot.png. - Remove only
<!-- Scene author notes -->and repeat the command.
The reproduction was run with this commit's built CLI, using the same locally installed GSAP 3.15.0 distribution instead of fetching it during capture.
Expected behavior
Both runs reuse the scene's mount in index.html, load GSAP, and produce the same motion shot.
Actual behavior
With the comment, the command prints:
[StaticGuard] Invalid HyperFrame contract: Composition uses GSAP but no GSAP script is loaded.
--shot: --selector '#title' matched no element.
No shot is written. Without the comment, the shot is written. The public bundleToSingleHtml(projectDir, {entryFile: 'compositions/scene.html'}) boundary also demonstrates the cause: the commented scene's output has no root shell, retains one inert template, and has no live #title.
Environment
- Current main
fcec26ed5f35ad04154361bde2faa0aa3b014c45, HyperFrames 0.8.193 - Linux x64, Node 26.11.1, Bun 1.4.1
- Local Chromium capture, GSAP 3.15.0; no custom plugins or private media
Additional context
isTemplateEntry checks html.trimStart().startsWith('<template'). The leading comment therefore prevents readMountedSceneShell from using the existing standalone-scene shell. Core already handles leading comments when classifying full HTML documents; this template-entry check misses that behavior.
Related merged work #5401 introduced the shared entry check and fixed uncommented scene shots. #4539 handles comments before full HTML documents, a different classification path. Neither reports this template-entry case. Open/closed issues and PRs, their comments/reviews, and discussions were searched by symptom and these symbols before filing.
Activity
miguel-heygen commentedon Oct 24, 2026
Thanks for the report and the fix. Confirmed on 0.8.193 and current main: the check that decides whether a file is a template scene only looks for
<templateat the very start, so a leading comment makes the scene get bundled as a standalone page, without the project's shell and scripts. Full HTML documents already skip leading comments; template scenes do not.Reproduced with the published
@hyperframes/core@0.8.193using your project:bundleToSingleHtmlwithentryFile: "compositions/scene.html"keeps the root shell and the GSAP script for the plain scene, but with only the comment added the output has no root shell, no GSAP script and an inert<template>.#6239 is the fix to follow for this.