new-template
Skill3 starsChanged 3 months agoMITView on GitHub
Find what kind of frame this kit cannot draw yet, then build it — for an agent working inside content-agent-kit. Use when the user says "template mới cho hôm nay", "thêm template", "add a template", "we need a frame for X", or asks what is missing from video-templates/. Also covers pulling one from the upstream HyperFrames registry when that is the cheaper answer.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- robritacca-dotcom/rift-dstheir own version, first seen Nov 1, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- robritacca-dotcom/rift-ds★ 9same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository16 other files it gives its agents.
- AGENTS.mdAGENTS.md
- ads-reportSkill
- audit-and-fixSkill
- bootstrap-content-agentSkill
- crawl-and-queueSkill
- create-videoSkill
- daily-runSkill
- daily-topic-videoSkill
- design-campaignSkill
- geo-optimizeSkill
- motion-craftSkill
- repurposeSkill
- research-and-captureSkill
- review-gateSkill
- topic-radarSkill
- video-and-postSkill
The file
We split this skill into the rules it gives an agent
10 rules. About 0 are common, 4 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 45
Do the survey, bring back two or three candidates with the gap each one fills, and let them pick.
- Distinctive: line 116
Generate both from one source: Every template added since v0.5.0 was emitted by a small script that takes shared markup, shared JS and …
- Distinctive: line 122
Draw from data, never from a hardcoded value: If a bar length and its printed number can disagree, one day they will.
- Distinctive: line 124
No caller-facing text in the markup: Every visible string arrives through a slot and is set in JS.
- Very specific: line 130
No default is someone else's brand: No real URLs, no channel names in data-composition-variables.
- Very specific: line 154
Every composition (both index.html and compositions/portrait.html) MUST register its timeline under both IDs:
- Very specific: line 161
If compositions/portrait.html only registers "main" or omits "portrait", Puppeteer will wait 45 seconds for the sub-composition ready …
- Very specific: line 177
add it to NOTICE.md's list of templates original to this repo
- Very specific: line 178
add it to a genre in templates/VIDEO_GENRES.template.json only if it earns a beat there — a template in no genre is fine.
- Very specific: line 180
update the counts in README, README.en, docs/16 and .github/repo-about.json — a test checks all seven against the folder
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Add a template
Two different jobs share this name, and picking the wrong one wastes an hour.
| the user wants | do this |
| an effect, overlay, transition or caption style | pull it — one command, §1 |
| a kind of frame the kit cannot draw | build it — §2 onward |
0. Never start from "what would be cool"
A template with no gap behind it is a twenty-third way to show a headline. Find the gap first, and be able to say it in one sentence before writing any CSS.
# what exists, and what each one is FOR
node -e "import('./scripts/video/lib/paths.mjs').then(m=>console.log(m.listTemplateIds().join('\n')))"
grep -n '^\*\*Role:\*\*' video-templates/CATALOG.md
# and how they MOVE — which techniques are well covered, which are nearly absent
node scripts/video/motion-index.mjsThe second command answers a question the first cannot. A gap is not only "no frame does this
job" — it is also "no frame moves this way". mask-sweep and clip-reveal have two samples
each; draw-on has thirteen. A new template that fills a thin row is worth more than one that
adds a fourteenth way to draw a line, and the counts tell you which is which.
Then read templates/VIDEO_GENRES.template.json and ask which beat has no good frame.
A real gap sounds like: "frame-chart-bars compares magnitudes and frame-split-compare
compares states — nothing can strike a claim down." A fake one sounds like "we could use
another dark statement frame."
Say the gap out loud to the user before building. They know what they publish; you are guessing from a folder listing.
If the user just says "a new template for today"
Do the survey, bring back two or three candidates with the gap each one fills, and let them pick. Do not build five because "new templates" was plural — five templates nobody needed is worse than one they will use.
A SIGNATURE FRAME every episode — how to do it without rotting the library
A series can ask for one bespoke frame per episode so no two videos look alike. That is a legitimate goal, and it is in tension with §0 above. Resolve it this way, not by suspending the rule:
The gap for a signature frame is the episode, not the library. It sounds like "this episode turns on 40 days of quarantine against 40 days of fundraising, and nothing in the library can hold two numbers that mirror each other and mean opposite things." It does not sound like "episode 7 needs its own look." If you cannot name the one image the episode turns on, the episode does not need a frame — it needs a better script.
Build ONE, for the beat that carries the video. Usually the reveal or the twist. The other fifteen scenes reuse library frames; that is what makes the signature one land.
Name it for its job, not its episode. frame-mirror-numbers, not frame-poveglia-40.
An episode-specific name guarantees nobody reuses it, which is how you end up with forty
single-use folders.
Every contract in §2 still applies — both aspects, both timeline keys, CATALOG entry, ambient layer, the lot. A signature frame that renders black is not distinctive, it is broken.
Review the pile every ~10 episodes. Frames used twice or more graduate into the general library and get documented as such. Frames used once and never again get deleted — leaving them costs a CATALOG row, a theme probe, and a slower test suite for nothing. This review is the whole reason the practice stays affordable; skip it and the library is landfill in a year.
1. Pulling from upstream is often the right answer
367 items live in the HyperFrames registry, and registry-watch.mjs reports what arrived
since the last check. For code-driven motion prompts and 12 visual style recipes (productui,
explainer, collage, handdrawn, pixel, lowpoly, generative, photoreal), also check
opus-55-videos (yihui-dev/awesome-opus5-5-videos) and opus-video-styles via
node scripts/install-skills.mjs --list.
node scripts/video/registry-watch.mjs # anything new upstream?
node scripts/video/add-template.mjs --list --grep caption # search
node scripts/video/add-template.mjs <name> <name> # pullWhat you get is building material, not a scene template. The command says so itself:
blocks and components ship compositions/ with no index.html, so listTemplateIds()
skips them and no script.json can name them. They are overlays and effects to compose
with. Turning one into a scene template still means writing both compositions by hand — at
which point you are in §2 anyway, just with a head start on the design.
Licence and attribution are handled: the installer writes a NOTICE.md with the source URL
and the pinned commit sha. Do not delete it.
2. Building one — the five files
Copy the shape of a recent template rather than inventing one. frame-checklist and
frame-timeline are the plainest.
video-templates/<id>/
├── index.html 16:9 — data-width="1920" data-height="1080"
├── compositions/portrait.html 9:16 — data-width="1080" data-height="1920"
├── meta.json { "id": "<id>", "name": "Human Name" }
├── hyperframes.json copy verbatim from any existing template
└── NOTICE.md who wrote it, why it exists, which slotsid is frame-<kebab>. The two compositions must expose the same slot names — a test
checks it, because two files drift the moment they are edited separately.
Generate both from one source. Every template added since v0.5.0 was emitted by a small script that takes shared markup, shared JS and per-aspect layout CSS. Writing the same file twice is how slot parity gets broken, and it is also how a fix lands in one aspect only.
The rules, all enforced by tests/templates.test.mjs
- Draw from data, never from a hardcoded value. If a bar length and its printed number can disagree, one day they will.
- No caller-facing text in the markup. Every visible string arrives through a slot and is
set in JS. Text sitting in the body renders on every video regardless of what the caller
passed — found three times here, twice after it reached a finished render. Decorative
punctuation (a quote mark, a tick) may be CSS
content; a word may not. - An empty slot removes its element, it does not render a placeholder. An empty heading reads as missing data; an absent one reads as a deliberate omission.
- No default is someone else's brand. No real URLs, no channel names in
data-composition-variables. - Vietnamese-capable fonts. Be Vietnam Pro, Lora, Alfa Slab One are known-good. Test with
ữ ệ ợ ằ— a font missing diacritics rendersbướcasbc.
Three traps that pass every test and still look wrong or stall rendering
1. A delayed animation with no start state shows its ending first.
.thing { animation: rise 0.5s ease 0.45s forwards; } /* wrong */
.thing { opacity: 0; animation: rise 0.5s ease 0.45s forwards; } /* base = the start */
.thing { animation: rise 0.5s ease 0.45s both; } /* or backwards fill */forwards does nothing during the delay — the element renders with its normal style, which
for a forwards animation is where it finishes. Half a second of the finished state, then
a snap back. Use both when the start state differs between aspects.
2. An animation must travel the same way as the thing it reveals. A divider sweeping in from
the left while a clip-path uncovers from the right reads as two animations that happen to
end together. Both real bugs, both in shipped-looking code, neither catchable by a test.
3. Missing sub-composition timeline registration (window.__timelines["portrait"]).
Every composition (both index.html and compositions/portrait.html) MUST register its timeline under both IDs:
window.__timelines = window.__timelines || {};
window.__timelines["main"] = window.__timelines["portrait"] = timeline;If compositions/portrait.html only registers "main" or omits "portrait", Puppeteer will wait 45 seconds for the sub-composition ready signal, causing a 10x render slowdown. Always register both keys.
3. Measure, document, wire up
node scripts/video/theme-probe.mjs --template <id> # writes theme-map.jsonThemes flip lightness only on dark canvases. An unmeasured template is flipped on a guess, which renders — wrongly, in exactly the way the theme system exists to prevent.
Then:
- a
## <id>section invideo-templates/CATALOG.md: role, best-for, and a slot table with real character limits you found by rendering long text, not by estimating - raise the count in
.github/workflows/ci.yml(listTemplateIds().length < N) - add it to
NOTICE.md's list of templates original to this repo - add it to a genre in
templates/VIDEO_GENRES.template.jsononly if it earns a beat there — a template in no genre is fine; a genre with a frame that does not fit is not - update the counts in README, README.en,
docs/16and.github/repo-about.json— a test checks all seven against the folder
4. Look at it. The tests cannot.
node scripts/video/template-sheet.mjs <id> --out /tmp/check.jpg
node scripts/video/template-sheet.mjs <id> --aspect 16:9 --out /tmp/check-l.jpgSample the animation, not just the settled frame — tile three moments and open the image. Everything visual ever caught in this repo was caught this way: two templates rendering 1920×1080 inside a 9:16 video with correct CSS and a correct viewport; a strike-through that crossed only the first line of a two-line claim; an eleven-character name wrapping so a shutter wiped two lines instead of one.
Render with real content at realistic length, and check the awkward cases: the longest string a caller might pass, an empty optional slot, one item in a list that expects four.
data-composition-variablesdoes not reach the renderer. Those are the editor's preview defaults;composeTemplate({ inputs: {} })comes back blank. Pass inputs explicitly, or read the defaults out of the HTML and pass those.
5. Ship it
node --test tests/*.test.mjsOne PR per template batch, with the strip image in the description so a reviewer sees the frames without checking out the branch. Say which gap each one fills — if that sentence is hard to write, the template probably should not exist.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

