Communitygithub.com

d0-hyperframe

HyperFrames로 D0 브랜드 비디오를 제작합니다.素材 추출, 프로젝트 설정, 장면 레이아웃, GSAP 애니메이션, TG 컴포넌트 규격, 전환 규칙을 포함합니다.

d0-hyperframe란 무엇인가요?

이 스킬은 HyperFrames HTML과 GSAP 애니메이션을 사용하여 D0 브랜드 비디오를 제작하는 완전한 워크플로우를 제공합니다. 글꼴, 색상, 레이아웃, 애니메이션, 전환 규칙 등 모든 브랜드 비주얼 요소가 이 파일에 정의되어 있으며, `d0-brand` 스킬을 글꼴 규격의 최종 권위로 참조합니다. 주로 Claude Code, Codex, Cursor 등의 AI 에이전트 플랫폼에서 사용되며, 사용자가 "D0 비디오를 만들어 줘" 또는 "/d0-hyperframe" 명령어로 트리거할 수 있습니다. 스킬은 초기화 스크립트를 통해 프로젝트와 브랜드素材를 신속하게 설정하고, 고정 배경과 개별 `.blk` 컴포넌트의 계층적 구조를 사용하여 장면 간 전환이 아닌 컴포넌트 레벨에서 전환을 수행함으로써 "PPT 느낌"을 제거합니다. 또한 TG 패널 컴포넌트 규격과 GSAP 타임라인 애니메이션 규칙을 제공하며, lint 및 미리보기 도구를 포함합니다.

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

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

D0 HyperFrame 비디오 제작

HyperFrames HTML + GSAP으로 D0 브랜드 비디오를 제작하는 완전한 워크플로우입니다. 이 파일을 유일한 권위로 삼으십시오 — 글꼴, 색상, 레이아웃, 애니메이션, 전환 규칙이 모두 여기 정의되어 있습니다.

글꼴 규격은 d0-brand 스킬이 최종 권위이며, 본 스킬은 비디오 제작 관련 추가 규정만 덮어씁니다.


트리거 구문

  • "D0 비디오 만들어 줘" / "d0 hyperframe"
  • "hyperframes로 비디오 만들어 줘" / "/d0-hyperframe"

Step 0 — 프로젝트 및素材 초기화

권장: 스킬 제공 초기화 스크립트 사용

리포지토리를 설치한 후, 본 스킬 내의 스크립트를 실행하십시오. 이 스크립트는 HyperFrames 프로젝트를 초기화하고 D0 로고, D0 아바타 및 필요한 모든 글꼴을 복사합니다:

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

프로젝트가 이미 초기화된 경우, 브랜드素材만 동기화합니다:

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

스크립트는 Node.js 18+와 npx에 의존합니다. HyperFrames CLI는 npx hyperframes@latest를 통해 필요 시 실행되며, Skill 리포지토리에 서드파티 패키지를 복사하지 않습니다.

선택 사항: 소스 HTML에서 D0_AVATAR와 로고 덮어쓰기

소스 HTML에서 D0_AVATAR와 로고 추출

소스 포스터 HTML에는 일반적으로 두 가지 유형의 base64 이미지가 인라인으로 포함되어 있습니다:

자산유형특징용도
D0 로고PNG, 약 12–16 KB.brand img 또는 가장 짧은 PNG모든 장면의 왼쪽 위 모서리
D0_AVATARJPEG, 약 100 KB.av 또는 가장 긴 JPEGTG 컴포넌트의 아바타
python3 - << 'EOF'
import re, base64, os

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

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

# 로고 (가장 짧은 PNG)
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)
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/ ready:", os.listdir('assets'))
EOF

글꼴 (수동 방식)

mkdir -p fonts
cp /path/to/d0-hyperframe/assets/fonts/*.woff2 fonts/
# 필요: InstrumentSerif-Regular.woff2, InstrumentSerif-Italic.woff2
#       OpenSans-400/600/700/800-normal.woff2

프로젝트 초기화 (수동 방식)

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

Step 1 — 브랜드 토큰 (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; }

Step 2 — 무대 구조 (고정 스테이지 + 컴포넌트 계층)

핵심 모델: 하나의 고정 배경 위에 내용을 컴포넌트로 분할합니다. 배경 + 고정 요소(로고/푸터/상단 레일)는 고정 계층에 속하며, 전체에 걸쳐 움직이지 않습니다; 제목, 데이터, TG 패널, 차트 등은 각각 독립적인 .blk 컴포넌트로서 각자 입장/퇴장합니다. 전환은 컴포넌트 레벨에서 발생하며, 전체 화면 단위가 아닙니다 — 이것이 "PPT 하드 컷"을 제거하는 근본입니다.

HTML 뼈대

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D0 · [비디오 제목]</title>
<style>/* 토큰 + 장면 CSS */</style>
</head>
<body>
<div id="main"
  data-composition-id="main"
  data-start="0"
  data-duration="[총 초]"
  data-width="1920"
  data-height="1080">

  <!-- ── 고정 계층: 전체에 걸쳐 움직이지 않음, tl 애니메이션 미작성 (Step 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>

  <!-- ── 내용 계층: beat별로 그룹화, 컴포넌트가 각자 교차하여 입장/퇴장 (Step 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>/* GSAP 타임라인 */</script>
</body>
</html>

무대 CSS (고정 계층 + 내용 계층)

/* 무대 컨테이너 */
#main {
  position: absolute; inset: 0; overflow: hidden;
  font-family: 'Open Sans', sans-serif; color: var(--white);
}

/* 고정 배경 — 전체에 걸쳐 고정, 절대 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 {
  position: absolute; top: 0; left: 0; right: 0; height: 5px; z-index: 10;
  background: var(--grad);
}

/* 내용 컴포넌트 — 애니메이션의 최소 단위, 기본적으로 숨김, 각자 입장/퇴장 */
.blk { position: absolute; opacity: 0; z-index: 2; }

이전 모델은 각 전체 화면 .scene이 자체 배경과 함께 통째로 슬라이드되어 → PPT 느낌 + 끊김을 유발했습니다. 새 모델은 하나의 고정 배경만 있으며, 내용을 .blk 컴포넌트로 분할하고 전환은 컴포넌트 레벨에서 발생합니다 (Step 6 참조).


Step 3 — 고정 요소 규격 (협상 불가)

다음 세 요소는 모든 장면에서 일관되게 유지되며, 입장 또는 퇴장 애니메이션을 작성하지 않습니다:

요소위치글자 크기설명
Donut 로고왼쪽 위 top:40px left:72px200×76pxCSS background, <img> 미사용
Agentic Trading for Every Market.왼쪽 아래 bottom:48px left:72px27pxInstrument Serif 이탤릭, --pu2
getdonut.ai오른쪽 아래 bottom:50px right:72px14pxOpen Sans, --t3
/* 로고 — CSS background, 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;
}

/* 푸터 — 직접 보임, 애니메이션 없음 */
.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;
}

고정 요소는 고정 계층에 속하며, 0번 프레임부터 보여야 하고, 전체에 걸쳐 tl 애니메이션을 전혀 작성하지 않습니다. foot-tag는 직접 보여야 하며; foot-url은 일회성 미세 페이드인을 유지할 수 있지만, 강제 사항은 아닙니다.


Step 4 — 레이아웃 원칙

좌우 균형, 중앙 공백 제거

  • 2열 레이아웃 우선: 텍스트/데이터는 왼쪽, TG 컴포넌트/이미지는 오른쪽
  • 오른쪽에 캐릭터 배경 이미지가 있는 경우: 절대 위치로 오른쪽 전체를 채우고, 왼쪽에서 오른쪽으로 가는 그라데이션 마스크를 겹쳐 놓습니다.
.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%);
}
  • 왼쪽 텍스트 영역은 position: relative; z-index: 2로 설정하여 배경 이미지 위에 겹쳐지도록 합니다.

글자 크기 최소 기준

D0 Thorp Engine 비디오를 기준으로, 다음보다 작을 수 없습니다:

계층최소 글자 크기글꼴
주 제목80pxInstrument Serif
장면 부제목56pxInstrument Serif
Kick label / eyebrow18pxOpen Sans 700 대문자
본문 / feature bullet22pxOpen Sans
데이터 앵커 (stat-val)48pxInstrument Serif
Footer 태그27pxInstrument Serif 이탤릭
TG 컴포넌트 내부 텍스트13px (허용 가능 최소값)Open Sans

Step 5 — TG 컴포넌트 규격

아바타: 반드시 D0_AVATAR 사용

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

/* 작은 아바타 (메시지 행, 28px) */
.mav { width:28px; height:28px; border-radius:50%; flex:none; margin-top:2px;
       background: url('assets/d0-avatar.jpg') center/cover no-repeat; }

<img> 태그를 사용하지 마십시오 — HyperFrames가 중복 미디어 노드를 감지하여 경고를 표시할 수 있습니다. 그라데이션 fallback을 사용하지 마십시오 — 반드시 실제 D0_AVATAR 파일이어야 합니다.

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</div>
    <div class="msg-bot">
      <div class="mav"></div>
      <div class="bbubble">D0 응답 내용</div>
    </div>
  </div>
</div>

Step 6 — 전환 규칙 (협상 불가)

핵심 원칙: 배경은 움직이지 않고, 컴포넌트가 움직입니다. "PPT 느낌"은 전체 화면 .scene(배경 포함)이 함께 슬라이드되어 나가면서 발생합니다 — 시청자는 안정적인 기준점을 잃습니다; "끊김"은 out 애니메이션과 in 애니메이션이 처음과 끝을 연결하여 나타납니다 — 중간에 완전히 정지하는 순간이 생깁니다. 두 문제의 해결책은 동일합니다: 고정 배경 + 컴포넌트가 교차하여 겹쳐서 입장/퇴장합니다.

기본 전환: 컴포넌트 레벨 교차 입/퇴장 (element cross-stagger)

배경 + 고정 요소(로고/푸터/레일)는 전체에 걸쳐 움직이지 않습니다. 각 beat 전환 시 내용 컴포넌트만 움직입니다:

  • 이전 beat의 컴포넌트가 차례로 퇴장 (stagger, .in ease, 미세 이동 + 페이드 아웃)
  • 새 beat의 컴포넌트가 차례로 입장 (stagger, .out ease)
  • 두 과정이 시간상 약 0.2–0.3초 겹칩니다 — 이전 것이 완전히 사라지기 전에 새 것이 들어오기 시작합니다. 이것이 끊김을 제거하는 핵심입니다.
// beat 전환: 이전 그룹이 퇴장하고 새 그룹이 입장, 시간적 중첩 (처음과 끝 연결이 아님)
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 = 중첩
}
// 사용법: beat(['#b1-title','#b1-sub'], ['#b2-stat','#b2-tg'], 4.0);
  • 이동량은 작게(20–40px); 방향은 통일할 수 있습니다(예: 모두 위로 이동하여 "페이지 넘김 기류"를 만듦). 그러나 배경은 절대 참여하지 않습니다.
  • 컴포넌트가 많을 때는 stagger를 활용하여 화면에 지속적인 움직임을 유지하고 "동시 입장 → 함께 멈춤"을 방지합니다.

전체 화면 전환을 사용해야 하는 경우

큰 분할(예: 브랜드 타이틀 카드 → 데이터 섹션)에서만 드물게 사용하며, 내용 계층만 밀고 배경은 밀지 않습니다 — 해당 섹션의 컴포넌트를 #grp 컨테이너로 감싼 후 밀어냅니다:

// Push-slide (내용 컨테이너만 밀고, 배경 .bg는 움직이지 않음)
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 크로스페이드 (감정 전환, 보통 마지막 전환에 사용)
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);

❌ 금지: 전체 화면 .scene(배경 포함) 슬라이드 아웃, 모서리 확대/축소, 전체 화면 zoom, out/in을 처음과 끝으로 연결하여 중첩 없이 사용하는 것.


Step 7 — GSAP 애니메이션 규칙

반드시 준수

const tl = gsap.timeline({ paused: true });
// ...tweens...
window.__timelines['main'] = tl;
  • tl.fromTo()를 사용하고 tl.from()은 사용하지 마십시오 (HyperFrames seek 결정성 보장)
  • 반복 애니메이션은 Math.floor(duration / cycle) - 1을 사용하고, repeat: -1은 금지
  • 동일 요소의 여러 애니메이션 그룹에 overwrite: 'auto' 추가
  • 입장에는 .out easing, 퇴장에는 .in easing 사용

레이아웃 우선, 애니메이션은 그 다음

먼저 요소의 최종 상태(CSS 위치)를 작성한 후, fromTo로 입장 경로를 설명합니다:

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

고정 계층에 애니메이션 추가 금지

.bg, .rail, .logo, .foot-tag, .foot-url은 전체에 걸쳐 고정되며, 애니메이션은 오직 .blk 컴포넌트에만 발생합니다. 배경이 한 번 움직이면 즉시 PPT 느낌으로 돌아갑니다 — 전환은 내용 계층만 움직입니다 (Step 6 beat() 참조).


Step 8 — Lint & 미리보기

npx hyperframes lint     # 반드시 0 errors
npx hyperframes preview  # http://localhost:300x, 핫 리로드
일반적인 경고처리
overlapping_gsap_tweensoverwrite:'auto' 추가
duplicate_media_discovery_riskCSS background:url()을 사용하여 <img> 대체
composition_file_too_large단일 파일 <500행이면 무시 가능

종속성 및 자산 출처

  • d0-brand Skill: 글꼴, 글자 크기 및 브랜드 원칙의 최종 권위이며, 본 Skill과 함께 설치되어야 합니다.
  • HyperFrames CLI: npx hyperframes@latest를 통해 필요 시 가져옵니다.
  • GSAP: 예제는 3.14.2 CDN 버전을 고정하여 사용합니다; 버전을 업그레이드하는 경우 먼저 lint와 seek 검증을 다시 실행하십시오.
  • assets/fonts/: Instrument Serif와 Open Sans; 라이선스 파일은 해당 글꼴 디렉터리에 있습니다.
  • assets/brand/: D0 로고 및 D0 아바타, 권한을 받은 Donut 팀 구성원만 D0 브랜드 콘텐츠에 사용할 수 있습니다.

Individual skills in this repo

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

관련 스킬