Liveloop

An interactive timeline for social media. Every post is a tiny app you can play, save, and remix.

Product

  • Feed
  • Create
  • Claude Code plugin
  • Blog

Legal

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DMCA

Project

  • Templates
© 2026 Liveloop. All rights reserved.
LiveloopVersion history

v1Current

@liveloop · 5/17/2026, 11:52:13 AM

Initial version — all lines are new.

+<style>
+ html,body{height:100%;margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;background:#0b1020;color:#f8fafc;overflow:hidden;}
+ .wrap{display:flex;flex-direction:column;height:100%;box-sizing:border-box;padding:.8rem;gap:.5rem;}
+ .top{display:flex;align-items:baseline;justify-content:space-between;gap:.5rem;}
+ h1{margin:0;font-size:1rem;}
+ #count{font-size:.78rem;color:#94a3b8;}
+ #stage{flex:1;min-height:0;display:flex;align-items:center;justify-content:center;}
+ #frame{position:relative;height:100%;aspect-ratio:3/4;max-width:100%;border-radius:1rem;border:4px solid #334155;background:#1e293b;background-size:cover;background-position:center;overflow:hidden;box-shadow:0 10px 30px rgba(0,0,0,.45);}
+ #ph{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.4rem;color:#94a3b8;font-size:.78rem;text-align:center;padding:1rem;}
+ #ph .big{font-size:3rem;}
+ .sticker{position:absolute;transform:translate(-50%,-50%);line-height:1;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;filter:drop-shadow(0 3px 7px rgba(0,0,0,.45));}
+ .sticker.sel{outline:2px dashed #fbbf24;outline-offset:5px;border-radius:8px;}
+ .palette{display:flex;gap:.35rem;overflow-x:auto;padding:.2rem;}
+ .pal{flex:none;font:inherit;font-size:1.5rem;width:2.7rem;height:2.7rem;border:2px solid #334155;background:#1e293b;border-radius:.6rem;cursor:pointer;touch-action:manipulation;}
+ .controls{display:flex;gap:.4rem;align-items:center;justify-content:center;flex-wrap:wrap;}
+ .btn{font:inherit;font-size:.8rem;font-weight:600;border:0;border-radius:9999px;padding:.45rem .95rem;background:#3b82f6;color:#fff;cursor:pointer;touch-action:manipulation;display:inline-flex;align-items:center;gap:.3rem;}
+ .ghost{background:transparent;border:1px solid #475569;color:#cbd5e1;}
+ .sz{font:inherit;font-weight:800;font-size:1rem;border:1px solid #475569;background:transparent;color:#cbd5e1;width:2.1rem;height:2.1rem;border-radius:.5rem;cursor:pointer;touch-action:manipulation;}
+ .hint{font-size:.68rem;color:#64748b;text-align:center;}
+ .hidden{display:none;}
+</style>
+<div class="wrap">
+ <div class="top"><h1>🧑‍🎤 Costume Studio</h1><span id="count"></span></div>
+ <div id="stage">
+ <div id="frame">
+ <div id="ph"><div class="big">🙂</div><div>Add your photo, then tap accessories to dress it up</div></div>
+ </div>
+ </div>
+ <div class="palette" id="palette"></div>
+ <div class="controls">
+ <label class="btn">📷 Photo<input type="file" accept="image/*" id="pick" class="hidden"></label>
+ <button class="sz" id="minus" type="button">−</button>
+ <button class="sz" id="plus" type="button">+</button>
+ <button class="btn ghost" id="del" type="button">✕ Remove</button>
+ <button class="btn ghost" id="clear" type="button">Clear all</button>
+ </div>
+ <div class="hint">Tap an accessory to add it · drag to place · tap a sticker to select</div>
+</div>
+<script>
+(function(){
+ var PALETTE=['🎩','🤠','👑','🧢','👒','🎓','⛑️','🪖','🕶️','👓','🥸','🧣','👔','🎀','💍','🌟'];
+ var frame=document.getElementById('frame'),ph=document.getElementById('ph'),
+ palette=document.getElementById('palette'),count=document.getElementById('count'),
+ pick=document.getElementById('pick');
+ var stickers=[],sel=null;
+
+ function onTap(el,fn){
+ var sx=0,sy=0,armed=false;
+ el.addEventListener('pointerdown',function(e){ armed=true;sx=e.clientX;sy=e.clientY; });
+ el.addEventListener('pointercancel',function(){ armed=false; });
+ el.addEventListener('pointerup',function(e){
+ if(!armed) return; armed=false;
+ if(Math.abs(e.clientX-sx)<14&&Math.abs(e.clientY-sy)<14) fn();
+ });
+ }
+ function updateCount(){
+ count.textContent=stickers.length?stickers.length+(stickers.length===1?' piece':' pieces'):'';
+ }
+ function layout(s){
+ s.el.style.left=(s.x*100)+'%';
+ s.el.style.top=(s.y*100)+'%';
+ s.el.style.fontSize=s.size+'px';
+ }
+ function select(s){
+ sel=s;
+ stickers.forEach(function(o){ o.el.classList.toggle('sel',o===s); });
+ }
+ function bindDrag(s){
+ var dragging=false;
+ s.el.addEventListener('pointerdown',function(e){
+ dragging=true; select(s);
+ try{ s.el.setPointerCapture(e.pointerId); }catch(_){}
+ e.preventDefault();
+ });
+ s.el.addEventListener('pointermove',function(e){
+ if(!dragging) return;
+ var r=frame.getBoundingClientRect();
+ s.x=Math.max(0,Math.min(1,(e.clientX-r.left)/r.width));
+ s.y=Math.max(0,Math.min(1,(e.clientY-r.top)/r.height));
+ layout(s);
+ e.preventDefault();
+ });
+ function endDrag(e){ dragging=false; try{ s.el.releasePointerCapture(e.pointerId); }catch(_){} }
+ s.el.addEventListener('pointerup',endDrag);
+ s.el.addEventListener('pointercancel',endDrag);
+ }
+ function addSticker(emoji){
+ var s={emoji:emoji,x:0.5,y:0.38,size:56,el:document.createElement('div')};
+ s.el.className='sticker'; s.el.textContent=emoji;
+ frame.appendChild(s.el);
+ stickers.push(s);
+ layout(s); bindDrag(s); select(s); updateCount();
+ s.el.animate([{transform:'translate(-50%,-50%) scale(.4)'},{transform:'translate(-50%,-50%) scale(1.15)'},{transform:'translate(-50%,-50%) scale(1)'}],{duration:230,easing:'ease-out'});
+ }
+ PALETTE.forEach(function(emoji){
+ var b=document.createElement('button');
+ b.type='button'; b.className='pal'; b.textContent=emoji;
+ onTap(b,function(){ addSticker(emoji); });
+ palette.appendChild(b);
+ });
+
+ onTap(document.getElementById('minus'),function(){
+ if(!sel) return; sel.size=Math.max(20,sel.size-12); layout(sel);
+ });
+ onTap(document.getElementById('plus'),function(){
+ if(!sel) return; sel.size=Math.min(240,sel.size+12); layout(sel);
+ });
+ onTap(document.getElementById('del'),function(){
+ if(!sel) return;
+ var i=stickers.indexOf(sel);
+ sel.el.remove(); stickers.splice(i,1);
+ sel=stickers.length?stickers[stickers.length-1]:null;
+ if(sel) select(sel);
+ updateCount();
+ });
+ onTap(document.getElementById('clear'),function(){
+ stickers.forEach(function(s){ s.el.remove(); });
+ stickers=[]; sel=null; updateCount();
+ });
+
+ pick.addEventListener('change',function(e){
+ var file=e.target.files&&e.target.files[0]; if(!file) return;
+ var reader=new FileReader();
+ reader.onload=function(){
+ var img=new Image();
+ img.onload=function(){
+ try{
+ var max=760,sc=Math.min(1,max/Math.max(img.width,img.height));
+ var c=document.createElement('canvas');
+ c.width=Math.round(img.width*sc); c.height=Math.round(img.height*sc);
+ c.getContext('2d').drawImage(img,0,0,c.width,c.height);
+ frame.style.backgroundImage='url("'+c.toDataURL('image/jpeg',0.85)+'")';
+ }catch(err){ frame.style.backgroundImage='url("'+reader.result+'")'; }
+ ph.style.display='none';
+ };
+ img.onerror=function(){ frame.style.backgroundImage='url("'+reader.result+'")'; ph.style.display='none'; };
+ img.src=reader.result;
+ };
+ reader.readAsDataURL(file);
+ });
+})();
+</script>

v1Current

@liveloop · 5/17/2026, 11:52:13 AM

Initial version — all lines are new.

+<style>
+ html,body{height:100%;margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;background:#0b1020;color:#f8fafc;overflow:hidden;}
+ .wrap{display:flex;flex-direction:column;height:100%;box-sizing:border-box;padding:.8rem;gap:.5rem;}
+ .top{display:flex;align-items:baseline;justify-content:space-between;gap:.5rem;}
+ h1{margin:0;font-size:1rem;}
+ #count{font-size:.78rem;color:#94a3b8;}
+ #stage{flex:1;min-height:0;display:flex;align-items:center;justify-content:center;}
+ #frame{position:relative;height:100%;aspect-ratio:3/4;max-width:100%;border-radius:1rem;border:4px solid #334155;background:#1e293b;background-size:cover;background-position:center;overflow:hidden;box-shadow:0 10px 30px rgba(0,0,0,.45);}
+ #ph{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.4rem;color:#94a3b8;font-size:.78rem;text-align:center;padding:1rem;}
+ #ph .big{font-size:3rem;}
+ .sticker{position:absolute;transform:translate(-50%,-50%);line-height:1;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;filter:drop-shadow(0 3px 7px rgba(0,0,0,.45));}
+ .sticker.sel{outline:2px dashed #fbbf24;outline-offset:5px;border-radius:8px;}
+ .palette{display:flex;gap:.35rem;overflow-x:auto;padding:.2rem;}
+ .pal{flex:none;font:inherit;font-size:1.5rem;width:2.7rem;height:2.7rem;border:2px solid #334155;background:#1e293b;border-radius:.6rem;cursor:pointer;touch-action:manipulation;}
+ .controls{display:flex;gap:.4rem;align-items:center;justify-content:center;flex-wrap:wrap;}
+ .btn{font:inherit;font-size:.8rem;font-weight:600;border:0;border-radius:9999px;padding:.45rem .95rem;background:#3b82f6;color:#fff;cursor:pointer;touch-action:manipulation;display:inline-flex;align-items:center;gap:.3rem;}
+ .ghost{background:transparent;border:1px solid #475569;color:#cbd5e1;}
+ .sz{font:inherit;font-weight:800;font-size:1rem;border:1px solid #475569;background:transparent;color:#cbd5e1;width:2.1rem;height:2.1rem;border-radius:.5rem;cursor:pointer;touch-action:manipulation;}
+ .hint{font-size:.68rem;color:#64748b;text-align:center;}
+ .hidden{display:none;}
+</style>
+<div class="wrap">
+ <div class="top"><h1>🧑‍🎤 Costume Studio</h1><span id="count"></span></div>
+ <div id="stage">
+ <div id="frame">
+ <div id="ph"><div class="big">🙂</div><div>Add your photo, then tap accessories to dress it up</div></div>
+ </div>
+ </div>
+ <div class="palette" id="palette"></div>
+ <div class="controls">
+ <label class="btn">📷 Photo<input type="file" accept="image/*" id="pick" class="hidden"></label>
+ <button class="sz" id="minus" type="button">−</button>
+ <button class="sz" id="plus" type="button">+</button>
+ <button class="btn ghost" id="del" type="button">✕ Remove</button>
+ <button class="btn ghost" id="clear" type="button">Clear all</button>
+ </div>
+ <div class="hint">Tap an accessory to add it · drag to place · tap a sticker to select</div>
+</div>
+<script>
+(function(){
+ var PALETTE=['🎩','🤠','👑','🧢','👒','🎓','⛑️','🪖','🕶️','👓','🥸','🧣','👔','🎀','💍','🌟'];
+ var frame=document.getElementById('frame'),ph=document.getElementById('ph'),
+ palette=document.getElementById('palette'),count=document.getElementById('count'),
+ pick=document.getElementById('pick');
+ var stickers=[],sel=null;
+
+ function onTap(el,fn){
+ var sx=0,sy=0,armed=false;
+ el.addEventListener('pointerdown',function(e){ armed=true;sx=e.clientX;sy=e.clientY; });
+ el.addEventListener('pointercancel',function(){ armed=false; });
+ el.addEventListener('pointerup',function(e){
+ if(!armed) return; armed=false;
+ if(Math.abs(e.clientX-sx)<14&&Math.abs(e.clientY-sy)<14) fn();
+ });
+ }
+ function updateCount(){
+ count.textContent=stickers.length?stickers.length+(stickers.length===1?' piece':' pieces'):'';
+ }
+ function layout(s){
+ s.el.style.left=(s.x*100)+'%';
+ s.el.style.top=(s.y*100)+'%';
+ s.el.style.fontSize=s.size+'px';
+ }
+ function select(s){
+ sel=s;
+ stickers.forEach(function(o){ o.el.classList.toggle('sel',o===s); });
+ }
+ function bindDrag(s){
+ var dragging=false;
+ s.el.addEventListener('pointerdown',function(e){
+ dragging=true; select(s);
+ try{ s.el.setPointerCapture(e.pointerId); }catch(_){}
+ e.preventDefault();
+ });
+ s.el.addEventListener('pointermove',function(e){
+ if(!dragging) return;
+ var r=frame.getBoundingClientRect();
+ s.x=Math.max(0,Math.min(1,(e.clientX-r.left)/r.width));
+ s.y=Math.max(0,Math.min(1,(e.clientY-r.top)/r.height));
+ layout(s);
+ e.preventDefault();
+ });
+ function endDrag(e){ dragging=false; try{ s.el.releasePointerCapture(e.pointerId); }catch(_){} }
+ s.el.addEventListener('pointerup',endDrag);
+ s.el.addEventListener('pointercancel',endDrag);
+ }
+ function addSticker(emoji){
+ var s={emoji:emoji,x:0.5,y:0.38,size:56,el:document.createElement('div')};
+ s.el.className='sticker'; s.el.textContent=emoji;
+ frame.appendChild(s.el);
+ stickers.push(s);
+ layout(s); bindDrag(s); select(s); updateCount();
+ s.el.animate([{transform:'translate(-50%,-50%) scale(.4)'},{transform:'translate(-50%,-50%) scale(1.15)'},{transform:'translate(-50%,-50%) scale(1)'}],{duration:230,easing:'ease-out'});
+ }
+ PALETTE.forEach(function(emoji){
+ var b=document.createElement('button');
+ b.type='button'; b.className='pal'; b.textContent=emoji;
+ onTap(b,function(){ addSticker(emoji); });
+ palette.appendChild(b);
+ });
+
+ onTap(document.getElementById('minus'),function(){
+ if(!sel) return; sel.size=Math.max(20,sel.size-12); layout(sel);
+ });
+ onTap(document.getElementById('plus'),function(){
+ if(!sel) return; sel.size=Math.min(240,sel.size+12); layout(sel);
+ });
+ onTap(document.getElementById('del'),function(){
+ if(!sel) return;
+ var i=stickers.indexOf(sel);
+ sel.el.remove(); stickers.splice(i,1);
+ sel=stickers.length?stickers[stickers.length-1]:null;
+ if(sel) select(sel);
+ updateCount();
+ });
+ onTap(document.getElementById('clear'),function(){
+ stickers.forEach(function(s){ s.el.remove(); });
+ stickers=[]; sel=null; updateCount();
+ });
+
+ pick.addEventListener('change',function(e){
+ var file=e.target.files&&e.target.files[0]; if(!file) return;
+ var reader=new FileReader();
+ reader.onload=function(){
+ var img=new Image();
+ img.onload=function(){
+ try{
+ var max=760,sc=Math.min(1,max/Math.max(img.width,img.height));
+ var c=document.createElement('canvas');
+ c.width=Math.round(img.width*sc); c.height=Math.round(img.height*sc);
+ c.getContext('2d').drawImage(img,0,0,c.width,c.height);
+ frame.style.backgroundImage='url("'+c.toDataURL('image/jpeg',0.85)+'")';
+ }catch(err){ frame.style.backgroundImage='url("'+reader.result+'")'; }
+ ph.style.display='none';
+ };
+ img.onerror=function(){ frame.style.backgroundImage='url("'+reader.result+'")'; ph.style.display='none'; };
+ img.src=reader.result;
+ };
+ reader.readAsDataURL(file);
+ });
+})();
+</script>
← Version history