57
Handle credit
Crediting whoever built the demo on screen: an X handle, a GitHub repo, a YouTube channel

Add the "Handle credit" video component (X, light) from everestchris.com to this project.
1. Download https://ai-component-library-dun.vercel.app/projects/handle-credit.zip?v=976775bc794b and unzip it into components/handle-credit/. Read the README.md and CLAUDE.md in it.
2. Render it: cd components/handle-credit && npx hyperframes@0.8.162 render . --variables '{"variant":"0","theme":"light"}' -o handle-credit.mp4
3. Give me the path of the MP4. The text, names and timings live in the CONFIG block at the top of the script in index.html; change nothing there unless I ask.Code
One file. The project download adds the fonts, skins and motion kit it runs on.
1<!doctype html>2<html lang="en" data-composition-variables='[{"id":"variant","label":"Variant","type":"enum","default":"0","options":[{"value":"0","label":"X handle"},{"value":"1","label":"GitHub repo"},{"value":"2","label":"YouTube channel"}]},{"id":"theme","label":"Theme","type":"enum","default":"light","options":[{"value":"light","label":"Light"},{"value":"dark","label":"Dark"}]}]'>3<head><meta charset="UTF-8"><meta name="viewport" content="width=1920, height=1080"><link rel="stylesheet" href="assets/fonts/fonts.css">4<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script><script src="assets/kit/motion/motion.js"></script>5<style>6*{box-sizing:border-box;margin:0;padding:0}html,body{width:1920px;height:1080px;overflow:hidden;background:transparent}7#root{position:relative;width:1920px;height:1080px;font-family:Inter,sans-serif;-webkit-font-smoothing:antialiased}8#aroll{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}9#overlay{position:absolute;inset:0;--surface:#fff;--ink:#0a0a0a;--muted:#606060;--line:rgba(0,0,0,.08);--shadow:0 1px 2px rgba(0,0,0,.08),0 10px 24px -12px rgba(0,0,0,.3)}10#overlay[data-theme=dark]{--surface:#18181a;--ink:#fafafa;--muted:#bababa;--line:rgba(255,255,255,.1);--shadow:0 1px 2px rgba(0,0,0,.25),0 10px 24px -12px rgba(0,0,0,.5)}11#credit{position:absolute;left:80px;bottom:80px;width:max-content;max-width:1760px;opacity:0;color:var(--ink)}12#plate{position:absolute;inset:0;border:1px solid var(--line);border-radius:16px;background:var(--surface);box-shadow:var(--shadow)}13#row{position:relative;display:flex;align-items:center;gap:16px;padding:20px 24px;white-space:nowrap}14#mark{width:32px;height:32px;flex:none;background:currentColor;mask:var(--mark) center/contain no-repeat;-webkit-mask:var(--mark) center/contain no-repeat}15#youtube{display:none;width:40px;height:28px;flex:none}16#identity{font-size:34px;font-weight:500;line-height:40px;letter-spacing:-.02em}17#credit.repo #identity{font-family:'JetBrains Mono',monospace;font-size:32px;letter-spacing:-.03em;font-weight:400}18#credit.channel #mark{display:none}#credit.channel #youtube{display:block}19</style></head>20<body><div id="root" data-composition-id="main" data-start="0" data-duration="8" data-width="1920" data-height="1080">21<video id="aroll" class="clip" src="assets/still/aroll-right.mp4" muted playsinline data-start="0" data-duration="8" data-track-index="0"></video>22<div id="overlay" class="clip" data-start="0" data-duration="8" data-track-index="1"><div id="credit"><div id="plate"></div><div id="row"><span id="mark"></span><img id="youtube" src="assets/marks/youtube.svg" alt=""><span id="identity"></span></div></div></div></div>23<script>24const CONFIG={duration:8,aroll:'assets/still/aroll-right.mp4',timing:{enter:.4,reveal:.3,out:7.3,exit:.3},variants:{25'0':{kind:'handle',identity:'@OpenAI',mark:'assets/logos/x-si.svg',url:'https://x.com/OpenAI'},26'1':{kind:'repo',identity:'openai/codex',mark:'assets/logos/github.svg',url:'https://github.com/openai/codex'},27'2':{kind:'channel',identity:'OpenAI',mark:'assets/marks/youtube.svg',url:'https://www.youtube.com/OpenAI'}28}};29const vars=window.__hyperframes?.getVariables?.()||{};const vi=['0','1','2'].includes(String(vars.variant))?String(vars.variant):'0';const theme=vars.theme==='dark'?'dark':'light';const V=CONFIG.variants[vi],$=s=>document.querySelector(s);30$('#overlay').dataset.theme=theme;$('#credit').className=V.kind;$('#identity').textContent=V.identity;$('#mark').style.setProperty('--mark',`url("${V.mark}")`);if(V.kind==='channel')$('#youtube').src=V.mark;31if(CONFIG.aroll)$('#aroll').src=CONFIG.aroll;else $('#aroll').remove();32document.fonts.ready.then(()=>{const K=KitMotion,T=CONFIG.timing,tl=gsap.timeline({paused:true});33K.fadeUp(tl,'#credit',T.enter,{distance:6,blur:0,duration:T.reveal});K.fadeOut(tl,'#credit',T.out,{duration:T.exit});34// Fade samples have intentionally reduced composited contrast; audit the fully held identity.35K.drive(tl,0,CONFIG.duration,p=>{const t=p*CONFIG.duration,el=$('#credit');if(t<T.enter+T.reveal||t>T.out)el.setAttribute('data-layout-ignore','');else el.removeAttribute('data-layout-ignore');});36// fadeOut primes opacity 1 at build time. Restore the empty initial state after registering it.37gsap.set('#credit',{opacity:0,y:6,filter:'blur(0px)'});tl.set({}, {},CONFIG.duration);window.__timelines=window.__timelines||{};window.__timelines.main=tl;tl.seek(0);38});39</script></body></html>