chore: import upstream snapshot with attribution
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
---
|
||||
title: Contributing to the Catalog
|
||||
description: How to add blocks and components to the HyperFrames registry.
|
||||
---
|
||||
|
||||
Your agent already knows how to build video components. It writes HTML. HyperFrames renders it. The registry is the collection of everything that's been built — 52 blocks and counting.
|
||||
|
||||
This guide shows you how to add to it.
|
||||
|
||||
<Info>
|
||||
**Quick version** — Fork the repo. Write one HTML file with a paused GSAP timeline. Add `registry-item.json`. Run `hyperframes lint` + `validate`. Publish with `npx hyperframes publish`. Open a PR.
|
||||
</Info>
|
||||
|
||||
## Why Contribute?
|
||||
|
||||
Every block in the registry exists because someone needed it and built it. When you add a block, every HyperFrames user gets it with one command:
|
||||
|
||||
```bash
|
||||
npx hyperframes add instagram-follow
|
||||
```
|
||||
|
||||
The registry grows, HyperFrames gets more useful, and your work ships to everyone.
|
||||
|
||||
## Two Paths
|
||||
|
||||
### Ideas (No Code)
|
||||
|
||||
You spot visual trends before anyone. That's the most valuable contribution.
|
||||
|
||||
- Screen-record a caption style from TikTok/YouTube that doesn't exist yet
|
||||
- Sketch a lower-third in Figma with fonts, colors, and timing
|
||||
- Install a component, preview it, report what feels off
|
||||
|
||||
Open an issue on [GitHub](https://github.com/heygen-com/hyperframes/issues) with a visual reference. Tag it `component-request`.
|
||||
|
||||
<Tip>The bar for ideas is low. We'd rather have 100 and build the best 10.</Tip>
|
||||
|
||||
### Build It
|
||||
|
||||
Every block is a single HTML file. No build step, no framework.
|
||||
|
||||
If you use Claude Code with HyperFrames skills:
|
||||
|
||||
> "I want to contribute a new transition that looks like \[description\]"
|
||||
|
||||
The `/hyperframes-registry` skill scaffolds the structure, validates, renders a preview, publishes to [hyperframes.dev](https://hyperframes.dev), and prepares the PR.
|
||||
|
||||
## What Goes in the Registry
|
||||
|
||||
**Blocks** (`registry/blocks/`) — full standalone compositions. Fixed dimensions, fixed duration. Caption styles, VFX effects, title cards, transitions.
|
||||
|
||||
**Components** (`registry/components/`) — reusable snippets. No fixed size. CSS effects, text treatments, overlays that adapt to any composition.
|
||||
|
||||
### Structure
|
||||
|
||||
```
|
||||
registry/blocks/my-block/
|
||||
my-block.html ← the composition
|
||||
registry-item.json ← metadata
|
||||
```
|
||||
|
||||
### registry-item.json
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://hyperframes.heygen.com/schema/registry-item.json",
|
||||
"name": "my-block",
|
||||
"type": "hyperframes:block",
|
||||
"title": "My Block",
|
||||
"description": "What this block does in one sentence",
|
||||
"tags": ["category", "subcategory"],
|
||||
"dimensions": { "width": 1920, "height": 1080 },
|
||||
"duration": 5,
|
||||
"files": [
|
||||
{
|
||||
"path": "my-block.html",
|
||||
"target": "compositions/my-block.html",
|
||||
"type": "hyperframes:composition"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## The Rules
|
||||
|
||||
Five things that must be true for every registry item:
|
||||
|
||||
<Steps>
|
||||
<Step title="Deterministic">
|
||||
No `Math.random()`, no `Date.now()`. Use seeded PRNG only.
|
||||
</Step>
|
||||
<Step title="Paused timeline">
|
||||
`gsap.timeline({ paused: true })`. The player controls playback.
|
||||
</Step>
|
||||
<Step title="Register timeline">
|
||||
`window.__timelines["id"]` must match `data-composition-id`.
|
||||
</Step>
|
||||
<Step title="No requestAnimationFrame">
|
||||
Use `tl.eventCallback("onUpdate", render)` for Three.js/WebGL scenes.
|
||||
</Step>
|
||||
<Step title="Hard kills on captions">
|
||||
`tl.set(el, { opacity: 0, visibility: "hidden" }, group.end)` — no lingering text.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
Break any of these and renders won't be reproducible. The renderer captures every frame by seeking the timeline — if your animation depends on real time or random state, it breaks.
|
||||
</Warning>
|
||||
|
||||
## Quality Bar
|
||||
|
||||
Not everything belongs in the registry. The bar is production quality.
|
||||
|
||||
| Type | Minimum standard |
|
||||
|------|-----------------|
|
||||
| Captions | 96px+ font, text-stroke/shadow, overflow prevention |
|
||||
| VFX | Solves a problem that takes 4+ hours from scratch |
|
||||
| Transitions | Smoother than CSS — if opacity 0→1 works, it's not a transition |
|
||||
| Blocks | Would a professional use this in a client project? |
|
||||
|
||||
### Common rejection reasons
|
||||
|
||||
1. **"Looks like a demo"** — a spinning cube is not a component
|
||||
2. **"Text unreadable"** — font too small, no contrast treatment
|
||||
3. **"Non-deterministic"** — `Math.random()` or `Date.now()`
|
||||
4. **"Timeline not found"** — ID mismatch between HTML and JS
|
||||
5. **"Breaks as sub-composition"** — element IDs collide (prefix everything)
|
||||
|
||||
## Workflow
|
||||
|
||||
<Steps>
|
||||
<Step title="Fork and create">
|
||||
Fork [heygen-com/hyperframes](https://github.com/heygen-com/hyperframes) and create your block directory:
|
||||
```bash
|
||||
mkdir -p registry/blocks/your-block
|
||||
```
|
||||
</Step>
|
||||
<Step title="Write your block">
|
||||
Create the HTML composition and `registry-item.json`. Use the templates above.
|
||||
</Step>
|
||||
<Step title="Validate">
|
||||
```bash
|
||||
hyperframes lint
|
||||
hyperframes check
|
||||
npx oxfmt your-block.html
|
||||
```
|
||||
</Step>
|
||||
<Step title="Update registry">
|
||||
```bash
|
||||
# Add to registry index
|
||||
# Update registry/registry.json
|
||||
npx tsx scripts/generate-catalog-pages.ts
|
||||
```
|
||||
</Step>
|
||||
<Step title="Render preview">
|
||||
```bash
|
||||
hyperframes render -o preview.mp4
|
||||
```
|
||||
</Step>
|
||||
<Step title="Publish and PR">
|
||||
```bash
|
||||
npx hyperframes publish
|
||||
```
|
||||
Open a PR with your [hyperframes.dev](https://hyperframes.dev) preview link.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
**External contributors:** attach the preview MP4 to your PR. A maintainer handles the catalog image.
|
||||
|
||||
**HeyGen internal:** run `scripts/upload-docs-images.sh` to push catalog PNGs.
|
||||
|
||||
## What's Needed Right Now
|
||||
|
||||
These are gaps in the registry. If you're looking for something to build, start here.
|
||||
|
||||
| Category | Gap | Difficulty |
|
||||
|----------|-----|-----------|
|
||||
| Captions | Karaoke with clip-path sweep (CapCut style) | Medium |
|
||||
| Captions | RTL language layouts (Arabic, Hebrew) | Medium |
|
||||
| Lower thirds | 10 variations for podcasts/interviews | Easy |
|
||||
| Lower thirds | News ticker / scrolling text bar | Easy |
|
||||
| Maps | Animated route maps, region highlights, location pins | Medium |
|
||||
| VFX | Product turntable with HDRI | Hard |
|
||||
| VFX | Particle system with physics (collisions, gravity) | Hard |
|
||||
| Transitions | Morphing shape transitions | Hard |
|
||||
| Data viz | Sankey / flow diagrams | Medium |
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
title: Changelog process
|
||||
description: How HyperFrames drafts, reviews, and publishes release notes.
|
||||
---
|
||||
|
||||
HyperFrames changelogs have two audiences:
|
||||
|
||||
- Developers reading the docs changelog for user-facing changes, migration notes, and reasons to upgrade.
|
||||
- Maintainers publishing GitHub Releases during the npm release process.
|
||||
|
||||
The release workflow keeps both audiences in sync while preserving a human editing step.
|
||||
|
||||
## Goals
|
||||
|
||||
- Make every stable release easy to scan from the docs site.
|
||||
- Publish useful GitHub Release notes without relying only on raw commit logs.
|
||||
- Keep release notes editable before publishing.
|
||||
- Avoid over-documenting internal-only commits that do not change user behavior.
|
||||
|
||||
## Source of truth
|
||||
|
||||
Each reviewed release note lives in `releases/vX.Y.Z.md`.
|
||||
|
||||
The docs changelog lives in `docs/changelog.mdx` and uses Mintlify `<Update>` entries. The draft generator can prepend a docs entry, but maintainers should edit the generated copy before tagging the release. After any manual rewrite, keep `releases/vX.Y.Z.md` and the matching docs `<Update>` entry in sync.
|
||||
|
||||
## Stable release workflow
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the release">
|
||||
Run the stable release command from the repository root:
|
||||
```bash
|
||||
bun run release:prepare 0.6.53
|
||||
```
|
||||
On the first run, this creates or updates the changelog draft and then exits before tagging:
|
||||
- `releases/v0.6.53.md`
|
||||
- `docs/changelog.mdx`
|
||||
|
||||
The checkpoint exits non-zero intentionally so chained release commands stop. Review the generated copy, remove the TODO summary marker, and rerun the same command. Once both changelog artifacts are reviewed, `release:prepare` runs `set-version` to create the release commit and tag.
|
||||
</Step>
|
||||
<Step title="Review and rewrite">
|
||||
Read the generated notes and rewrite them for users. Prioritize impact over implementation detail.
|
||||
|
||||
Call out:
|
||||
- Breaking changes and required migration steps
|
||||
- New capabilities
|
||||
- Important bug fixes
|
||||
- Performance or reliability improvements
|
||||
- Security fixes
|
||||
</Step>
|
||||
<Step title="Rerun the release command">
|
||||
After review, run the same command again:
|
||||
```bash
|
||||
bun run release:prepare 0.6.53
|
||||
```
|
||||
For stable releases, `release:prepare` checks that `releases/v0.6.53.md` exists, that `docs/changelog.mdx` has a matching `HyperFrames v0.6.53` entry, and that neither artifact still contains the generated TODO summary. The lower-level `set-version` command enforces the same reviewed-changelog checkpoint for maintainers who run it directly. Prereleases and `--no-tag` version bumps skip this check. Use `--skip-changelog-check` only for emergency stable releases.
|
||||
|
||||
The release commit can include the version bump, `releases/v0.6.53.md`, and the docs changelog update.
|
||||
</Step>
|
||||
<Step title="Publish">
|
||||
Push the release tag:
|
||||
```bash
|
||||
git push origin main --tags
|
||||
```
|
||||
The publish workflow uses `releases/v0.6.53.md` as the GitHub Release body when the file exists. If no reviewed release file is present, it falls back to GitHub-generated notes.
|
||||
|
||||
The generated compare link points to the future `v0.6.53` tag. It may not resolve between the PR merge and the final tag push.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Draft regeneration
|
||||
|
||||
Use the lower-level draft command when you need to regenerate changelog copy before review:
|
||||
|
||||
```bash
|
||||
bun run changelog:draft 0.6.53 --write --force
|
||||
```
|
||||
|
||||
Without `--force`, the draft command leaves an existing `releases/vX.Y.Z.md` file unchanged and still adds the docs changelog entry if it is missing. If the docs changelog already has that version, edit the existing docs entry manually.
|
||||
|
||||
## Weekly digest workflow
|
||||
|
||||
Weekly updates are editorial rollups, not release notes. Keep `docs/changelog.mdx` versioned and use `docs/weekly-updates.mdx` for curated weekly highlights that can also be adapted for Discord and X.
|
||||
|
||||
Generate an editable weekly packet from the repository root:
|
||||
|
||||
```bash
|
||||
bun run changelog:weekly --from 2026-06-01 --to 2026-06-07 --write
|
||||
```
|
||||
|
||||
Run it from an up-to-date `main` branch so the selected range reflects public history, not a feature branch.
|
||||
|
||||
This creates:
|
||||
|
||||
- `updates/weekly/2026-06-07.md`
|
||||
- `updates/social/2026-06-07.discord.md`
|
||||
- `updates/social/2026-06-07.x.md`
|
||||
|
||||
It also prepends a matching entry to `docs/weekly-updates.mdx`. Review and rewrite the generated files before publishing. Social drafts are never posted automatically.
|
||||
|
||||
## Writing style
|
||||
|
||||
Use plain, user-facing language. Prefer "Fixed Studio render failures when FFmpeg is missing" over "Added pre-flight check in render activity." Link to relevant docs, migration guides, or pull requests when they help users act.
|
||||
|
||||
Group changes in this order when applicable:
|
||||
|
||||
1. Breaking Changes
|
||||
2. Features
|
||||
3. Fixes
|
||||
4. Performance
|
||||
5. Docs & Examples
|
||||
6. Catalog
|
||||
7. Internal
|
||||
|
||||
Avoid listing release commits, dependency-only updates, generated file churn, and changes labeled `skip-changelog`.
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: Release channels
|
||||
description: How HyperFrames keeps alpha-only work out of stable releases.
|
||||
---
|
||||
|
||||
HyperFrames publishes two release channels:
|
||||
|
||||
- Stable releases use versions like `0.4.24` and publish to the npm `latest` dist-tag.
|
||||
- Prereleases use versions like `0.4.24-alpha.1` and publish to the npm dist-tag named by the prerelease suffix, such as `alpha`.
|
||||
|
||||
## Branch policy
|
||||
|
||||
Use branch separation to decide what code is eligible for each release channel.
|
||||
Dist-tags only control npm install defaults; they do not remove code from a package.
|
||||
|
||||
- `main` is stable/releasable. Anything merged to `main` is eligible for `latest`.
|
||||
- `release/v*` branches are for stable patch releases and hotfixes.
|
||||
- `next`, `alpha`, `beta`, `rc`, `canary`, and `prerelease/*` branches are for prerelease integration.
|
||||
|
||||
If a feature should ship in alpha only, merge or retarget that PR to a prerelease branch instead of `main`.
|
||||
|
||||
## Stable release
|
||||
|
||||
Stable releases must be reachable from `origin/main` or `origin/release/v*`.
|
||||
Prepare and review release notes before creating the release commit:
|
||||
|
||||
```bash
|
||||
bun run release:prepare <version>
|
||||
```
|
||||
|
||||
On the first run, `release:prepare` drafts missing changelog artifacts and exits non-zero for review so chained release commands stop before tagging. After the generated TODO summary is rewritten, rerun the same command to create the release commit and tag.
|
||||
|
||||
See [Changelog process](/contributing/changelog-process) for the full workflow. For stable releases, `bun run set-version <version>` still enforces this checkpoint when maintainers run the lower-level release command directly.
|
||||
|
||||
```bash
|
||||
bun run release:prepare <version>
|
||||
git push origin main --tags
|
||||
```
|
||||
|
||||
For hotfixes, branch from the last stable tag, cherry-pick only the fix, publish the patch release, then merge or cherry-pick the same fix back into the prerelease branch.
|
||||
|
||||
## Alpha release
|
||||
|
||||
Alpha releases must be reachable from a prerelease branch such as `origin/next` or `origin/alpha`.
|
||||
Use the same changelog draft workflow when the prerelease contains changes that users should know about.
|
||||
|
||||
```bash
|
||||
git checkout next
|
||||
bun run set-version 0.4.25-alpha.1
|
||||
git push origin next
|
||||
git push origin v0.4.25-alpha.1
|
||||
```
|
||||
|
||||
Consumers can install alpha builds explicitly:
|
||||
|
||||
```bash
|
||||
npm install hyperframes@alpha
|
||||
npm install @hyperframes/core@alpha
|
||||
```
|
||||
|
||||
## CI guardrails
|
||||
|
||||
The publish workflow validates release channel boundaries before publishing:
|
||||
|
||||
- Stable versions must publish with `latest`.
|
||||
- Prerelease versions must publish with the prerelease dist-tag, such as `alpha`.
|
||||
- Stable tags must be reachable from `main` or `release/v*`.
|
||||
- Prerelease tags must be reachable from a prerelease branch.
|
||||
- Merged `release/vX.Y.Z` PRs publish stable releases only.
|
||||
|
||||
This prevents an alpha-only feature from being included in a stable hotfix by accident.
|
||||
@@ -0,0 +1,315 @@
|
||||
---
|
||||
title: Studio Manual DOM Editing
|
||||
description: What the Studio manual DOM editing inspector ships today, including capabilities, UX, and constraints.
|
||||
---
|
||||
|
||||
This page documents the current manual DOM editing surface in HyperFrames Studio. It reflects the implementation that ships in the Studio inspector today, not the earlier design draft that explored third-party transform engines.
|
||||
|
||||
## What Shipped
|
||||
|
||||
Studio now supports a direct DOM editing workflow inside the preview:
|
||||
|
||||
- select supported elements directly in the preview
|
||||
- see an editor-owned overlay around the current selection
|
||||
- move and resize supported elements on canvas when geometry is safe
|
||||
- detach eligible layout-controlled layers with an explicit `Make movable` action
|
||||
- edit style properties from the right-side `Design` inspector
|
||||
- edit text layers for safe text-bearing selections, including empty text values
|
||||
- add and remove child text layers for multi-text selections
|
||||
- edit solid fills, gradients, project-asset image fills, external image fills, opacity, radius, flex metadata, typography, and blend mode
|
||||
- drill into nested compositions from master view instead of pretending every inner node is editable in place
|
||||
- generate an element-scoped `Ask agent` prompt bundle from the right inspector
|
||||
|
||||
The important rule is conservative: Studio only exposes interactions it can round-trip back to authored HTML with deterministic behavior.
|
||||
|
||||
## Current User Experience
|
||||
|
||||
### Preview selection
|
||||
|
||||
- Single click selects a patchable element in the preview.
|
||||
- The selection overlay is rendered in Studio chrome, not injected into authored content.
|
||||
- The overlay is cleared when:
|
||||
- the `Inspector` panel is closed
|
||||
- the user clicks an empty area in the preview
|
||||
- the underlying element disappears after a source refresh
|
||||
|
||||
### Overlay behavior
|
||||
|
||||
The overlay provides:
|
||||
|
||||
- selection bounds
|
||||
- drag behavior for supported elements
|
||||
- a resize handle when width and height are safely patchable
|
||||
- blocked-drag feedback for unsupported movement
|
||||
|
||||
The overlay intentionally does not include a floating action toolbar. `Ask agent` lives in the right inspector header, and style controls live in the `Design` panel.
|
||||
|
||||
The current implementation uses Studio-owned pointer handling in `DomEditOverlay.tsx`. It does **not** use `Moveable`.
|
||||
|
||||
### Inspector behavior
|
||||
|
||||
The `Design` panel currently includes:
|
||||
|
||||
- `Layout`
|
||||
- X / Y / W / H fields
|
||||
- wheel and arrow-key numeric scrubbing
|
||||
- `Make movable` for block-ish layout-controlled layers that can be detached safely
|
||||
- `Flex`
|
||||
- direction, justify, align, gap, clip content
|
||||
- `Radius`
|
||||
- slider + live readout
|
||||
- `Blending`
|
||||
- opacity slider + live readout
|
||||
- blend mode
|
||||
- `Fill`
|
||||
- solid color
|
||||
- multi-stop gradient editing
|
||||
- project asset image fills
|
||||
- inline image upload into the project assets list
|
||||
- external image URL fill
|
||||
- text color
|
||||
- `Color picker`
|
||||
- viewport-clamped floating picker
|
||||
- saturation / brightness crosshair
|
||||
- hue and alpha sliders
|
||||
- hex input
|
||||
- `Text`
|
||||
- direct text layer editing when the selection is safe to patch
|
||||
- add / remove text layers for child text selections
|
||||
- font size, weight, and family controls
|
||||
- `Selection colors`
|
||||
- a summary of detected colors for the current selection
|
||||
|
||||
The inspector is intentionally split from `Renders` with a `Design / Renders` tab control in the right panel. Switching to `Renders` does not mean the header-level `Inspector` panel is closed.
|
||||
|
||||
## What Counts As Editable
|
||||
|
||||
Studio builds a `DomEditSelection` and `DomEditCapabilities` object for each selection.
|
||||
|
||||
### Selection requirements
|
||||
|
||||
A node is only useful to Studio if it can be identified with a stable patch target, for example:
|
||||
|
||||
- `id`
|
||||
- stable selector
|
||||
- selector index scoped to the correct source file
|
||||
- composition host mapping when master view is involved
|
||||
|
||||
### Move support
|
||||
|
||||
Move is allowed only when the selected element:
|
||||
|
||||
- has a stable patch target
|
||||
- is `absolute` or `fixed`
|
||||
- has `left` and `top` values that resolve to pixel values
|
||||
- is not transform-driven (`transform: none`)
|
||||
|
||||
### Resize support
|
||||
|
||||
Resize is allowed only when move is already allowed and Studio can also safely patch pixel `width` and/or `height`.
|
||||
|
||||
### Detach from layout support
|
||||
|
||||
Some block-ish layers are selectable and style-editable, but cannot be moved directly because flex, grid, or normal document flow owns their position.
|
||||
|
||||
For those layers, Studio can expose `Make movable` instead of silently converting on drag. The action measures the current visual rect relative to the composition root and writes conservative inline geometry:
|
||||
|
||||
- `position: absolute`
|
||||
- `left`, `top`, `width`, and `height` in pixels
|
||||
- `margin: 0`
|
||||
|
||||
The UI explains that this detaches the layer from flex/grid flow and preserves the current visual position. Inline text nodes are not detached directly.
|
||||
|
||||
### Text editing support
|
||||
|
||||
Text editing is allowed only for safe text-bearing selections:
|
||||
|
||||
- supported text-bearing tags such as `div`, `span`, `p`, `strong`, and headings
|
||||
- self text selections or leaf child text layers
|
||||
- empty text values after a user clears the content
|
||||
- not a composition host
|
||||
|
||||
For multi-text selections, Studio shows a text-layer list. Users can select a specific text layer, edit content live, change size, weight, and font family, add a sibling text layer, or remove the active layer.
|
||||
|
||||
### Unsupported examples
|
||||
|
||||
Studio intentionally withholds direct geometry editing for:
|
||||
|
||||
- flex/grid children whose position is emergent from layout, unless the user chooses `Make movable`
|
||||
- transform-driven geometry
|
||||
- nested composition internals while the user is still in master view
|
||||
- nodes without a stable patch target
|
||||
- inline text spans as geometry targets
|
||||
|
||||
When geometry is blocked but style edits are still safe, the inspector shows the selection and the reason direct geometry editing is unavailable.
|
||||
|
||||
If the user tries to drag a blocked layer, Studio shows a toast. Layout-owned layers point users to `Make movable`; transform-driven or unsafe targets explain that direct move/resize is limited to absolute or fixed pixel geometry with no transform-driven layout.
|
||||
|
||||
## Nested Composition Rules
|
||||
|
||||
Nested compositions are handled explicitly.
|
||||
|
||||
### In master view
|
||||
|
||||
- clicking content inside a nested composition maps back to the composition host
|
||||
- supported composition hosts can move as a whole when their host geometry is safe
|
||||
- Studio does not expose direct inner-node geometry edits from the master preview
|
||||
- double click drills into the subcomposition
|
||||
|
||||
### After drill-down
|
||||
|
||||
- Studio resolves selections inside that composition normally
|
||||
- direct move/resize becomes available again if the selected inner node meets the capability rules
|
||||
- text, fill, gradient, image, radius, opacity, and typography edits apply to the selected inner node
|
||||
|
||||
This keeps Studio honest about what it can patch safely from the current editing context.
|
||||
|
||||
## Source Patching Model
|
||||
|
||||
Studio still uses authored HTML as the source of truth.
|
||||
|
||||
The manual DOM editing flow patches source through the existing patch pipeline in `packages/studio/src/utils/sourcePatcher.ts`.
|
||||
|
||||
Current patch types used by the inspector include:
|
||||
|
||||
- inline style patches
|
||||
- attribute patches for timeline-linked editing paths
|
||||
- text-content patches
|
||||
- detach-from-layout style patches
|
||||
|
||||
The flow is:
|
||||
|
||||
1. user selects or manipulates an element in the preview
|
||||
2. Studio resolves a stable target
|
||||
3. the preview is updated optimistically for interaction feedback
|
||||
4. the patch is written back to source
|
||||
5. the preview refreshes and selection is reattached
|
||||
|
||||
## Gradient Editing
|
||||
|
||||
The current gradient editor is a structured Studio control, not a raw CSS text field.
|
||||
|
||||
It supports:
|
||||
|
||||
- `linear`, `radial`, and `conic` gradients
|
||||
- repeating variants
|
||||
- multiple stops
|
||||
- stop insertion by clicking the preview strip
|
||||
- stop removal
|
||||
- angle control
|
||||
- radial shape and size controls
|
||||
- radial/conic center controls
|
||||
|
||||
The editor still serializes back to CSS `background-image`, but the inspector works with a parsed gradient model instead of forcing the user to type raw gradient syntax.
|
||||
|
||||
## Image Fill Editing
|
||||
|
||||
The image fill editor is no longer just a raw `background-image` input.
|
||||
|
||||
It supports:
|
||||
|
||||
- selecting an existing project image asset
|
||||
- uploading an image from the fill panel, which also adds it to the Assets tab
|
||||
- previewing the selected project asset in the panel
|
||||
- entering an external URL when the image is not a project asset
|
||||
|
||||
Studio serializes project asset selections back to `background-image: url(...)`, and rewrites asset URLs so nested subcomposition previews still resolve the image correctly.
|
||||
|
||||
## Color Editing
|
||||
|
||||
The color editor is a custom Studio popover instead of the native browser color dialog.
|
||||
|
||||
It supports:
|
||||
|
||||
- opening from the whole color row
|
||||
- staying inside the viewport near the clicked color
|
||||
- saturation / brightness picking with visible crosshair guides
|
||||
- hue and alpha controls with visible handles
|
||||
- a current color swatch, readout, and hex input
|
||||
|
||||
The picker writes CSS `rgb(...)` or `rgba(...)` values and preserves alpha through edits.
|
||||
|
||||
## Numeric Scrubbing
|
||||
|
||||
Numeric layout/detail inputs support lightweight design-tool-style nudging:
|
||||
|
||||
- mouse wheel over the focused field
|
||||
- `ArrowUp` / `ArrowDown`
|
||||
- `Shift` for larger steps
|
||||
- `Alt` for finer steps
|
||||
|
||||
This is currently used across the numeric commit fields in the inspector, including layout metrics and other numeric text inputs that parse cleanly as values plus units.
|
||||
|
||||
## Files That Own The Feature
|
||||
|
||||
The main implementation lives in:
|
||||
|
||||
- `packages/studio/src/App.tsx`
|
||||
- overall inspector wiring
|
||||
- selection lifecycle
|
||||
- preview hit testing
|
||||
- persistence hooks
|
||||
- detach-from-layout commit flow
|
||||
- `packages/studio/src/components/editor/DomEditOverlay.tsx`
|
||||
- overlay box, drag, resize, blocked-drag feedback
|
||||
- `packages/studio/src/components/editor/PropertyPanel.tsx`
|
||||
- right-side inspector UI
|
||||
- `packages/studio/src/components/editor/domEditing.ts`
|
||||
- selection resolution
|
||||
- capability gating
|
||||
- text field modeling
|
||||
- prompt generation
|
||||
- `packages/studio/src/components/editor/colorValue.ts`
|
||||
- color parsing, HSV conversion, and CSS color serialization
|
||||
- `packages/studio/src/components/editor/floatingPanel.ts`
|
||||
- viewport-safe floating panel placement for color picking
|
||||
- `packages/studio/src/components/editor/fontAssets.ts`
|
||||
- imported font asset helpers
|
||||
- `packages/studio/src/components/editor/fontCatalog.ts`
|
||||
- Google font catalog metadata and stylesheet URLs
|
||||
- `packages/studio/src/components/editor/gradientValue.ts`
|
||||
- gradient parsing, serialization, and stop editing helpers
|
||||
- `packages/studio/src/utils/sourcePatcher.ts`
|
||||
- source patch persistence
|
||||
|
||||
Supporting Studio shell changes also landed in:
|
||||
|
||||
- `packages/studio/src/components/nle/NLELayout.tsx`
|
||||
- `packages/studio/src/components/nle/NLEPreview.tsx`
|
||||
- `packages/studio/src/components/sidebar/CompositionsTab.tsx`
|
||||
- `packages/studio/src/components/sidebar/LeftSidebar.tsx`
|
||||
- `packages/studio/src/player/components/Player.tsx`
|
||||
- `packages/studio/src/player/components/Timeline.tsx`
|
||||
- `packages/studio/src/player/components/TimelineClip.tsx`
|
||||
- `packages/studio/src/player/hooks/useTimelinePlayer.ts`
|
||||
- `packages/studio/src/utils/mediaTypes.ts`
|
||||
|
||||
## Current Constraints
|
||||
|
||||
This feature is intentionally **not** a full general-purpose visual builder.
|
||||
|
||||
Still out of scope today:
|
||||
|
||||
- rotation
|
||||
- arbitrary transforms
|
||||
- snapping and alignment guides
|
||||
- multi-select
|
||||
- marquee selection
|
||||
- freeform editing of every DOM node regardless of layout model
|
||||
- editing nested subcomposition internals directly from the master preview without drill-down
|
||||
- automatic conversion to absolute positioning on drag without user confirmation
|
||||
- direct geometry editing of inline text spans
|
||||
|
||||
## Bottom Line
|
||||
|
||||
Studio manual DOM editing is now a narrow, deterministic visual editing layer over authored HTML.
|
||||
|
||||
It does **not** try to make the whole DOM freely editable. Instead it:
|
||||
|
||||
- keeps source HTML as the source of truth
|
||||
- exposes only patchable interactions
|
||||
- uses a Studio-owned overlay layer for direct manipulation
|
||||
- gives users a real inspector for safe style and text edits
|
||||
- treats nested compositions as drill-down boundaries instead of flattening them into an unsafe editing surface
|
||||
|
||||
That tradeoff is the reason the current feature feels reliable instead of deceptive.
|
||||
@@ -0,0 +1,132 @@
|
||||
---
|
||||
title: Testing Local CLI Changes
|
||||
description: How to test unreleased CLI changes outside the monorepo using your local build.
|
||||
---
|
||||
|
||||
When you modify the CLI or any package it bundles (core, engine, producer, studio), you need to test those changes against real projects _outside_ the monorepo — the same way an end user would run `hyperframes preview`.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Build the monorepo first. Every time you change source files, rebuild before testing.
|
||||
|
||||
```bash
|
||||
# From the monorepo root
|
||||
bun run build
|
||||
```
|
||||
|
||||
## Option 1: bun link (recommended)
|
||||
|
||||
`bun link` makes the `hyperframes` binary in your `$PATH` point at your local build. It survives across terminal sessions and auto-picks up new builds without re-linking.
|
||||
|
||||
```bash
|
||||
# If you previously installed hyperframes globally, remove it first —
|
||||
# a global install takes priority over bun link and shadows your local build.
|
||||
npm uninstall -g hyperframes 2>/dev/null
|
||||
|
||||
# Link your local build
|
||||
cd packages/cli
|
||||
bun link
|
||||
|
||||
# Verify — should print your local version AND point to the monorepo
|
||||
hyperframes --version
|
||||
which hyperframes
|
||||
```
|
||||
|
||||
Now use `hyperframes` normally in any directory:
|
||||
|
||||
```bash
|
||||
cd ~/my-video-project
|
||||
hyperframes preview .
|
||||
```
|
||||
|
||||
**After every `bun run build`** the linked binary is already up to date — no re-linking needed.
|
||||
|
||||
To restore the published release when you're done:
|
||||
|
||||
```bash
|
||||
bun unlink hyperframes
|
||||
npm install -g hyperframes@latest
|
||||
```
|
||||
|
||||
## Option 2: node alias (no PATH changes)
|
||||
|
||||
If you don't want to touch your global `$PATH`, add a shell alias or call `node` directly:
|
||||
|
||||
```bash
|
||||
# Temporary alias for your current shell session
|
||||
alias hyperframes="node /path/to/hyperframes/packages/cli/dist/cli.js"
|
||||
|
||||
# Or invoke directly
|
||||
node /path/to/hyperframes/packages/cli/dist/cli.js preview .
|
||||
```
|
||||
|
||||
Replace `/path/to/hyperframes` with your actual monorepo path.
|
||||
|
||||
## Option 3: npm pack (test the exact published artifact)
|
||||
|
||||
Use this when you want to verify what would actually ship in a release, including the bundled studio and examples.
|
||||
|
||||
```bash
|
||||
cd packages/cli
|
||||
npm pack
|
||||
# Creates: hyperframes-<version>.tgz
|
||||
|
||||
# Test it in an isolated directory
|
||||
mkdir /tmp/pack-test && cd /tmp/pack-test
|
||||
npx /path/to/hyperframes/packages/cli/hyperframes-<version>.tgz init my-video
|
||||
cd my-video
|
||||
npx /path/to/hyperframes/packages/cli/hyperframes-<version>.tgz preview .
|
||||
```
|
||||
|
||||
## Testing the fix branches
|
||||
|
||||
When validating a specific bug fix, extract one of the test project archives and run through the scenario:
|
||||
|
||||
```bash
|
||||
# Example: testing audio-after-seek fix
|
||||
unzip golden-lyric-video.zip && cd golden-lyric-video
|
||||
hyperframes preview .
|
||||
# 1. Press Play — confirm audio plays
|
||||
# 2. Drag the timeline scrubber to a different position
|
||||
# 3. Press Play again — audio should resume from the seeked position
|
||||
```
|
||||
|
||||
Common test scenarios:
|
||||
|
||||
| Bug | Project | Steps |
|
||||
|---|---|---|
|
||||
| Audio silent after seek | `golden-lyric-video` | Play → seek → play again, verify audio |
|
||||
| Render stuck at 0% | any | Renders tab → Export → watch progress bar |
|
||||
| Download 404 after restart | any | Complete a render → `Ctrl+C` → restart → Download |
|
||||
| Timeline stops early | `intro-vid` | Play → should reach `0:05`, not stop at `0:03` |
|
||||
| Lottie missing | `hyperframe-build-up-demo` | Play → rocket visible during 0–2 s |
|
||||
| Blank thumbnails | any | Compositions sidebar should show previews |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Changes not reflected after `bun run build`**
|
||||
|
||||
The CLI binary is a single bundled file at `packages/cli/dist/cli.js`. If your change is in `@hyperframes/core` or another workspace package, make sure `bun run build` rebuilt _all_ packages — the CLI bundles its dependencies at build time.
|
||||
|
||||
**`hyperframes` still shows the old version / old UI**
|
||||
|
||||
A globally installed `hyperframes` package shadows `bun link`. Check which binary is active:
|
||||
|
||||
```bash
|
||||
which hyperframes
|
||||
```
|
||||
|
||||
If it points to a global store rather than your monorepo, remove the global install and re-link:
|
||||
|
||||
```bash
|
||||
npm uninstall -g hyperframes
|
||||
cd packages/cli && bun link
|
||||
```
|
||||
|
||||
**Port already in use**
|
||||
|
||||
`hyperframes preview` defaults to port 3002 and auto-increments if it's taken. Pass `--port` to use a specific port:
|
||||
|
||||
```bash
|
||||
hyperframes preview . --port 4000
|
||||
```
|
||||
Reference in New Issue
Block a user