Repository navigation
Description
Describe the bug
A composition whose root declares data-width="1080" data-height="1920" renders a 1080×1920 MP4, but content is only visible in the top 1080px; everything below y=1080 is clipped and
shows the page background.
This happens constantly with agent-authored portrait (9:16 / TikTok / Reels) videos. The creation workflows scaffold with npx hyperframes init ... --example=blank without
--resolution (e.g. skills/general-video/SKILL.md, skills/motion-graphics/SKILL.md), so the project starts at 1920×1080. The agent then switches the root data-width/data-height
to portrait but leaves the template's html, body { width: 1920px; height: 1080px; overflow: hidden; } and <meta name="viewport" content="width=1920, height=1080"> untouched. Users
have to ask the agent to "fix the cropped frames" by hand.
Why:
- Viewport and output size come from the root data attributes (producer
htmlCompiler.ts, engineframeCapture.ts) → 1080×1920. Correct. - The runtime forces
#rootto 1080×1920 (core/src/runtime/init.ts,applyCompositionSizing/applyClipLayout). Correct. - But
<body>is still 1920×1080 withoverflow: hidden, so it clips the root at y=1080.
Nothing reports it:
hyperframes linthas no rule comparing rootdata-width/data-heightwith thehtml, bodyCSS size or the meta viewport (onlyroot_missing_dimensions).hyperframes checklayout audits (canvas_overflow,panel_out_of_canvas) measure against the root rect, which the runtime already forced to the correct size, so the body clip is
invisible to them.
In the default blank template the bug is easy to miss: the centered title sits at y≈960 (just above the cut) and html/body share the same dark background, so the repro below adds a
colored root and a bottom-anchored element.
Related but different: #587 (same symptom; cause was snapshot ignoring root dimensions, already fixed).
Link to reproduction
Steps to reproduce
npx hyperframes init repro --non-interactive --example blank- Replace
index.htmlwith the file below. The only changes vs the scaffold: root set todata-width="1080" data-height="1920",#rootgiven a red background, and a green bar
anchored atbottom: 40px. Thehtml, bodyCSS and meta viewport are left as scaffolded. npx hyperframes lint→ passes, no warningnpx hyperframes render- Open the MP4
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=1920, height=1080" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html,
body {
margin: 0;
width: 1920px;
height: 1080px;
overflow: hidden;
background: #0a0a0a;
}
#root {
background: #c0392b;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-family: Inter, ui-sans-serif, system-ui, sans-serif;
}
#title { color: #f4f4f5; font-size: 72px; font-weight: 600; }
</style>
</head>
<body>
<div id="root" data-composition-id="main" data-start="0" data-duration="10"
data-width="1080" data-height="1920">
<div id="bottom" style="position:absolute;left:0;right:0;bottom:40px;height:200px;background:#27ae60"></div>
<h1 id="title" class="clip" data-start="0" data-duration="10" data-track-index="0">Title</h1>
</div>
<script>
const tl = gsap.timeline({ paused: true });
window.__timelines["main"] = tl;
tl.seek(0);
</script>
</body>
</html>Expected behavior
Either the full 1080×1920 canvas is usable (red root fills the frame, green bar visible near the bottom), or hyperframes lint warns that the root dimensions disagree with the html, body CSS size / meta viewport, with a fix hint (update both, or scaffold with init --resolution portrait).
Actual behavior
Output is 1080×1920. The red root only covers y=0–1080; the rest of the frame is the dark body background, and the green bar at bottom: 40px is not visible (clipped). lint passes
with no warning. Screenshot of a frame attached.
Environment
✓ Version 0.8.41 (latest)
✓ Node.js v24.18.0 (win32 x64)
✓ CPU 12 cores · AMD Ryzen 5 7600X 6-Core Processor @ 4691MHz
✓ Memory 31.1 GB total · 3.5 GB available
✓ Disk 977.5 GB free
✓ Frames cache C:\Users\develover\AppData\Local\Temp\hyperframes-extract-cache-u · 616.2 GB free at C:\Users\develover\AppData\Local\Temp · default
✓ Archive extractor Built into Windows
✓ Environment Native terminal
✗ whisper-cpp Not found (optional — needed for transcription)
Build with cmake: https://github.com/ggml-org/whisper.cpp#building
✗ TTS (Kokoro) Not installed (optional — local voice fallback)
pip install kokoro-onnx soundfile
✗ BGM (MusicGen) Not installed (optional — local music fallback)
pip install transformers torch soundfile numpy
✓ FFmpeg ffmpeg 9.0.1-full_build-www.gyan.dev at C:\Users\develover\AppData\Local\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-9.0.1-full_build\bin\ffmpeg.exe
✓ FFprobe ffprobe 9.0.1-full_build-www.gyan.dev at C:\Users\develover\AppData\Local\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-9.0.1-full_build\bin\ffprobe.exe
✓ Chrome cache: C:\Users\develover\.cache\puppeteer\chrome-headless-shell\win64-152.0.7977.54\chrome-headless-shell-win64\chrome-headless-shell.exe
✓ Docker Docker version 29.7.2, build a7dcaa6
✓ Docker running RunningAdditional context
Reproduced with [email protected] on Windows 11.
Proposed fix (happy to open a PR): a warning-level lint rule, e.g. root_dimensions_mismatch, in packages/lint/src/rules/core.ts next to root_missing_dimensions. It would compare
the root data-width/data-height against html, body { width/height: Npx } and <meta name="viewport" content="width=N, height=N"> on the top-level composition only (sub-composition
CSS is already scoped by the compiler). It can reuse the patterns applyResolutionPreset (cli/src/commands/init.ts) already uses to rewrite those three places together.
A complementary follow-up could pass --resolution from the brief in the workflows' init calls.
Activity
miga-heygen commentedon Sep 16, 2026
Reproduced, fix in progress.
fix(core,lint): keep html/body sized to the composition root, warn wh…
fix(core,lint): keep html/body sized to the composition root, warn wh…
chore: release v0.8.43
chore: release v0.8.43 (#4007)
feat(telemetry): add root_body_mismatch and root_body_delta_px_bucket
feat(telemetry): render output-shape, adapter, count, and environment…