Communitygithub.com

d0-hyperframe

Créez des vidéos de marque D0 avec HyperFrames. Comprend l'extraction d'actifs, la configuration de projet, la mise en page des scènes, les animations GSAP, les normes des composants TG et les règles de transition.

Qu'est-ce que d0-hyperframe ?

Ce skill fournit un workflow complet pour la création de vidéos de marque D0 à l'aide de HyperFrames HTML et GSAP. Il est conçu pour les développeurs et les créateurs de contenu qui souhaitent produire des vidéos animées de haute qualité, cohérentes avec l'identité visuelle de D0, sans les limitations des transitions de type PPT. Le skill définit des règles strictes pour les polices, les couleurs, la mise en page et les animations, et s'appuie sur un modèle à calque persistant unique où l'arrière-plan et les éléments fixes restent immobiles pendant que les composants de contenu individuels entrent et sortent avec des transitions fluides et chevauchées. Il est compatible avec les agents utilisant HyperFrames CLI (via npx) et GSAP, et nécessite le skill `d0-brand` pour les spécifications typographiques ultimes. Le workflow inclut des scripts d'initialisation de projet, l'extraction d'actifs (logo D0, avatar JPEG), la configuration des tokens CSS de marque, la structuration HTML du stage, les animations GSAP avec des règles de transition précises (stagger, chevauchement), et des étapes de linting et de prévisualisation via la CLI HyperFrames. Les transitions au niveau des composants, avec un chevauchement de 0,2 à 0,3 seconde, éliminent les arrêts brusques et donnent une sensation de flux continu, essentielle pour un rendu professionnel.

Compatible avec~Claude Code✓Codex CLI~Cursor✓Antigravity
npx skills add https://github.com/scof-real/d0-hyperframe-skill/tree/main/skills/d0-hyperframe

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

D0 HyperFrame – Création vidéo

Workflow complet pour réaliser des vidéos de marque D0 avec HyperFrames HTML + GSAP. Ce document est la seule référence — polices, couleurs, mise en page, animations, règles de transition sont définies ici.

La spécification typographique du skill d0-brand fait autorité ; ce skill ne fait que réécrire les règles complémentaires liées à la production vidéo.


Mots déclencheurs

  • "Fais une vidéo D0" / "d0 hyperframe"
  • "Utilise hyperframes pour faire une vidéo" / "/d0-hyperframe"

Étape 0 — Initialisation du projet et des assets

Recommandé : utiliser le script d'initialisation fourni avec le skill

Après avoir installé le dépôt, exécutez le script contenu dans ce skill. Il initialise un projet HyperFrames et copie le logo D0, l'avatar D0 ainsi que toutes les polices nécessaires :

bash "${CODEX_HOME:-$HOME/.codex}/skills/d0-hyperframe/scripts/bootstrap_project.sh" .

Si le projet est déjà initialisé, synchronisez uniquement les assets de marque :

bash "${CODEX_HOME:-$HOME/.codex}/skills/d0-hyperframe/scripts/bootstrap_project.sh" . --assets-only

Le script nécessite Node.js 18+ et npx. La CLI HyperFrames est exécutée à la demande via npx hyperframes@latest, aucun paquet tiers n'est copié dans le dépôt du skill.

Optionnel : écraser D0_AVATAR et le logo depuis le HTML source

Extraire D0_AVATAR et le logo depuis le HTML source

Le HTML source de l'affiche contient généralement deux types d'images base64 :

AssetTypeCaractéristiqueUsage
Logo D0PNG, environ 12–16 KB.brand img ou PNG la plus courteEn haut à gauche de toutes les scènes
D0_AVATARJPEG, environ 100 KB.av ou JPEG la plus longueAvatar des composants TG
python3 - << 'EOF'
import re, base64, os

with open('SOURCE.html', 'r') as f:
    src = f.read()

os.makedirs('assets', exist_ok=True)

# Logo (PNG la plus courte)
pngs = re.findall(r'(data:image/png;base64,[A-Za-z0-9+/=]+)', src)
logo_b64 = min(pngs, key=len)
with open('assets/d0-logo.png', 'wb') as f:
    f.write(base64.b64decode(logo_b64.split(',')[1]))

# D0_AVATAR (JPEG la plus longue)
jpegs = re.findall(r'data:image/jpeg;base64,([A-Za-z0-9+/=]+)', src)
avatar = max(jpegs, key=len)
with open('assets/d0-avatar.jpg', 'wb') as f:
    f.write(base64.b64decode(avatar))

print("assets/ prêt :", os.listdir('assets'))
EOF

Polices (méthode manuelle)

mkdir -p fonts
cp /chemin/vers/d0-hyperframe/assets/fonts/*.woff2 fonts/
# Nécessite : InstrumentSerif-Regular.woff2, InstrumentSerif-Italic.woff2
#       OpenSans-400/600/700/800-normal.woff2

Initialisation du projet (méthode manuelle)

npx hyperframes@latest init . --non-interactive --example blank --skill=d0-hyperframe

Étape 1 — Tokens de marque (CSS)

:root {
  --bg:    #06060d;
  --pu2:   #b3a8f7;
  --white: #f2f2f5;
  --t2:    #8d8d98;
  --t3:    #5a5a66;
  --green: #3ddc84;
  --red:   #f87171;
  --gold:  #f7a93a;
  --bdr:   #23232c;
  --bdr2:  #2e2e39;
  --grad:  linear-gradient(120deg, #5468F5 0%, #9B4FD6 34%, #C25C9A 62%, #DD8B57 100%);
}

@font-face { font-family:'Instrument Serif'; src:url('fonts/InstrumentSerif-Regular.woff2') format('woff2'); font-weight:400; font-style:normal; }
@font-face { font-family:'Instrument Serif'; src:url('fonts/InstrumentSerif-Italic.woff2')  format('woff2'); font-weight:400; font-style:italic; }
@font-face { font-family:'Open Sans'; src:url('fonts/OpenSans-400-normal.woff2') format('woff2'); font-weight:400; }
@font-face { font-family:'Open Sans'; src:url('fonts/OpenSans-600-normal.woff2') format('woff2'); font-weight:600; }
@font-face { font-family:'Open Sans'; src:url('fonts/OpenSans-700-normal.woff2') format('woff2'); font-weight:700; }
@font-face { font-family:'Open Sans'; src:url('fonts/OpenSans-800-normal.woff2') format('woff2'); font-weight:800; }

Étape 2 — Structure du stage (calque persistant + couche composant)

Modèle central : un seul calque d'arrière-plan fixe, le contenu est découpé en composants. L'arrière-plan + les éléments fixes (logo/footer/rail supérieur) appartiennent au calque persistant, immobile tout au long de la vidéo ; les titres, données, panneaux TG, graphiques, etc., sont chacun des composants .blk indépendants, qui entrent et sortent individuellement. Les transitions se produisent au niveau des composants, pas au niveau de l'écran entier — c'est la clé pour se débarrasser des coupures brutales style PPT.

Squelette HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D0 · [Titre de la vidéo]</title>
<style>/* tokens + CSS de la scène */</style>
</head>
<body>
<div id="main"
  data-composition-id="main"
  data-start="0"
  data-duration="[Durée totale en secondes]"
  data-width="1920"
  data-height="1080">

  <!-- ── Calque persistant : immobile, aucune animation tl (voir Étape 3) ── -->
  <div class="bg"></div>
  <div class="rail"></div>
  <div class="logo"></div>
  <div class="foot-tag">Agentic Trading for Every Market.</div>
  <div class="foot-url">getdonut.ai</div>

  <!-- ── Couche contenu : groupée par beat, composants entrent/sortent en décalé (voir Étape 6) ── -->
  <!-- beat 1 -->
  <div class="blk" id="b1-title">...</div>
  <div class="blk" id="b1-sub">...</div>
  <!-- beat 2 -->
  <div class="blk" id="b2-stat">...</div>
  <div class="blk" id="b2-tg">...</div>

</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
<script>/* Timeline GSAP */</script>
</body>
</html>

CSS du stage (calque persistant + couche contenu)

/* Conteneur du stage */
#main {
  position: absolute; inset: 0; overflow: hidden;
  font-family: 'Open Sans', sans-serif; color: var(--white);
}

/* Arrière-plan persistant — fixe tout au long de la vidéo, jamais dans l'animation tl */
.bg {
  position: absolute; inset: 0; width: 1920px; height: 1080px; z-index: 0;
  background: var(--bg);
  background-image:
    radial-gradient(ellipse 46% 58% at 76% 50%, rgba(150,128,255,.16) 0%, transparent 60%),
    radial-gradient(ellipse 62% 50% at 8%   4%, rgba(110,100,255,.10) 0%, transparent 56%);
}

/* Rail dégradé supérieur — fixe, un seul pour toute la vidéo */
.rail {
  position: absolute; top: 0; left: 0; right: 0; height: 5px; z-index: 10;
  background: var(--grad);
}

/* Composant contenu — unité minimale d'animation, caché par défaut, entre et sort individuellement */
.blk { position: absolute; opacity: 0; z-index: 2; }

L'ancien modèle avec chaque écran .scene complet, arrière-plan inclu, glissait en bloc → effet PPT + arrêts brusques. Le nouveau modèle n'a qu'un seul arrière-plan fixe, le contenu est découpé en composants .blk, les transitions se produisent au niveau des composants (voir Étape 6).


Étape 3 — Spécifications des éléments fixes (non négociables)

Les trois éléments suivants restent identiques dans toutes les scènes et n'ont pas d'animation d'entrée ou de sortie :

ÉlémentPositionTaille policeDescription
Logo DonutEn haut à gauche top:40px left:72px200×76pxCSS background, pas de <img>
Agentic Trading for Every Market.En bas à gauche bottom:48px left:72px27pxInstrument Serif italic, --pu2
getdonut.aiEn bas à droite bottom:50px right:72px14pxOpen Sans, --t3
/* Logo — CSS background, pas d'opacity:0 */
.logo {
  position: absolute; top: 40px; left: 72px; z-index: 10;
  width: 200px; height: 76px;
  background: url('assets/d0-logo.png') left center / contain no-repeat;
}

/* Footer — directement visible, sans animation */
.foot-tag {
  position: absolute; bottom: 48px; left: 72px; z-index: 10;
  font-family: 'Instrument Serif', serif; font-style: italic;
  font-size: 27px; color: var(--pu2);
}

.foot-url {
  position: absolute; bottom: 50px; right: 72px; z-index: 10;
  font-size: 14px; font-weight: 700; letter-spacing: .06em; color: var(--t3); opacity: 0;
}

Les éléments fixes appartiennent au calque persistant, visibles dès l'image 0, aucune animation tl n'est écrite. foot-tag est directement visible ; foot-url peut conserver un léger fondu unique, mais ce n'est pas obligatoire.


Étape 4 — Principes de mise en page

Équilibre gauche-droite, éliminer le vide central

  • Priorité à la disposition à deux colonnes : texte / données à gauche, composant TG / image à droite
  • Avec une image de fond de personnage à droite : positionnée en absolu pour remplir la droite, superposée d'un masque dégradé de gauche à droite
.scene-char {
  position: absolute; top:0; right:0; bottom:0; width:62%;
  background: url('assets/bg-char.png') right center / cover no-repeat;
  z-index: 0;
}
.scene-char::after {
  content:''; position:absolute; inset:0;
  background: linear-gradient(to right,
    var(--bg) 0%, rgba(6,6,13,.82) 18%, rgba(6,6,13,.45) 45%, transparent 100%);
}
  • La zone de texte à gauche doit avoir position: relative; z-index: 2 pour être superposée à l'image de fond

Taille de police minimale

Sur la base de la vidéo D0 Thorp Engine, ne pas descendre en dessous de :

NiveauTaille minimalePolice
Titre principal80pxInstrument Serif
Sous-titre de scène56pxInstrument Serif
Kick label / eyebrow18pxOpen Sans 700 uppercase
Corps de texte / feature bullet22pxOpen Sans
Point d'ancrage de donnée (stat-val)48pxInstrument Serif
Footer tag27pxInstrument Serif italic
Texte dans les composants TG13px (minimal acceptable)Open Sans

Étape 5 — Spécifications des composants TG

Avatar : doit utiliser D0_AVATAR

/* Grand avatar (header, 40px) */
.av  { width:40px; height:40px; border-radius:50%; flex:none;
       background: url('assets/d0-avatar.jpg') center/cover no-repeat; }

/* Petit avatar (ligne de message, 28px) */
.mav { width:28px; height:28px; border-radius:50%; flex:none; margin-top:2px;
       background: url('assets/d0-avatar.jpg') center/cover no-repeat; }

Ne pas utiliser de balise <img> pour éviter que HyperFrames ne détecte des nœuds media en double (avertissement lint). Ne pas utiliser de dégradé de repli, le fichier D0_AVATAR réel est obligatoire.

Structure du panneau TG

<div id="tg-panel">
  <div class="tg-chrome">
    <div class="dot r"></div><div class="dot y"></div><div class="dot g"></div>
    <div class="tg-url">t.me / D0_Bot</div>
  </div>
  <div class="tg-hdr">
    <div class="av"></div>
    <div>
      <div class="tg-nm">D0</div>
      <div class="tg-st">bot · online</div>
    </div>
  </div>
  <div class="tg-body">
    <div class="msg-user">prompt utilisateur</div>
    <div class="msg-bot">
      <div class="mav"></div>
      <div class="bbubble">contenu de la réponse de D0</div>
    </div>
  </div>
</div>

Étape 6 — Règles de transition (non négociables)

Principe central : l'arrière-plan ne bouge pas, ce sont les composants qui bougent. L'"effet PPT" vient du défilement complet de la scène (y compris l'arrière-plan) — le spectateur perd son point d'ancrage stable ; les "arrêts brusques" viennent de l'enchaînement bout à bout de l'animation de sortie et de l'animation d'entrée — il y a un instant de silence total entre les deux. La solution aux deux problèmes est la même phrase : arrière-plan fixe + entrées/sorties de composants décalées et chevauchées.

Transition par défaut : entrées/sorties de composants en décalé (element cross-stagger)

L'arrière-plan + les éléments fixes (logo/footer/rail) restent immobiles. Chaque changement de beat ne fait bouger que les composants de contenu :

  • Les composants de l'ancien beat sortent l'un après l'autre (stagger, easing .in, léger déplacement + fondu)
  • Les composants du nouveau beat entrent l'un après l'autre (stagger, easing .out)
  • Les deux sont chevauchement d'environ 0,2–0,3 s — l'ancien n'a pas fini de sortir que le nouveau commence déjà à entrer. C'est la clé pour éliminer les arrêts brusques.
// Changement de beat : sortie des anciens en décalé, entrée des nouveaux en décalé, avec chevauchement (pas bout à bout)
function beat(outEls, inEls, t) {
  outEls.forEach((el, i) =>
    tl.to(el, { opacity:0, y:-30, duration:0.45, ease:'power2.in' }, t + i*0.06));
  inEls.forEach((el, i) =>
    tl.fromTo(el, { opacity:0, y:40 },
      { opacity:1, y:0, duration:0.6, ease:'expo.out' }, t + 0.2 + i*0.08));  // +0.2 = chevauchement
}
// Utilisation : beat(['#b1-title','#b1-sub'], ['#b2-stat','#b2-tg'], 4.0);
  • Le déplacement est faible (20–40 px) ; la direction peut être uniforme (par exemple, tous vers le haut) pour créer une "sensation de courant d'air", mais l'arrière-plan ne participe jamais.
  • Quand il y a beaucoup de composants, le stagger maintient une action continue à l'écran, évitant "entrée simultanée → tout gelé".

Quand utiliser une transition d'écran complet

Uniquement pour les grandes sections (par exemple, carte titre de marque → section données), et seulement la couche contenu est poussée, pas l'arrière-plan — les composants de cette section sont regroupés dans un conteneur #grp puis poussés :

// Push-slide (ne pousse que le conteneur contenu, l'arrière-plan .bg ne bouge pas)
tl.to('#grpA',     { x:-1920, duration:0.55, ease:'power3.inOut' }, t);
tl.fromTo('#grpB', { x:1920, opacity:1 }, { x:0, duration:0.55, ease:'power3.inOut' }, t);

// Blur crossfade (transition émotionnelle, généralement pour la dernière transition)
tl.to('#grpC', { filter:'blur(20px)', opacity:0, duration:0.65, ease:'power2.in' }, t);
tl.fromTo('#grpD', { filter:'blur(20px)', opacity:0 },
  { filter:'blur(0px)', opacity:1, duration:0.65, ease:'power2.out' }, t);

❌ Interdit : scène entière (y compris l'arrière-plan) qui glisse, zoom dans un coin, zoom d'écran entier, enchaînement out/in bout à bout sans chevauchement.


Étape 7 — Règles d'animation GSAP

Obligations

const tl = gsap.timeline({ paused: true });
// ... tweens ...
window.__timelines['main'] = tl;
  • Utiliser tl.fromTo() plutôt que tl.from() (pour garantir la détermination du seek HyperFrames)
  • Pour les animations répétées, utiliser Math.floor(duration / cycle) - 1, interdiction de repeat: -1
  • Pour plusieurs groupes d'animations sur le même élément, ajouter overwrite: 'auto'
  • Utiliser l'easing .out pour l'entrée et l'easing .in pour la sortie

Mise en page d'abord, animation ensuite

Écrire d'abord l'état final de l'élément (positionnement CSS), puis utiliser fromTo pour décrire le chemin d'entrée :

// ✅ Correct
tl.fromTo('#title', { opacity:0, y:40 }, { opacity:1, y:0, duration:0.8, ease:'expo.out' }, 0.3);

Pas d'animation sur le calque persistant

.bg, .rail, .logo, .foot-tag, .foot-url sont fixes tout au long de la vidéo, les animations ne concernent que les composants .blk. Dès que l'arrière-plan participe à un déplacement, on retombe dans l'effet PPT — les transitions ne font bouger que la couche contenu (voir Étape 6 beat()).


Étape 8 — Lint & Aperçu

npx hyperframes lint     # 0 erreurs obligatoire
npx hyperframes preview  # http://localhost:300x, rechargement à chaud
Avertissement courantTraitement
overlapping_gsap_tweensAjouter overwrite:'auto'
duplicate_media_discovery_riskRemplacer <img> par background:url() en CSS
composition_file_too_largeIgnorer si fichier unique <500 lignes

Dépendances et sources des assets

  • Skill d0-brand : autorité ultime pour les polices, tailles et principes de marque, doit être installé avec ce skill.
  • CLI HyperFrames : obtenue à la demande via npx hyperframes@latest.
  • GSAP : version CDN 3.14.2 utilisée dans l'exemple ; en cas de mise à niveau, relancer lint et validation seek.
  • assets/fonts/ : Instrument Serif et Open Sans ; les fichiers de licence se trouvent dans le répertoire de police correspondant.
  • assets/brand/ : Logo D0 et avatar D0, destinés uniquement aux membres autorisés de l'équipe Donut pour le contenu de marque D0.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills associés