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/18/2026, 7:49:56 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:#0f172a;color:#f1f5f9;overflow:hidden;}
+ #app{position:relative;height:100%;}
+ .screen{position:absolute;inset:0;display:none;flex-direction:column;align-items:center;justify-content:center;gap:.85rem;padding:1.5rem;box-sizing:border-box;text-align:center;}
+ h1{margin:0;font-size:1.5rem;}
+ .sub{margin:0;color:#94a3b8;font-size:.84rem;max-width:26ch;line-height:1.5;}
+ button{font:inherit;font-weight:700;border:0;border-radius:9999px;padding:.7rem 1.5rem;cursor:pointer;touch-action:manipulation;background:#38bdf8;color:#08131f;font-size:1rem;}
+ button.alt{background:#1e293b;color:#e2e8f0;}
+ input{font:inherit;font-size:1rem;border-radius:.6rem;border:2px solid #334155;background:#0b1220;color:#fff;padding:.55rem .7rem;}
+ .name-field{width:11rem;text-align:center;}
+ .err{color:#f87171;font-size:.85rem;}
+ #chat{position:absolute;inset:0;display:none;flex-direction:column;}
+ #chead{display:flex;align-items:center;gap:.4rem;padding:.55rem .65rem;background:#1e293b;border-bottom:1px solid #334155;}
+ #cwho{flex:1;font-weight:700;font-size:.88rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
+ #chead button{padding:.4rem .85rem;font-size:.76rem;font-weight:700;}
+ #clog{flex:1;overflow-y:auto;padding:.7rem;display:flex;flex-direction:column;gap:.4rem;}
+ .msg{max-width:78%;padding:.45rem .7rem;border-radius:.9rem;font-size:.92rem;line-height:1.35;word-wrap:break-word;white-space:pre-wrap;}
+ .msg.me{align-self:flex-end;background:#38bdf8;color:#08131f;border-bottom-right-radius:.2rem;}
+ .msg.them{align-self:flex-start;background:#1e293b;color:#f1f5f9;border-bottom-left-radius:.2rem;}
+ .sys{align-self:center;color:#64748b;font-size:.78rem;text-align:center;}
+ #cbar{display:flex;gap:.45rem;padding:.55rem;background:#1e293b;border-top:1px solid #334155;}
+ #cinput{flex:1;}
+ #cinput:disabled{opacity:.5;}
+</style>
+<div id="app">
+ <div class="screen" id="screen"></div>
+ <div id="chat">
+ <div id="chead">
+ <span id="cwho">Stranger</span>
+ <button class="alt" id="nextBtn" type="button">Next ⏭</button>
+ <button class="alt" id="stopBtn" type="button">Stop</button>
+ </div>
+ <div id="clog"></div>
+ <div id="cbar">
+ <input id="cinput" type="text" maxlength="500" placeholder="Say something…" autocomplete="off">
+ <button id="sendBtn" type="button">Send</button>
+ </div>
+ </div>
+</div>
+<script>
+(function(){
+ var L=window.liveloop, RT=L&&L.realtime;
+ var screen=document.getElementById('screen'), chat=document.getElementById('chat');
+ var clog=document.getElementById('clog'), cinput=document.getElementById('cinput'), cwho=document.getElementById('cwho');
+ var phase='menu';
+ var lobbyId=null, lobbyMates=[], lobbyCand=null, queueTimer=null, shownCount=-1, joinStamp=0;
+ var myName='', partnerName='', players=[], hiTimer=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)<16&&Math.abs(e.clientY-sy)<16) fn();
+ });
+ }
+ function el(tag,cls,txt){ var e=document.createElement(tag); if(cls)e.className=cls; if(txt!=null)e.textContent=txt; return e; }
+ function show(){ chat.style.display='none'; screen.style.display='flex'; screen.innerHTML=''; for(var i=0;i<arguments.length;i++) screen.appendChild(arguments[i]); }
+ function showChat(){ screen.style.display='none'; chat.style.display='flex'; }
+
+ if(!RT){ show(el('h1',null,'💬 Chat Roulette'), el('p','err','Realtime is not available here — open this from the Liveloop feed.')); return; }
+
+ function commitName(inp){
+ var n=(((inp&&inp.value)||'').trim()).slice(0,16) || 'Someone';
+ myName=n;
+ if(L&&L.storage){ try{ L.storage.set({name:n}); }catch(e){} }
+ }
+ function loadName(){
+ if(!L||!L.storage) return;
+ L.storage.get().then(function(s){
+ if(s&&typeof s.name==='string'&&s.name) myName=s.name;
+ if(phase==='menu') menu();
+ },function(){});
+ }
+ function menu(){
+ phase='menu';
+ var nameInp=el('input','name-field'); nameInp.maxLength=16; nameInp.placeholder='Your name'; nameInp.value=myName;
+ var start=el('button',null,'Start chatting');
+ onTap(start,function(){ commitName(nameInp); startQueue(); });
+ show(el('h1',null,'💬 Chat Roulette'),
+ el('p','sub','Type a name and we’ll match you with a random person to chat with. Be kind — and use the 🚩 flag on the card to report anything off.'),
+ nameInp, start);
+ }
+
+ function stopQueue(){ if(queueTimer){ clearInterval(queueTimer); queueTimer=null; } }
+ function clearHi(){ if(hiTimer){ clearInterval(hiTimer); hiTimer=null; } }
+ function backToMenu(){ try{ RT.leave(); }catch(e){} stopQueue(); clearHi(); phase='menu'; players=[]; menu(); }
+ function errScreen(msg){
+ stopQueue(); clearHi(); phase='menu';
+ var back=el('button','alt','Back'); onTap(back,menu);
+ show(el('h1',null,'Something went wrong'), el('p','err',msg), back);
+ }
+ function startQueue(){
+ try{ RT.leave(); }catch(e){}
+ stopQueue(); clearHi();
+ phase='searching'; lobbyCand=null; lobbyMates=[]; shownCount=-1;
+ searching();
+ RT.join('_lobby').then(function(res){
+ if(phase!=='searching') return;
+ if(!res||!res.ok){ errScreen((res&&res.error)||'Could not reach matchmaking.'); return; }
+ lobbyId=res.playerId; lobbyMates=res.players||[];
+ queueTimer=setInterval(queueTick,1000);
+ queueTick();
+ });
+ }
+ function searching(){
+ var n=lobbyMates.length;
+ var cancel=el('button','alt','Cancel'); onTap(cancel,backToMenu);
+ show(el('h1',null,'Finding someone…'),
+ el('p','sub', n>1 ? (n+' people waiting — pairing you up.') : 'Waiting for someone else to start chatting.'),
+ cancel);
+ }
+ function queueTick(){
+ if(phase!=='searching') return;
+ var sorted=lobbyMates.slice().sort(), cand=null;
+ if(sorted.length>=2){
+ if(lobbyId===sorted[0]) cand=sorted[1];
+ else if(lobbyId===sorted[1]) cand=sorted[0];
+ }
+ lobbyCand=cand;
+ if(cand) RT.send({t:'match',with:cand});
+ if(lobbyMates.length!==shownCount){ shownCount=lobbyMates.length; searching(); }
+ }
+ function roomFor(a,b){
+ var s=[a,b].slice().sort().join('|'), h=5381;
+ for(var i=0;i<s.length;i++){ h=(((h<<5)+h)+s.charCodeAt(i))>>>0; }
+ return 'c'+h.toString(36);
+ }
+ function beginMatch(partner){
+ if(phase!=='searching') return;
+ stopQueue();
+ phase='connecting';
+ show(el('h1',null,'Found someone!'), el('p','sub','Connecting you…'));
+ RT.join(roomFor(lobbyId,partner)).then(function(res){
+ if(phase!=='connecting') return;
+ if(!res||!res.ok){ errScreen((res&&res.error)||'Could not connect.'); return; }
+ players=res.players||[];
+ phase='lobby';
+ var stamp=++joinStamp;
+ show(el('h1',null,'Almost there…'), el('p','sub','Waiting for the other person to load.'));
+ checkStart();
+ setTimeout(function(){ if(phase==='lobby' && joinStamp===stamp) startQueue(); }, 9000);
+ });
+ }
+ function checkStart(){
+ if((phase==='lobby'||phase==='connecting') && players.length>=2) startChat();
+ }
+
+ function startChat(){
+ phase='chatting'; partnerName=''; cwho.textContent='Stranger';
+ clog.innerHTML=''; sysMsg('You’re connected. Say hi! 👋');
+ cinput.value=''; cinput.disabled=false;
+ showChat();
+ var n=0; clearHi(); sendHi();
+ hiTimer=setInterval(function(){
+ if(++n>=3 || phase!=='chatting'){ clearHi(); return; }
+ sendHi();
+ },900);
+ }
+ function sendHi(){ RT.send({t:'hi',nm:myName}); }
+ function sysMsg(t){ clog.appendChild(el('div','sys',t)); clog.scrollTop=clog.scrollHeight; }
+ function addMsg(mine,text){
+ clog.appendChild(el('div','msg '+(mine?'me':'them'),text));
+ clog.scrollTop=clog.scrollHeight;
+ }
+ function setPartner(nm){
+ if(nm && nm!==partnerName){ partnerName=nm; cwho.textContent='Chatting with '+nm; }
+ }
+ function sendMsg(){
+ if(phase!=='chatting' || cinput.disabled) return;
+ var t=(cinput.value||'').trim().slice(0,500);
+ if(!t) return;
+ cinput.value='';
+ RT.send({t:'msg',text:t,nm:myName});
+ addMsg(true,t);
+ }
+ onTap(document.getElementById('sendBtn'),sendMsg);
+ onTap(document.getElementById('nextBtn'),function(){ clearHi(); startQueue(); });
+ onTap(document.getElementById('stopBtn'),backToMenu);
+ cinput.addEventListener('keydown',function(e){ if(e.key==='Enter'){ e.preventDefault(); sendMsg(); } });
+
+ RT.onPlayers(function(list){
+ list=list||[];
+ if(phase==='searching'){ lobbyMates=list; queueTick(); return; }
+ players=list;
+ if(phase==='lobby'||phase==='connecting'){ checkStart(); }
+ else if(phase==='chatting' && players.length<2){
+ cinput.disabled=true;
+ cwho.textContent='They left — tap Next ⏭';
+ sysMsg((partnerName||'They')+' left the chat.');
+ }
+ });
+ RT.onMessage(function(m){
+ var d=m&&m.data; if(!d) return;
+ if(phase==='searching'){
+ if(d.t==='match' && d.with===lobbyId){
+ queueTick();
+ if(m.from===lobbyCand) beginMatch(m.from);
+ }
+ return;
+ }
+ if(phase!=='chatting') return;
+ if(typeof d.nm==='string' && d.nm) setPartner(d.nm);
+ if(d.t==='msg' && typeof d.text==='string'){ addMsg(false,d.text.slice(0,500)); }
+ });
+
+ menu();
+ loadName();
+})();
+</script>

v1Current

@liveloop · 5/18/2026, 7:49:56 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:#0f172a;color:#f1f5f9;overflow:hidden;}
+ #app{position:relative;height:100%;}
+ .screen{position:absolute;inset:0;display:none;flex-direction:column;align-items:center;justify-content:center;gap:.85rem;padding:1.5rem;box-sizing:border-box;text-align:center;}
+ h1{margin:0;font-size:1.5rem;}
+ .sub{margin:0;color:#94a3b8;font-size:.84rem;max-width:26ch;line-height:1.5;}
+ button{font:inherit;font-weight:700;border:0;border-radius:9999px;padding:.7rem 1.5rem;cursor:pointer;touch-action:manipulation;background:#38bdf8;color:#08131f;font-size:1rem;}
+ button.alt{background:#1e293b;color:#e2e8f0;}
+ input{font:inherit;font-size:1rem;border-radius:.6rem;border:2px solid #334155;background:#0b1220;color:#fff;padding:.55rem .7rem;}
+ .name-field{width:11rem;text-align:center;}
+ .err{color:#f87171;font-size:.85rem;}
+ #chat{position:absolute;inset:0;display:none;flex-direction:column;}
+ #chead{display:flex;align-items:center;gap:.4rem;padding:.55rem .65rem;background:#1e293b;border-bottom:1px solid #334155;}
+ #cwho{flex:1;font-weight:700;font-size:.88rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
+ #chead button{padding:.4rem .85rem;font-size:.76rem;font-weight:700;}
+ #clog{flex:1;overflow-y:auto;padding:.7rem;display:flex;flex-direction:column;gap:.4rem;}
+ .msg{max-width:78%;padding:.45rem .7rem;border-radius:.9rem;font-size:.92rem;line-height:1.35;word-wrap:break-word;white-space:pre-wrap;}
+ .msg.me{align-self:flex-end;background:#38bdf8;color:#08131f;border-bottom-right-radius:.2rem;}
+ .msg.them{align-self:flex-start;background:#1e293b;color:#f1f5f9;border-bottom-left-radius:.2rem;}
+ .sys{align-self:center;color:#64748b;font-size:.78rem;text-align:center;}
+ #cbar{display:flex;gap:.45rem;padding:.55rem;background:#1e293b;border-top:1px solid #334155;}
+ #cinput{flex:1;}
+ #cinput:disabled{opacity:.5;}
+</style>
+<div id="app">
+ <div class="screen" id="screen"></div>
+ <div id="chat">
+ <div id="chead">
+ <span id="cwho">Stranger</span>
+ <button class="alt" id="nextBtn" type="button">Next ⏭</button>
+ <button class="alt" id="stopBtn" type="button">Stop</button>
+ </div>
+ <div id="clog"></div>
+ <div id="cbar">
+ <input id="cinput" type="text" maxlength="500" placeholder="Say something…" autocomplete="off">
+ <button id="sendBtn" type="button">Send</button>
+ </div>
+ </div>
+</div>
+<script>
+(function(){
+ var L=window.liveloop, RT=L&&L.realtime;
+ var screen=document.getElementById('screen'), chat=document.getElementById('chat');
+ var clog=document.getElementById('clog'), cinput=document.getElementById('cinput'), cwho=document.getElementById('cwho');
+ var phase='menu';
+ var lobbyId=null, lobbyMates=[], lobbyCand=null, queueTimer=null, shownCount=-1, joinStamp=0;
+ var myName='', partnerName='', players=[], hiTimer=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)<16&&Math.abs(e.clientY-sy)<16) fn();
+ });
+ }
+ function el(tag,cls,txt){ var e=document.createElement(tag); if(cls)e.className=cls; if(txt!=null)e.textContent=txt; return e; }
+ function show(){ chat.style.display='none'; screen.style.display='flex'; screen.innerHTML=''; for(var i=0;i<arguments.length;i++) screen.appendChild(arguments[i]); }
+ function showChat(){ screen.style.display='none'; chat.style.display='flex'; }
+
+ if(!RT){ show(el('h1',null,'💬 Chat Roulette'), el('p','err','Realtime is not available here — open this from the Liveloop feed.')); return; }
+
+ function commitName(inp){
+ var n=(((inp&&inp.value)||'').trim()).slice(0,16) || 'Someone';
+ myName=n;
+ if(L&&L.storage){ try{ L.storage.set({name:n}); }catch(e){} }
+ }
+ function loadName(){
+ if(!L||!L.storage) return;
+ L.storage.get().then(function(s){
+ if(s&&typeof s.name==='string'&&s.name) myName=s.name;
+ if(phase==='menu') menu();
+ },function(){});
+ }
+ function menu(){
+ phase='menu';
+ var nameInp=el('input','name-field'); nameInp.maxLength=16; nameInp.placeholder='Your name'; nameInp.value=myName;
+ var start=el('button',null,'Start chatting');
+ onTap(start,function(){ commitName(nameInp); startQueue(); });
+ show(el('h1',null,'💬 Chat Roulette'),
+ el('p','sub','Type a name and we’ll match you with a random person to chat with. Be kind — and use the 🚩 flag on the card to report anything off.'),
+ nameInp, start);
+ }
+
+ function stopQueue(){ if(queueTimer){ clearInterval(queueTimer); queueTimer=null; } }
+ function clearHi(){ if(hiTimer){ clearInterval(hiTimer); hiTimer=null; } }
+ function backToMenu(){ try{ RT.leave(); }catch(e){} stopQueue(); clearHi(); phase='menu'; players=[]; menu(); }
+ function errScreen(msg){
+ stopQueue(); clearHi(); phase='menu';
+ var back=el('button','alt','Back'); onTap(back,menu);
+ show(el('h1',null,'Something went wrong'), el('p','err',msg), back);
+ }
+ function startQueue(){
+ try{ RT.leave(); }catch(e){}
+ stopQueue(); clearHi();
+ phase='searching'; lobbyCand=null; lobbyMates=[]; shownCount=-1;
+ searching();
+ RT.join('_lobby').then(function(res){
+ if(phase!=='searching') return;
+ if(!res||!res.ok){ errScreen((res&&res.error)||'Could not reach matchmaking.'); return; }
+ lobbyId=res.playerId; lobbyMates=res.players||[];
+ queueTimer=setInterval(queueTick,1000);
+ queueTick();
+ });
+ }
+ function searching(){
+ var n=lobbyMates.length;
+ var cancel=el('button','alt','Cancel'); onTap(cancel,backToMenu);
+ show(el('h1',null,'Finding someone…'),
+ el('p','sub', n>1 ? (n+' people waiting — pairing you up.') : 'Waiting for someone else to start chatting.'),
+ cancel);
+ }
+ function queueTick(){
+ if(phase!=='searching') return;
+ var sorted=lobbyMates.slice().sort(), cand=null;
+ if(sorted.length>=2){
+ if(lobbyId===sorted[0]) cand=sorted[1];
+ else if(lobbyId===sorted[1]) cand=sorted[0];
+ }
+ lobbyCand=cand;
+ if(cand) RT.send({t:'match',with:cand});
+ if(lobbyMates.length!==shownCount){ shownCount=lobbyMates.length; searching(); }
+ }
+ function roomFor(a,b){
+ var s=[a,b].slice().sort().join('|'), h=5381;
+ for(var i=0;i<s.length;i++){ h=(((h<<5)+h)+s.charCodeAt(i))>>>0; }
+ return 'c'+h.toString(36);
+ }
+ function beginMatch(partner){
+ if(phase!=='searching') return;
+ stopQueue();
+ phase='connecting';
+ show(el('h1',null,'Found someone!'), el('p','sub','Connecting you…'));
+ RT.join(roomFor(lobbyId,partner)).then(function(res){
+ if(phase!=='connecting') return;
+ if(!res||!res.ok){ errScreen((res&&res.error)||'Could not connect.'); return; }
+ players=res.players||[];
+ phase='lobby';
+ var stamp=++joinStamp;
+ show(el('h1',null,'Almost there…'), el('p','sub','Waiting for the other person to load.'));
+ checkStart();
+ setTimeout(function(){ if(phase==='lobby' && joinStamp===stamp) startQueue(); }, 9000);
+ });
+ }
+ function checkStart(){
+ if((phase==='lobby'||phase==='connecting') && players.length>=2) startChat();
+ }
+
+ function startChat(){
+ phase='chatting'; partnerName=''; cwho.textContent='Stranger';
+ clog.innerHTML=''; sysMsg('You’re connected. Say hi! 👋');
+ cinput.value=''; cinput.disabled=false;
+ showChat();
+ var n=0; clearHi(); sendHi();
+ hiTimer=setInterval(function(){
+ if(++n>=3 || phase!=='chatting'){ clearHi(); return; }
+ sendHi();
+ },900);
+ }
+ function sendHi(){ RT.send({t:'hi',nm:myName}); }
+ function sysMsg(t){ clog.appendChild(el('div','sys',t)); clog.scrollTop=clog.scrollHeight; }
+ function addMsg(mine,text){
+ clog.appendChild(el('div','msg '+(mine?'me':'them'),text));
+ clog.scrollTop=clog.scrollHeight;
+ }
+ function setPartner(nm){
+ if(nm && nm!==partnerName){ partnerName=nm; cwho.textContent='Chatting with '+nm; }
+ }
+ function sendMsg(){
+ if(phase!=='chatting' || cinput.disabled) return;
+ var t=(cinput.value||'').trim().slice(0,500);
+ if(!t) return;
+ cinput.value='';
+ RT.send({t:'msg',text:t,nm:myName});
+ addMsg(true,t);
+ }
+ onTap(document.getElementById('sendBtn'),sendMsg);
+ onTap(document.getElementById('nextBtn'),function(){ clearHi(); startQueue(); });
+ onTap(document.getElementById('stopBtn'),backToMenu);
+ cinput.addEventListener('keydown',function(e){ if(e.key==='Enter'){ e.preventDefault(); sendMsg(); } });
+
+ RT.onPlayers(function(list){
+ list=list||[];
+ if(phase==='searching'){ lobbyMates=list; queueTick(); return; }
+ players=list;
+ if(phase==='lobby'||phase==='connecting'){ checkStart(); }
+ else if(phase==='chatting' && players.length<2){
+ cinput.disabled=true;
+ cwho.textContent='They left — tap Next ⏭';
+ sysMsg((partnerName||'They')+' left the chat.');
+ }
+ });
+ RT.onMessage(function(m){
+ var d=m&&m.data; if(!d) return;
+ if(phase==='searching'){
+ if(d.t==='match' && d.with===lobbyId){
+ queueTick();
+ if(m.from===lobbyCand) beginMatch(m.from);
+ }
+ return;
+ }
+ if(phase!=='chatting') return;
+ if(typeof d.nm==='string' && d.nm) setPartner(d.nm);
+ if(d.t==='msg' && typeof d.text==='string'){ addMsg(false,d.text.slice(0,500)); }
+ });
+
+ menu();
+ loadName();
+})();
+</script>
← Version history