Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

product-launch-video: assemble-index.mjs is not idempotent — a second run drops every approved frame video

Open Beginner friendly
#5,733 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@Dante-dan is already working on this.

Since Oct 17, 2026.

  • #5738 by @Dante-dan — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
75/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
html, typescript
Domain
backend

Research direction

Start with skills/product-launch-video/scripts/assemble-index.mjs, especially guardFrame(), hoistApprovedVideos(), and the write near line 417. Trace how the repaired frame HTML is used when building index.html, then add a regression test that assembles the same fixture twice and compares the root video count. Done when both runs preserve the approved footage and the second run does not silently produce an empty render.

Written by the indexing model from the issue text.

Description

Summary

skills/product-launch-video/scripts/assemble-index.mjs is not idempotent. The first run hoists each approved frame <video> out of its frame file and writes the frame file back with only a placeholder comment (<!-- approved frame video hoisted by assemble-index -->). A second run finds no <video> in the frame files, so it rebuilds index.html with no footage, and it exits cleanly without any error or warning.

Repro (hyperframes 0.8.163)

  1. A project with a frame compositions/frames/02-x.html that holds an approved video (data-frame-video="approved", with data-start / data-duration / data-track-index / layout attrs).
  2. Run assemble-index.mjs, and index.html has the root-level <video>. ✅
  3. Edit any frame (e.g. a caption fix) and run assemble-index.mjs again.
  4. index.html has no <video>, the frame file has only the hoist comment, and the render shows empty device frames.

Cause

guardFrame() → hoistApprovedVideos() returns the stripped HTML as repairedHtml, and the caller persists it (writeFileSync(compAbs, guard.repairedHtml), ~line 417). The hoist is meant to happen at assembly time, but it mutates the source of truth, so the operation destroys data on re-run.

Suggested fix

Either of these would work:

  • Don't write the hoist back: keep the <video> in the frame source and strip it only in the in-memory copy used for index.html (the root-dimension repair can still be persisted on its own).
  • Or make the placeholder carry the full tag (e.g. a data-hoisted <template> or an attribute-bearing comment) so a re-run can re-hoist from it.

A regression test: run assembly twice on the same fixture and assert that the <video> count in index.html is equal across runs.

Impact

Any edit-and-reassemble loop, which the review loop encourages, silently loses all footage. The only signal is a blank render, found after a full render cycle.

Dominant language
TypeScript
Stars
54.1k
Forks
4.9k
Avg merge
10h 45m
Merged PRs (30d)
654

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from heygen-com/hyperframes

All issues in heygen-com/hyperframes

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.