Skip to content

fix(producer): extract head assets from non-template sub-comps + fix postcss ESM#220

Merged
miguel-heygen merged 2 commits intomainfrom
fix/producer-postcss-esm
Apr 7, 2026
Merged

fix(producer): extract head assets from non-template sub-comps + fix postcss ESM#220
miguel-heygen merged 2 commits intomainfrom
fix/producer-postcss-esm

Conversation

@miguel-heygen
Copy link
Copy Markdown
Collaborator

@miguel-heygen miguel-heygen commented Apr 7, 2026

Summary

Two fixes in the producer:

  1. Head styles/scripts extraction: mirrors the runtime fix from PR fix(core): load head styles/scripts from non-template sub-compositions #219. The producer's inlineSubCompositions() parsed only bodyEl.innerHTML from non-template sub-compositions, discarding all <head> content.
  2. Externalize postcss: postcss is a CJS module with require("path") — bundling it into ESM output caused "Dynamic require of path is not supported" at runtime, breaking npx tsx cli render and npx tsx cli preview from the local dev build.

Verified

Re-rendered the iris-wipe composition (eval prompt #25, previously scored 1.0/5 — entirely black):

Frame Before fix After fix
0.5s Black Red background + "HELLO" text
File size 16.9 KB (all black) 64.8 KB (actual content)

Scene 1 now renders correctly. Scene 2's clip-path animation has a separate GSAP issue (the lint already warns about it via scene_layer_missing_visibility_kill).

Test plan

  • pnpm --filter @hyperframes/producer build succeeds
  • node --input-type=module -e "import './dist/index.js'" loads without error
  • Re-render iris-wipe produces visible content (64.8 KB vs 16.9 KB)
  • Frame extraction confirms red "HELLO" scene renders correctly

@miguel-heygen miguel-heygen changed the title fix(producer): externalize postcss to fix ESM dynamic require fix(producer): extract head assets from non-template sub-comps + fix postcss ESM Apr 7, 2026
Copy link
Copy Markdown
Collaborator Author

miguel-heygen commented Apr 7, 2026

Merge activity

  • Apr 7, 2:53 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Apr 7, 3:19 PM UTC: Graphite rebased this pull request as part of a merge.
  • Apr 7, 3:37 PM UTC: @miguel-heygen merged this pull request with Graphite.

@miguel-heygen miguel-heygen changed the base branch from fix/subcomp-head-styles to graphite-base/220 April 7, 2026 14:54
miguel-heygen added a commit that referenced this pull request Apr 7, 2026
#219)

## Summary

Fixes a bug where non-template sub-compositions (full HTML documents loaded via `data-composition-src`) lost all `<head>` styles and scripts. This affected **three code paths**:

1. **Runtime** (`compositionLoader.ts`) — browser preview via iframe fetch
2. **Bundler** (`htmlBundler.ts`) — studio preview HTML bundling (**this was causing the black preview**)
3. Producer fix is in PR #220

## What it fixes

**Eval prompt #25** (iris-wipe) renders entirely black in both the studio preview and rendered video because scene backgrounds (`#EF4444` red, `#3B82F6` blue), positioning, and the GSAP CDN script were all in `<head>` and silently dropped.

### Verified

Rebuilt core, started studio preview, fetched the bundled HTML from `/api/projects/iris-wipe/preview` — confirmed `#scene1 { background: #EF4444 }` and `.scene { position: absolute }` are now present in the output.

## Root cause

All three code paths did the same thing:
```js
const contentHtml = template ? template.innerHTML : bodyEl.innerHTML;
// ^ <head> content is already lost here
```

## Test plan

- [x] All 429 core tests pass
- [x] Studio preview endpoint returns correct bundled HTML with head styles included
- [x] `pnpm --filter @hyperframes/core build` succeeds

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@miguel-heygen miguel-heygen changed the base branch from graphite-base/220 to main April 7, 2026 15:17
miguel-heygen and others added 2 commits April 7, 2026 15:18
postcss is a CJS module that uses `require("path")` internally.
When esbuild bundles it into the ESM producer output, the dynamic
require call fails at runtime with "Dynamic require of path is
not supported". This broke `npx tsx cli render` and `npx tsx cli
preview` from the local dev build.

Fix: add postcss to the external list alongside puppeteer and
esbuild — it stays as a runtime dependency resolved from
node_modules instead of being bundled.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ositions

Mirrors the runtime compositionLoader fix: the producer's
inlineSubCompositions() was parsing only `bodyEl.innerHTML`,
discarding all <head> content. CSS backgrounds, positioning,
fonts, and library scripts (GSAP CDN) defined in <head> were
silently dropped during compilation.

Also externalizes postcss in the esbuild config to fix
"Dynamic require of path is not supported" error that broke
local dev rendering via `npx tsx cli render`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@miguel-heygen miguel-heygen force-pushed the fix/producer-postcss-esm branch from f1e8590 to 6cd6514 Compare April 7, 2026 15:18
@miguel-heygen miguel-heygen merged commit ef2f646 into main Apr 7, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants