Skip to content

Commit a31c716

Browse files
committed
feat(skills): add contribute skill for registry block authoring
New skill that guides users through the full workflow of contributing caption styles, VFX blocks, transitions, and other components to the HyperFrames registry. Covers: scaffolding, proven patterns (seeded PRNG, paused timelines, hard kills, unique ID prefixes), validation, rendering, and PR prep. Includes copy-paste HTML templates for caption and Three.js components with all the non-negotiable rules baked in. Tested by an unbiased agent with zero prior HyperFrames knowledge — built a working cap-typewriter component that passed lint and validate on the first attempt. Feedback incorporated: per-character animation guidance, monospace font size exceptions, positioning variants, and PREFIX naming convention table.
1 parent 21794e6 commit a31c716

2 files changed

Lines changed: 441 additions & 0 deletions

File tree

skills/contribute/SKILL.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
name: contribute
3+
description: Scaffold, build, validate, and ship new HyperFrames registry components (caption styles, VFX blocks, transitions, lower thirds). Guides the full workflow from idea to merged PR. Use when user says "contribute", "new component", "add a block", "create a caption style", "build a transition", or wants to add something to the HyperFrames registry.
4+
---
5+
6+
# Contribute to HyperFrames Registry
7+
8+
Guide the user from idea to merged PR for a new registry block.
9+
10+
## Workflow
11+
12+
```
13+
1. Clarify → 2. Scaffold → 3. Build → 4. Validate → 5. Preview → 6. Ship
14+
```
15+
16+
### Step 1: Clarify
17+
18+
Ask what they're building:
19+
20+
- **Caption style** — word-level karaoke, specific animation/highlight pattern
21+
- **VFX block** — Three.js 3D effect, shader, particle system
22+
- **Transition** — scene-to-scene transition effect
23+
- **Block** — lower third, social card, title card, data viz
24+
25+
Then ask:
26+
- One-sentence description of the effect
27+
- Visual reference (URL, screenshot, or description)
28+
- Who uses this and when?
29+
30+
### Step 2: Scaffold
31+
32+
Create the registry block structure in the hyperframes repo:
33+
34+
```
35+
registry/blocks/{block-name}/
36+
{block-name}.html
37+
registry-item.json
38+
```
39+
40+
**Naming convention:**
41+
42+
| Block name | ID prefix for elements | Example IDs |
43+
|-----------|----------------------|-------------|
44+
| `cap-hormozi` | `hz` | `hz-cg-0`, `hz-cw-3` |
45+
| `cap-typewriter` | `tw` | `tw-cg-0`, `tw-ch-0-5` |
46+
| `vfx-chrome` | `vc` | `vc-canvas` |
47+
48+
Use a 2-3 letter prefix derived from the block name. ALL element IDs in the composition must use this prefix to avoid collisions when embedded as sub-compositions.
49+
50+
**registry-item.json template:**
51+
52+
```json
53+
{
54+
"$schema": "https://hyperframes.heygen.com/schema/registry-item.json",
55+
"name": "{block-name}",
56+
"type": "hyperframes:block",
57+
"title": "{Human Title}",
58+
"description": "{one sentence}",
59+
"stability": "experimental",
60+
"dimensions": { "width": 1920, "height": 1080 },
61+
"duration": 10,
62+
"tags": ["{category}", "{subcategory}"],
63+
"files": [
64+
{
65+
"path": "{block-name}.html",
66+
"target": "compositions/{block-name}.html",
67+
"type": "hyperframes:composition"
68+
}
69+
]
70+
}
71+
```
72+
73+
### Step 3: Build
74+
75+
Apply the correct template based on component type. See [templates.md](templates.md) for copy-paste starters.
76+
77+
#### Caption blocks
78+
79+
Read the captions reference in the hyperframes skill BEFORE writing.
80+
81+
**Non-negotiable caption rules:**
82+
- Font: **96px minimum** for proportional fonts (Montserrat, Figtree). **64-72px is acceptable for monospace** (JetBrains Mono, Chakra Petch) since monospace characters are wider.
83+
- Readability: `-webkit-text-stroke: 2-3px` OR multi-layer `text-shadow`
84+
- Overflow: call `window.__hyperframes.fitTextFontSize()` on every group
85+
- Karaoke: highlight active word via `tl.to(wordEl, { color/scale }, WORDS[wi].start)`
86+
- Hard kill: `tl.set(groupEl, { opacity: 0, visibility: "hidden" }, g.end)` on EVERY group
87+
- **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.
88+
89+
**Per-character animation** (typewriter, scramble, fade-in letter by letter):
90+
- Wrap each character in its own `<span>` with ID `{prefix}-ch-{groupIndex}-{charIndex}`
91+
- Stagger `tl.set(charSpan, { opacity: 1 }, charStartTime)` at computed intervals based on the word timestamps
92+
- For cursors and decorative elements: use `tl.set` at fixed intervals for blinking — NOT CSS animation (not seekable)
93+
94+
**Positioning variants:**
95+
- Centered (default): `display: flex; align-items: center; justify-content: center;`
96+
- Lower-third centered: `position: absolute; bottom: 100px; left: 0; width: 100%; text-align: center;`
97+
- Left-aligned: `position: absolute; bottom: 100px; left: 120px; text-align: left;`
98+
- Right-aligned: `position: absolute; bottom: 100px; right: 120px; text-align: right;`
99+
100+
#### VFX blocks (Three.js)
101+
102+
- Use `three@0.147.0` from CDN (global script, not ES modules)
103+
- `tl.eventCallback("onUpdate", renderScene); renderScene();` — NO requestAnimationFrame
104+
- State proxy pattern: GSAP animates plain JS object, render function applies to Three.js
105+
- Seeded PRNG (`mulberry32`) for any randomness
106+
107+
#### All component types
108+
109+
- `data-composition-id` MUST match `window.__timelines["id"]`
110+
- All element IDs prefixed with block abbreviation (see naming table above)
111+
- `gsap.timeline({ paused: true })` — always paused
112+
- No `Math.random()`, no `Date.now()`
113+
- Duration from `data-duration`, not GSAP timeline length
114+
115+
### Step 4: Validate
116+
117+
Run these in order. All must pass before proceeding.
118+
119+
```bash
120+
hyperframes lint # 0 errors required
121+
hyperframes validate --no-contrast # 0 console errors required
122+
```
123+
124+
Common fixes:
125+
- `timed_element_missing_clip_class` → add `class="clip"` to timed elements
126+
- `timeline_id_mismatch` → make `window.__timelines["X"]` match `data-composition-id="X"`
127+
- `composition_file_too_large` → warning only, acceptable for complex blocks
128+
129+
### Step 5: Preview
130+
131+
```bash
132+
hyperframes render -o preview.mp4
133+
hyperframes snapshot --at "1.0,3.0,5.0,7.0"
134+
```
135+
136+
Inspect every snapshot:
137+
- [ ] Text readable at 50% zoom (captions)
138+
- [ ] Animation visible at every timestamp (no blank frames)
139+
- [ ] No overflow or clipping
140+
141+
### Step 6: Ship
142+
143+
1. Create branch: `git checkout -b feat/registry-{block-name}`
144+
2. Format: `npx oxfmt registry/blocks/{block-name}/*.html`
145+
3. Stage only registry files: `git add registry/blocks/{block-name}/`
146+
4. Commit with descriptive message
147+
5. Push and open PR with rendered MP4 preview linked
148+
149+
## Quality Gate
150+
151+
Before opening the PR, verify:
152+
153+
- [ ] `hyperframes lint` → 0 errors
154+
- [ ] `hyperframes validate` → 0 console errors
155+
- [ ] Preview video shows the effect clearly
156+
- [ ] All IDs unique and prefixed with block abbreviation
157+
- [ ] `npx oxfmt --check` passes on HTML files

0 commit comments

Comments
 (0)