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

@remy_play · 6/9/2026, 10:51:33 PM

Initial version — all lines are new.

+<style>
+ html,body{height:100%;margin:0;overflow:hidden;background:#FFF4E6;}
+ *{box-sizing:border-box;}
+ #wrap{position:relative;height:100%;width:100%;display:flex;flex-direction:column;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;background:radial-gradient(110% 80% at 50% 0%,#FFFAF1 0%,#FFEFD9 70%,#FBE3C4 100%);-webkit-tap-highlight-color:transparent;user-select:none;-webkit-user-select:none;}
+ #head{padding:1.1rem 1.2rem .25rem;}
+ #head h1{margin:0;font-family:"Instrument Serif",Georgia,"Times New Roman",serif;font-weight:400;font-size:2.2rem;line-height:1;color:#4a3a55;}
+ #head p{margin:.2rem 0 0;font-size:.78rem;color:#a08d77;font-weight:500;}
+ #scene{margin:.55rem 1.1rem .15rem;background:linear-gradient(135deg,#7C5CFF22,#FF5A1F22);border:1px solid rgba(124,92,255,.25);border-radius:16px;padding:.8rem .9rem;text-align:center;}
+ #scene .em{font-size:2.3rem;line-height:1.25;letter-spacing:.1em;}
+ #scene .pr{margin-top:.15rem;font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:#8a76b8;}
+ #row{display:flex;gap:8px;padding:.55rem 1.1rem .2rem;}
+ #inp{flex:1;border:1px solid rgba(120,90,50,.25);background:rgba(255,255,255,.8);border-radius:999px;padding:.62rem .95rem;font-size:16px;color:#4a3a55;font-family:inherit;outline:none;}
+ #send{border:0;border-radius:999px;background:linear-gradient(135deg,#7C5CFF,#FF5A1F);color:#fff;font-weight:700;font-size:.85rem;padding:0 1.15rem;cursor:pointer;}
+ #send:active{transform:scale(.95);}
+ #note{padding:.25rem 1.25rem 0;font-size:.66rem;color:#b3a084;font-weight:600;min-height:1em;}
+ #wall{flex:1;min-height:0;overflow-y:auto;padding:.55rem 1.1rem 1.1rem;-webkit-overflow-scrolling:touch;}
+ .cap{background:rgba(255,255,255,.85);border:1px solid rgba(120,90,50,.14);border-radius:14px;padding:.6rem .75rem;margin-bottom:.5rem;display:flex;align-items:center;gap:.6rem;}
+ .cap.mine{border-color:rgba(124,92,255,.5);background:rgba(124,92,255,.08);}
+ .cap .t{flex:1;font-size:.86rem;color:#4a3a55;line-height:1.35;word-break:break-word;}
+ .cap .h{flex-shrink:0;border:0;background:transparent;font-size:.8rem;font-weight:700;color:#b3a084;cursor:pointer;padding:.3rem .4rem;border-radius:999px;font-family:inherit;}
+ .cap .h.on{color:#E14C8F;}
+ .cap .h:active{transform:scale(1.2);}
+ #empty{text-align:center;font-family:"Instrument Serif",Georgia,serif;font-style:italic;font-size:1.05rem;color:#a08d77;padding:1.4rem 1rem;}
+</style>
+<div id="wrap">
+ <div id="head"><h1>Caption This</h1><p>One scene a week. The wall belongs to everyone.</p></div>
+ <div id="scene"><div class="em" id="em"></div><div class="pr">caption this scene</div></div>
+ <div id="row">
+ <input id="inp" maxlength="90" placeholder="your caption…">
+ <button id="send">post</button>
+ </div>
+ <div id="note"></div>
+ <div id="wall"><div id="empty">be the first to caption it…</div></div>
+</div>
+<script>
+(function(){
+ var LL=window.liveloop||null;
+ var muted = LL ? LL.muted : true;
+ if(LL && LL.onMute){ try{ LL.onMute(function(m){ muted=m; }); }catch(e){} }
+ if(LL && LL.declareMedia){ try{ LL.declareMedia({sound:true}); }catch(e){} }
+ var _ac=null;
+ function actx(){ if(!_ac){ try{ _ac=new (window.AudioContext||window.webkitAudioContext)(); }catch(e){ _ac=null; } } return _ac; }
+ function pop(f){
+ if(muted) return; var c=actx(); if(!c) return;
+ var t=c.currentTime, o=c.createOscillator(), g=c.createGain();
+ o.type='sine'; o.frequency.setValueAtTime(f||520,t);
+ o.frequency.exponentialRampToValueAtTime((f||520)*1.5,t+0.07);
+ g.gain.setValueAtTime(0.0001,t); g.gain.exponentialRampToValueAtTime(0.12,t+0.01);
+ g.gain.exponentialRampToValueAtTime(0.0001,t+0.22);
+ o.connect(g); g.connect(c.destination); o.start(t); o.stop(t+0.25);
+ }
+
+ var SCENES=[
+ '🐈‍⬛ 💻 📉',
+ '🦆 🕶️ 🏖️',
+ '🧙‍♂️ 🛒 🥕',
+ '🐕 🎓 📜',
+ '🤖 ☕ 🌧️',
+ '🐧 🎤 🌟',
+ '🦀 🏋️ 💪',
+ '🐸 👑 🏰'
+ ];
+ var week=Math.floor(Date.now()/604800000);
+ var idx=((week%SCENES.length)+SCENES.length)%SCENES.length;
+ document.getElementById('em').textContent=SCENES[idx];
+ var CAPS='caps-w'+week, HEARTS='hearts-w'+week;
+
+ var inp=document.getElementById('inp'), send=document.getElementById('send');
+ var wall=document.getElementById('wall'), note=document.getElementById('note');
+ var hasData=!!(LL && LL.data && LL.data.submit);
+ var myIds={}, myHeart=null, busy=false;
+
+ function setNote(t){ note.textContent=t||''; }
+
+ function render(caps,hearts){
+ var tally={};
+ hearts.forEach(function(r){ var c=r.data && r.data.cap; if(c) tally[c]=(tally[c]||0)+1; });
+ wall.innerHTML='';
+ if(!caps.length){
+ var e=document.createElement('div'); e.id='empty';
+ e.textContent='be the first to caption it…';
+ wall.appendChild(e); return;
+ }
+ caps.sort(function(a,b){ return (tally[b.id]||0)-(tally[a.id]||0); });
+ caps.forEach(function(r){
+ var div=document.createElement('div');
+ div.className='cap'+(myIds[r.id]?' mine':'');
+ var t=document.createElement('div'); t.className='t';
+ t.textContent=String(r.data && r.data.text || '').slice(0,90);
+ var h=document.createElement('button');
+ h.className='h'+(myHeart===r.id?' on':'');
+ h.textContent='❤ '+(tally[r.id]||0);
+ h.addEventListener('click',function(){
+ if(!hasData || myIds[r.id]) return;
+ myHeart=r.id; pop(700);
+ try{ LL.data.submit(HEARTS,{cap:r.id},{mode:'keep_last'}).then(refresh); }catch(e){}
+ render(caps,hearts.filter(function(x){ return !x._mine; }).concat([{data:{cap:r.id},_mine:true}]));
+ });
+ div.appendChild(t); div.appendChild(h); wall.appendChild(div);
+ });
+ }
+
+ function refresh(){
+ if(!hasData) return;
+ try{
+ Promise.all([
+ LL.data.list(CAPS,{order:'recent',limit:40}),
+ LL.data.list(HEARTS,{order:'recent',limit:500}),
+ LL.data.mine(CAPS),
+ LL.data.mine(HEARTS)
+ ]).then(function(res){
+ var caps=(res[0]&&res[0].records)||[];
+ var hearts=(res[1]&&res[1].records)||[];
+ myIds={};
+ ((res[2]&&res[2].records)||[]).forEach(function(r){ myIds[r.id]=true; if(r.data&&r.data.text&&!inp.value) inp.value=r.data.text; });
+ var mh=((res[3]&&res[3].records)||[])[0];
+ if(mh && mh.data) myHeart=mh.data.cap||null;
+ render(caps,hearts);
+ }).catch(function(){});
+ }catch(e){}
+ }
+
+ function submit(){
+ var text=(inp.value||'').trim().slice(0,90);
+ if(!text || busy) return;
+ if(!hasData){
+ // editor preview — no shared data yet
+ render([{id:'me',data:{text:text}}],[]);
+ myIds['me']=true;
+ setNote('shared captions go live once this loop is published');
+ pop(560); return;
+ }
+ busy=true; setNote('posting…');
+ try{
+ LL.data.submit(CAPS,{text:text},{mode:'keep_last'}).then(function(r){
+ busy=false;
+ if(r && r.ok===false){ setNote('could not post — try again'); return; }
+ setNote('on the wall! (yours is highlighted — post again to edit)');
+ pop(560); refresh();
+ },function(){ busy=false; setNote('could not post — try again'); });
+ }catch(e){ busy=false; }
+ }
+ send.addEventListener('click',submit);
+ inp.addEventListener('keydown',function(e){ if(e.key==='Enter'){ e.preventDefault(); submit(); } });
+
+ // gentle polling while visible
+ var timer=null;
+ function startPoll(){ if(timer) return; timer=setInterval(refresh,25000); }
+ function stopPoll(){ if(timer){ clearInterval(timer); timer=null; } }
+ if(LL && LL.onVisibility){ try{ LL.onVisibility(function(v){ if(v){ refresh(); startPoll(); } else stopPoll(); }); }catch(e){} }
+ document.addEventListener('visibilitychange',function(){ if(document.hidden) stopPoll(); else { refresh(); startPoll(); } });
+
+ if(hasData){ refresh(); startPoll(); }
+ else setNote('preview mode — the live wall appears on the published loop');
+})();
+</script>

v1Current

@remy_play · 6/9/2026, 10:51:33 PM

Initial version — all lines are new.

+<style>
+ html,body{height:100%;margin:0;overflow:hidden;background:#FFF4E6;}
+ *{box-sizing:border-box;}
+ #wrap{position:relative;height:100%;width:100%;display:flex;flex-direction:column;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;background:radial-gradient(110% 80% at 50% 0%,#FFFAF1 0%,#FFEFD9 70%,#FBE3C4 100%);-webkit-tap-highlight-color:transparent;user-select:none;-webkit-user-select:none;}
+ #head{padding:1.1rem 1.2rem .25rem;}
+ #head h1{margin:0;font-family:"Instrument Serif",Georgia,"Times New Roman",serif;font-weight:400;font-size:2.2rem;line-height:1;color:#4a3a55;}
+ #head p{margin:.2rem 0 0;font-size:.78rem;color:#a08d77;font-weight:500;}
+ #scene{margin:.55rem 1.1rem .15rem;background:linear-gradient(135deg,#7C5CFF22,#FF5A1F22);border:1px solid rgba(124,92,255,.25);border-radius:16px;padding:.8rem .9rem;text-align:center;}
+ #scene .em{font-size:2.3rem;line-height:1.25;letter-spacing:.1em;}
+ #scene .pr{margin-top:.15rem;font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:#8a76b8;}
+ #row{display:flex;gap:8px;padding:.55rem 1.1rem .2rem;}
+ #inp{flex:1;border:1px solid rgba(120,90,50,.25);background:rgba(255,255,255,.8);border-radius:999px;padding:.62rem .95rem;font-size:16px;color:#4a3a55;font-family:inherit;outline:none;}
+ #send{border:0;border-radius:999px;background:linear-gradient(135deg,#7C5CFF,#FF5A1F);color:#fff;font-weight:700;font-size:.85rem;padding:0 1.15rem;cursor:pointer;}
+ #send:active{transform:scale(.95);}
+ #note{padding:.25rem 1.25rem 0;font-size:.66rem;color:#b3a084;font-weight:600;min-height:1em;}
+ #wall{flex:1;min-height:0;overflow-y:auto;padding:.55rem 1.1rem 1.1rem;-webkit-overflow-scrolling:touch;}
+ .cap{background:rgba(255,255,255,.85);border:1px solid rgba(120,90,50,.14);border-radius:14px;padding:.6rem .75rem;margin-bottom:.5rem;display:flex;align-items:center;gap:.6rem;}
+ .cap.mine{border-color:rgba(124,92,255,.5);background:rgba(124,92,255,.08);}
+ .cap .t{flex:1;font-size:.86rem;color:#4a3a55;line-height:1.35;word-break:break-word;}
+ .cap .h{flex-shrink:0;border:0;background:transparent;font-size:.8rem;font-weight:700;color:#b3a084;cursor:pointer;padding:.3rem .4rem;border-radius:999px;font-family:inherit;}
+ .cap .h.on{color:#E14C8F;}
+ .cap .h:active{transform:scale(1.2);}
+ #empty{text-align:center;font-family:"Instrument Serif",Georgia,serif;font-style:italic;font-size:1.05rem;color:#a08d77;padding:1.4rem 1rem;}
+</style>
+<div id="wrap">
+ <div id="head"><h1>Caption This</h1><p>One scene a week. The wall belongs to everyone.</p></div>
+ <div id="scene"><div class="em" id="em"></div><div class="pr">caption this scene</div></div>
+ <div id="row">
+ <input id="inp" maxlength="90" placeholder="your caption…">
+ <button id="send">post</button>
+ </div>
+ <div id="note"></div>
+ <div id="wall"><div id="empty">be the first to caption it…</div></div>
+</div>
+<script>
+(function(){
+ var LL=window.liveloop||null;
+ var muted = LL ? LL.muted : true;
+ if(LL && LL.onMute){ try{ LL.onMute(function(m){ muted=m; }); }catch(e){} }
+ if(LL && LL.declareMedia){ try{ LL.declareMedia({sound:true}); }catch(e){} }
+ var _ac=null;
+ function actx(){ if(!_ac){ try{ _ac=new (window.AudioContext||window.webkitAudioContext)(); }catch(e){ _ac=null; } } return _ac; }
+ function pop(f){
+ if(muted) return; var c=actx(); if(!c) return;
+ var t=c.currentTime, o=c.createOscillator(), g=c.createGain();
+ o.type='sine'; o.frequency.setValueAtTime(f||520,t);
+ o.frequency.exponentialRampToValueAtTime((f||520)*1.5,t+0.07);
+ g.gain.setValueAtTime(0.0001,t); g.gain.exponentialRampToValueAtTime(0.12,t+0.01);
+ g.gain.exponentialRampToValueAtTime(0.0001,t+0.22);
+ o.connect(g); g.connect(c.destination); o.start(t); o.stop(t+0.25);
+ }
+
+ var SCENES=[
+ '🐈‍⬛ 💻 📉',
+ '🦆 🕶️ 🏖️',
+ '🧙‍♂️ 🛒 🥕',
+ '🐕 🎓 📜',
+ '🤖 ☕ 🌧️',
+ '🐧 🎤 🌟',
+ '🦀 🏋️ 💪',
+ '🐸 👑 🏰'
+ ];
+ var week=Math.floor(Date.now()/604800000);
+ var idx=((week%SCENES.length)+SCENES.length)%SCENES.length;
+ document.getElementById('em').textContent=SCENES[idx];
+ var CAPS='caps-w'+week, HEARTS='hearts-w'+week;
+
+ var inp=document.getElementById('inp'), send=document.getElementById('send');
+ var wall=document.getElementById('wall'), note=document.getElementById('note');
+ var hasData=!!(LL && LL.data && LL.data.submit);
+ var myIds={}, myHeart=null, busy=false;
+
+ function setNote(t){ note.textContent=t||''; }
+
+ function render(caps,hearts){
+ var tally={};
+ hearts.forEach(function(r){ var c=r.data && r.data.cap; if(c) tally[c]=(tally[c]||0)+1; });
+ wall.innerHTML='';
+ if(!caps.length){
+ var e=document.createElement('div'); e.id='empty';
+ e.textContent='be the first to caption it…';
+ wall.appendChild(e); return;
+ }
+ caps.sort(function(a,b){ return (tally[b.id]||0)-(tally[a.id]||0); });
+ caps.forEach(function(r){
+ var div=document.createElement('div');
+ div.className='cap'+(myIds[r.id]?' mine':'');
+ var t=document.createElement('div'); t.className='t';
+ t.textContent=String(r.data && r.data.text || '').slice(0,90);
+ var h=document.createElement('button');
+ h.className='h'+(myHeart===r.id?' on':'');
+ h.textContent='❤ '+(tally[r.id]||0);
+ h.addEventListener('click',function(){
+ if(!hasData || myIds[r.id]) return;
+ myHeart=r.id; pop(700);
+ try{ LL.data.submit(HEARTS,{cap:r.id},{mode:'keep_last'}).then(refresh); }catch(e){}
+ render(caps,hearts.filter(function(x){ return !x._mine; }).concat([{data:{cap:r.id},_mine:true}]));
+ });
+ div.appendChild(t); div.appendChild(h); wall.appendChild(div);
+ });
+ }
+
+ function refresh(){
+ if(!hasData) return;
+ try{
+ Promise.all([
+ LL.data.list(CAPS,{order:'recent',limit:40}),
+ LL.data.list(HEARTS,{order:'recent',limit:500}),
+ LL.data.mine(CAPS),
+ LL.data.mine(HEARTS)
+ ]).then(function(res){
+ var caps=(res[0]&&res[0].records)||[];
+ var hearts=(res[1]&&res[1].records)||[];
+ myIds={};
+ ((res[2]&&res[2].records)||[]).forEach(function(r){ myIds[r.id]=true; if(r.data&&r.data.text&&!inp.value) inp.value=r.data.text; });
+ var mh=((res[3]&&res[3].records)||[])[0];
+ if(mh && mh.data) myHeart=mh.data.cap||null;
+ render(caps,hearts);
+ }).catch(function(){});
+ }catch(e){}
+ }
+
+ function submit(){
+ var text=(inp.value||'').trim().slice(0,90);
+ if(!text || busy) return;
+ if(!hasData){
+ // editor preview — no shared data yet
+ render([{id:'me',data:{text:text}}],[]);
+ myIds['me']=true;
+ setNote('shared captions go live once this loop is published');
+ pop(560); return;
+ }
+ busy=true; setNote('posting…');
+ try{
+ LL.data.submit(CAPS,{text:text},{mode:'keep_last'}).then(function(r){
+ busy=false;
+ if(r && r.ok===false){ setNote('could not post — try again'); return; }
+ setNote('on the wall! (yours is highlighted — post again to edit)');
+ pop(560); refresh();
+ },function(){ busy=false; setNote('could not post — try again'); });
+ }catch(e){ busy=false; }
+ }
+ send.addEventListener('click',submit);
+ inp.addEventListener('keydown',function(e){ if(e.key==='Enter'){ e.preventDefault(); submit(); } });
+
+ // gentle polling while visible
+ var timer=null;
+ function startPoll(){ if(timer) return; timer=setInterval(refresh,25000); }
+ function stopPoll(){ if(timer){ clearInterval(timer); timer=null; } }
+ if(LL && LL.onVisibility){ try{ LL.onVisibility(function(v){ if(v){ refresh(); startPoll(); } else stopPoll(); }); }catch(e){} }
+ document.addEventListener('visibilitychange',function(){ if(document.hidden) stopPoll(); else { refresh(); startPoll(); } });
+
+ if(hasData){ refresh(); startPoll(); }
+ else setNote('preview mode — the live wall appears on the published loop');
+})();
+</script>
← Version history