Skill Tracer
Skills › HyperFrames › hyperframes-registry › contributing.md

contributing.md

180 lines · skills/hyperframes-registry/references/contributing.md at a595755

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# Contributing a Block or Component to the Registry
2
3Guide the user from idea to merged PR for a new registry block or component.
4

Contributing a Block or Component to the Registry

Guide the user from idea to merged PR for a new registry block or component.

Raw lines 1 to 4
5## Workflow
6
7```
81. Clarify → 2. Scaffold → 3. Build → 4. Validate → 5. Preview → 6. Ship
9```

Workflow

1. Clarify → 2. Scaffold → 3. Build → 4. Validate → 5. Preview → 6. Ship
Raw lines 5 to 10
11### Step 1: Clarify
13Ask what they're building. The registry has two item types:
15- **Block** (`registry/blocks/`, type `hyperframes:block`) — a full standalone composition with fixed dimensions and duration. Caption styles, VFX effects, title cards, lower thirds.
16- **Component** (`registry/components/`, type `hyperframes:component`) — a reusable snippet with no fixed dimensions or duration. CSS effects, text treatments, overlays that adapt to any composition size.
18Then ask:
20- One-sentence description of the effect
21- Visual reference (URL, screenshot, or description)
22- Who uses this and when?

Step 1: Clarify

Ask what they're building. The registry has two item types:

  • Block (registry/blocks/, type hyperframes:block) — a full standalone composition with fixed dimensions and duration. Caption styles, VFX effects, title cards, lower thirds.
  • Component (registry/components/, type hyperframes:component) — a reusable snippet with no fixed dimensions or duration. CSS effects, text treatments, overlays that adapt to any composition size.

Then ask:

  • One-sentence description of the effect
  • Visual reference (URL, screenshot, or description)
  • Who uses this and when?
Raw lines 11 to 23
24### Step 2: Scaffold
26Create the registry structure:
28**For blocks:**
30```
31registry/blocks/{block-name}/
32 {block-name}.html
33 registry-item.json
34```
36**For components:**
38```
39registry/components/{component-name}/
40 {component-name}.html
41 registry-item.json
42```
44**Naming convention:**
46| Item name | ID prefix | Example IDs |
47| ---------------- | --------- | ---------------------- |
48| `cap-hormozi` | `hz` | `hz-cg-0`, `hz-cw-3` |
49| `cap-typewriter` | `tw` | `tw-cg-0`, `tw-ch-0-5` |
50| `vfx-chrome` | `vc` | `vc-canvas` |
52Use a 2-3 letter prefix. ALL element IDs must use this prefix to avoid collisions in sub-compositions.
54**registry-item.json** — use the canonical templates in [templates.md](templates.md) (block and component variants, both with all required fields).

Step 2: Scaffold

Create the registry structure:

For blocks:

registry/blocks/{block-name}/
  {block-name}.html
  registry-item.json

For components:

registry/components/{component-name}/
  {component-name}.html
  registry-item.json

Naming convention:

Item nameID prefixExample IDs
cap-hormozihzhz-cg-0, hz-cw-3
cap-typewritertwtw-cg-0, tw-ch-0-5
vfx-chromevcvc-canvas

Use a 2-3 letter prefix. ALL element IDs must use this prefix to avoid collisions in sub-compositions.

registry-item.json — use the canonical templates in templates.md (block and component variants, both with all required fields).

Raw lines 24 to 55
56### Step 3: Build
58Apply the correct template based on type. See [templates.md](templates.md) for copy-paste starters.
60#### Caption blocks
62**Non-negotiable caption rules:**
64- Font: **96px minimum** for proportional fonts. **64-72px acceptable for monospace** (wider characters need less size).
65- Readability: `-webkit-text-stroke: 2-3px` OR multi-layer `text-shadow`
66- Overflow: call `window.__hyperframes.fitTextFontSize()` on every group
67- Karaoke: highlight active word via `tl.to(wordEl, { color/scale }, WORDS[wi].start)`
68- Hard kill: `tl.set(groupEl, { opacity: 0, visibility: "hidden" }, g.end)` on EVERY group
69- **Never use `tl.from(el, { opacity: 0 })` at the same position as `tl.set(el, { opacity: 1 })`** — the from clobbers the set. Use `tl.to` instead.
71**Per-character animation** (typewriter, scramble):
73- Wrap each character in `<span>` with ID `{prefix}-ch-{group}-{char}`
74- Stagger via `tl.set` at computed intervals from word timestamps
75- Cursors/decorative elements: use `tl.set` at intervals — NOT CSS animation (not seekable)
77**Positioning variants:**
79- Centered: `display: flex; align-items: center; justify-content: center;`
80- Lower-third: `position: absolute; bottom: 100px; left: 0; width: 100%; text-align: center;`
81- Left-aligned: `position: absolute; bottom: 100px; left: 120px; text-align: left;`
83#### VFX blocks (Three.js)
85- Use `three@0.147.0` from CDN (global script)
86- `tl.eventCallback("onUpdate", renderScene); renderScene();` — NO requestAnimationFrame
87- State proxy pattern: GSAP animates plain JS object, render function reads it
88- Seeded PRNG (`mulberry32`) for randomness
90#### All types
92- **Load files the block ships through `__hyperframes.assetUrl("assets/...")`** whenever a script
93 builds the path (textures, fonts, JSON, models). Attributes like `src` and `href` are rebased
94 when the block is mounted; strings in a script are not, so a bare `"assets/..."` 404s once the
95 block lives under `compositions/<name>/`. A separate `.js` file gets the URLs from the block's
96 inline script. A block whose assets install to the project's own `assets/` (target
97 `compositions/<name>.html`) keeps plain project-root paths; `assetUrl` would look beside the file.
98- **Placeholder content is monochrome** — read
99 [placeholder-material.md](placeholder-material.md) before choosing a single colour. Stand-in
100 screens, images, cards, avatars, logos and chart series use four alpha steps of the
101 composition's ink; accent marks one element and never a placeholder.
102- `data-composition-id` MUST match `window.__timelines["id"]`
103- All element IDs prefixed with block abbreviation
104- `gsap.timeline({ paused: true })` — always paused
105- No `Math.random()`, no `Date.now()`

Step 3: Build

Apply the correct template based on type. See templates.md for copy-paste starters.

Caption blocks

Non-negotiable caption rules:

  • Font: 96px minimum for proportional fonts. 64-72px acceptable for monospace (wider characters need less size).
  • Readability: -webkit-text-stroke: 2-3px OR multi-layer text-shadow
  • Overflow: call window.__hyperframes.fitTextFontSize() on every group
  • Karaoke: highlight active word via tl.to(wordEl, { color/scale }, WORDS[wi].start)
  • Hard kill: tl.set(groupEl, { opacity: 0, visibility: "hidden" }, g.end) on EVERY group
  • **Never use tl.from(el, { opacity: 0 }) at the same position as tl.set(el, { opacity: 1 })** — the from clobbers the set. Use tl.to instead.

Per-character animation (typewriter, scramble):

  • Wrap each character in <span> with ID {prefix}-ch-{group}-{char}
  • Stagger via tl.set at computed intervals from word timestamps
  • Cursors/decorative elements: use tl.set at intervals — NOT CSS animation (not seekable)

Positioning variants:

  • Centered: display: flex; align-items: center; justify-content: center;
  • Lower-third: position: absolute; bottom: 100px; left: 0; width: 100%; text-align: center;
  • Left-aligned: position: absolute; bottom: 100px; left: 120px; text-align: left;

VFX blocks (Three.js)

  • Use three@0.147.0 from CDN (global script)
  • tl.eventCallback("onUpdate", renderScene); renderScene(); — NO requestAnimationFrame
  • State proxy pattern: GSAP animates plain JS object, render function reads it
  • Seeded PRNG (mulberry32) for randomness

All types

  • **Load files the block ships through __hyperframes.assetUrl("assets/...")** whenever a script builds the path (textures, fonts, JSON, models). Attributes like src and href are rebased when the block is mounted; strings in a script are not, so a bare "assets/..." 404s once the block lives under compositions/<name>/. A separate .js file gets the URLs from the block's inline script. A block whose assets install to the project's own assets/ (target compositions/<name>.html) keeps plain project-root paths; assetUrl would look beside the file.
  • Placeholder content is monochrome — read placeholder-material.md before choosing a single colour. Stand-in screens, images, cards, avatars, logos and chart series use four alpha steps of the composition's ink; accent marks one element and never a placeholder.
  • data-composition-id MUST match window.__timelines["id"]
  • All element IDs prefixed with block abbreviation
  • gsap.timeline({ paused: true }) — always paused
  • No Math.random(), no Date.now()
Raw lines 56 to 106
107### Step 4: Validate
109```bash
110hyperframes lint # 0 errors required
111hyperframes check --no-contrast # 0 console errors required
112```

Step 4: Validate

hyperframes lint                    # 0 errors required
hyperframes check --no-contrast  # 0 console errors required
Raw lines 107 to 113
114### Step 5: Preview
116```bash
117# Render preview video
118hyperframes render -o preview.mp4
120# Snapshot for visual QA
121hyperframes snapshot --at "1.0,3.0,5.0,7.0"
123# Publish to hyperframes.studio for review
124npx hyperframes publish
125```
127**Catalog preview image** — For the default PNG preview, save your snapshot at `docs/images/catalog/{kind}/{name}.png` in the repository checkout (`{kind}` is `blocks` or `components`). After upload, the catalog serves it from `https://static.heygen.ai/hyperframes-oss/docs/images/catalog/{kind}/{name}.png`. If `registry-item.json` declares `preview`, the card uses its `poster` URL; a `preview` without `poster` has no image fallback.
129- **HeyGen internal contributors:** run `scripts/upload-docs-images.sh` from the repository root (requires AWS profile `engineering-767398024897`)
130- **External contributors:** attach the preview MP4 to your PR description. A maintainer will generate and upload the catalog image before merging.

Step 5: Preview

# Render preview video
hyperframes render -o preview.mp4

# Snapshot for visual QA
hyperframes snapshot --at "1.0,3.0,5.0,7.0"

# Publish to hyperframes.studio for review
npx hyperframes publish

Catalog preview image — For the default PNG preview, save your snapshot at docs/images/catalog/{kind}/{name}.png in the repository checkout ({kind} is blocks or components). After upload, the catalog serves it from https://static.heygen.ai/hyperframes-oss/docs/images/catalog/{kind}/{name}.png. If registry-item.json declares preview, the card uses its poster URL; a preview without poster has no image fallback.

  • HeyGen internal contributors: run scripts/upload-docs-images.sh from the repository root (requires AWS profile engineering-767398024897)
  • External contributors: attach the preview MP4 to your PR description. A maintainer will generate and upload the catalog image before merging.
Raw lines 114 to 131
Runs code scripts/upload-docs-images.sh :129
132### Step 6: Ship
134**All steps are required. Missing any one produces a broken catalog entry.**
136`{kind}` is `blocks` or `components` depending on what you built in Step 1.
138```bash
139# 1. Create branch
140git checkout -b feat/registry-{name}
142# 2. Format HTML
143npx oxfmt registry/{kind}/{name}/*.html
145# 3. Regenerate registry/registry.json from the item directories.
146# Do not hand-edit it: an entry added by hand survives until the next
147# regeneration and then vanishes, and one left behind for a directory that
148# no longer exists is worse, because `hyperframes add <name>` resolves the
149# name and then fails on missing files.
150npx tsx scripts/generate-registry-items.ts
152# 4. Generate catalog docs page
153npx tsx scripts/generate-catalog-pages.ts
155# 5. Publish to hyperframes.studio so reviewers can preview
156npx hyperframes publish
158# 6. Stage everything
159git add registry/{kind}/{name}/ registry/registry.json docs/catalog/
161# 7. Commit
162git commit -m "feat(registry): add {name} — {one sentence}"
164# 8. Push and open PR with hyperframes.studio link
165git push origin feat/registry-{name}
166gh pr create --title "feat(registry): {name}" --body "preview: {hyperframes.studio-url}"
167```
169**If you don't have a GitHub account:** you need one to open a PR. Sign up at https://github.com/signup, then run `gh auth login`.

Step 6: Ship

All steps are required. Missing any one produces a broken catalog entry.

{kind} is blocks or components depending on what you built in Step 1.

# 1. Create branch
git checkout -b feat/registry-{name}

# 2. Format HTML
npx oxfmt registry/{kind}/{name}/*.html

# 3. Regenerate registry/registry.json from the item directories.
#    Do not hand-edit it: an entry added by hand survives until the next
#    regeneration and then vanishes, and one left behind for a directory that
#    no longer exists is worse, because `hyperframes add <name>` resolves the
#    name and then fails on missing files.
npx tsx scripts/generate-registry-items.ts

# 4. Generate catalog docs page
npx tsx scripts/generate-catalog-pages.ts

# 5. Publish to hyperframes.studio so reviewers can preview
npx hyperframes publish

# 6. Stage everything
git add registry/{kind}/{name}/ registry/registry.json docs/catalog/

# 7. Commit
git commit -m "feat(registry): add {name} — {one sentence}"

# 8. Push and open PR with hyperframes.studio link
git push origin feat/registry-{name}
gh pr create --title "feat(registry): {name}" --body "preview: {hyperframes.studio-url}"

If you don't have a GitHub account: you need one to open a PR. Sign up at https://github.com/signup, then run gh auth login.

Raw lines 132 to 170
Runs code scripts/generate-registry-items.ts :150
Runs code scripts/generate-catalog-pages.ts :153
171## Quality Gate
173- [ ] `hyperframes lint` → 0 errors
174- [ ] `hyperframes check` → 0 console errors
175- [ ] `npx oxfmt --check` passes
176- [ ] `registry/registry.json` updated with new entry
177- [ ] `scripts/generate-catalog-pages.ts` run (docs page generated)
178- [ ] `npx hyperframes publish` run (claim your project URL)
179- [ ] Preview MP4 attached to PR (external) or catalog PNG uploaded (internal)
180- [ ] All IDs unique and prefixed

Quality Gate

  • [ ] hyperframes lint → 0 errors
  • [ ] hyperframes check → 0 console errors
  • [ ] npx oxfmt --check passes
  • [ ] registry/registry.json updated with new entry
  • [ ] scripts/generate-catalog-pages.ts run (docs page generated)
  • [ ] npx hyperframes publish run (claim your project URL)
  • [ ] Preview MP4 attached to PR (external) or catalog PNG uploaded (internal)
  • [ ] All IDs unique and prefixed
Raw lines 171 to 180
Runs code scripts/generate-catalog-pages.ts :177