All components
54

Point counter

Corner badge counting through "4 reasons Claude Code beat Codex this week"

Prompt for your agentpaste into Claude Code or Codex
Add the "Point counter" video component (Progress dots, light) from everestchris.com to this project.

1. Download https://ai-component-library-dun.vercel.app/projects/point-counter.zip?v=eb572a092695 and unzip it into components/point-counter/. Read the README.md and CLAUDE.md in it.
2. Render it: cd components/point-counter && npx hyperframes@0.8.162 render . --variables '{"variant":"1","theme":"light"}' -o point-counter.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.

index.htmlhtmlDownload
1<!doctype html>
2<html lang="en" data-composition-variables='[{"id":"variant","label":"Variant","type":"enum","default":"0","options":[{"value":"0","label":"Numeral"},{"value":"1","label":"Progress dots"},{"value":"2","label":"Checklist"}]},{"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"><script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script><script src="assets/kit/motion/motion.js"></script>
4<style>
5*{box-sizing:border-box;margin:0;padding:0}html,body{width:1920px;height:1080px;overflow:hidden;background:transparent}#root{width:100%;height:100%;font-family:Inter,sans-serif;-webkit-font-smoothing:antialiased;position:relative}.aroll{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
6#overlay{position:absolute;inset:0;--surface:#fff;--ink:#0a0a0a;--muted:#636363;--edge:rgba(0,0,0,.1);--track:#d8d8d8;--pending:rgba(0,0,0,.18);--shadow:0 1px 2px rgba(0,0,0,.12),0 10px 26px -12px rgba(0,0,0,.35)}#overlay[data-theme=dark]{--surface:#18181a;--ink:#fafafa;--muted:#b9b9bb;--edge:rgba(255,255,255,.14);--track:#555557;--pending:rgba(255,255,255,.24);--shadow:0 1px 2px rgba(0,0,0,.3),0 10px 26px -12px rgba(0,0,0,.55)}
7#badge{position:absolute;right:96px;top:96px;color:var(--ink);background:var(--surface);border:1px solid var(--edge);box-shadow:var(--shadow);border-radius:22px;padding:24px 28px;opacity:0}
8#badge.numeral{width:380px;display:flex;align-items:center;gap:24px}.fraction{display:flex;align-items:baseline;white-space:nowrap;font-variant-numeric:tabular-nums;letter-spacing:-.03em;font-size:56px;line-height:64px;font-weight:600}.denom{color:var(--muted);font-size:28px;letter-spacing:-.01em;margin-left:7px;font-weight:500}.topic{font-size:32px;line-height:36px;font-weight:500;letter-spacing:-.02em;white-space:nowrap}#badge.numeral .topic{width:190px}#badge.numeral #number{display:block;height:64px;overflow:hidden}
9#badge.dots{width:350px;padding:24px 28px}.topline{display:flex;justify-content:space-between;align-items:center;gap:20px}.smallcount{font-size:28px;font-weight:500;line-height:32px;font-variant-numeric:tabular-nums;color:var(--muted)}#dots{display:flex;gap:12px;margin-top:22px}.dot{position:relative;width:18px;height:18px;border-radius:50%;background:var(--track)}.dotfill{position:absolute;inset:0;border-radius:50%;background:var(--ink);opacity:0}
10#badge.checklist{width:374px;padding:24px 28px}.listhead{display:flex;justify-content:space-between;align-items:center;padding-bottom:18px;border-bottom:1px solid var(--edge);font-size:24px;font-weight:500;line-height:32px;color:var(--muted)}#rows{display:flex;flex-direction:column;gap:22px;padding-top:22px}.checkrow{display:flex;align-items:center;gap:18px;font-size:28px;line-height:36px;font-weight:500;letter-spacing:-.015em}.box{width:30px;height:30px;border-radius:8px;border:2px solid var(--pending);flex:none;display:grid;place-items:center}.box svg{width:22px;height:22px;overflow:visible}.box path{fill:none;stroke:var(--surface);stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round}
11</style></head>
12<body><div id="root" data-composition-id="main" data-start="0" data-duration="8" data-width="1920" data-height="1080"><video id="aroll" class="clip aroll" src="assets/still/aroll-left.mp4" muted playsinline data-start="0" data-duration="8" data-track-index="0"></video><div id="overlay" class="clip" data-start="0" data-duration="8" data-track-index="1"><div id="badge"></div></div></div>
13<script>
14const CONFIG={duration:8,aroll:true,points:['Repo context','Small edits','Test runs','Review'],timing:{enter:.45,first:.85,advance:2,interval:1.45,exit:7.25},variants:{'0':{kind:'numeral'},'1':{kind:'dots'},'2':{kind:'checklist',label:'Covered'}}};
15const vars=window.__hyperframes?.getVariables?.()||{},vi=['0','1','2'].includes(String(vars.variant))?String(vars.variant):'0',theme=vars.theme==='dark'?'dark':'light',V=CONFIG.variants[vi],P=CONFIG.points,$=s=>document.querySelector(s),badge=$('#badge');$('#overlay').dataset.theme=theme;badge.className=V.kind;if(!CONFIG.aroll)$('#aroll').remove();
16if(vi==='0')badge.innerHTML='<div class="fraction"><span id="number">1</span><span class="denom">/ '+P.length+'</span></div><span class="topic" id="topic"></span>';
17else if(vi==='1')badge.innerHTML='<div class="topline"><span class="topic" id="topic"></span><span class="smallcount"><span id="number">1</span> / '+P.length+'</span></div><div id="dots">'+P.map((_,i)=>'<span class="dot"><span class="dotfill" id="dot'+i+'"></span></span>').join('')+'</div>';
18else badge.innerHTML='<div class="listhead"><span>'+V.label+'</span><span><span id="number">0</span> / '+P.length+'</span></div><div id="rows">'+P.map((text,i)=>'<div class="checkrow"><span class="box" id="check'+i+'"><svg viewBox="0 0 24 24"><path d="M5 12.5 9.5 17 19 7"/></svg></span><span>'+text+'</span></div>').join('')+'</div>';
19if($('#topic'))$('#topic').textContent=P[0];
20document.fonts.ready.then(()=>{const K=KitMotion,tl=gsap.timeline({paused:true}),T=CONFIG.timing,ink=theme==='dark'?'#fafafa':'#0a0a0a',track=theme==='dark'?'rgba(255,255,255,.24)':'rgba(0,0,0,.18)';K.fadeUp(tl,badge,T.enter,{distance:12,blur:0,duration:.3});
21if(vi!=='2'){K.numberPop(tl,'#number',{from:1,to:P.length,steps:P.length-1,at:T.advance+.125,every:T.interval,duration:.25,stagger:0,distance:8,blur:0,ease:'out'});for(let i=1;i<P.length;i++)K.textSwap(tl,'#topic',P[i],T.advance+(i-1)*T.interval,{distance:3,blur:0,duration:.125});}
22P.forEach((_,i)=>{const at=i===0?T.first:T.advance+(i-1)*T.interval;if(vi==='1'&&i>0)tl.fromTo('#dot'+i,{opacity:0,scale:.75},{opacity:1,scale:1,duration:.25,ease:'power3.out',immediateRender:false},at+.125);if(vi==='2'){K.checkboxCheck(tl,'#check'+i,at,{from:{backgroundColor:'transparent',borderColor:track},to:{backgroundColor:ink,borderColor:ink}});K.numberPop(tl,'#number',{from:i,to:i+1,at:at,duration:.15,stagger:0,distance:4,blur:0,ease:'out'});}});
23if(vi==='1')gsap.set('#dot0',{opacity:1,scale:1});
24K.fadeOut(tl,badge,T.exit,{duration:.3});gsap.set(badge,{opacity:0,y:12});tl.set({}, {},CONFIG.duration);window.__timelines.main=tl;tl.seek(0);});
25</script></body></html>
Download project17 MB