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

v3

@oconnorfranca · 6/5/2026, 11:24:32 PM

Diff against v2.

{"scenes":[{"id":"s1","text":"","media":{"type":"video","value":"https://customer-ivwo8uur2trcf08m.cloudflarestream.com/3b882b21df1a1517e4ba748749ac8a25/manifest/video.m3u8"},"title":"Go Build Something!","overlay":"<!DOCTYPE html>\n<html lang=\"pt-BR\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Flying Hearts</title>\n <style>\n html, body {\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n overflow: hidden;\n background: transparent;\n box-sizing: border-box;\n }\n\n #container {\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n background: transparent;\n }\n\n .heart {\n position: absolute;\n font-size: 1.8rem;\n color: #b366ff;\n cursor: pointer;\n user-select: none;\n pointer-events: auto;\n animation: float 6s infinite ease-in-out;\n }\n\n @keyframes float {\n 0% {\n transform: translateY(0) translateX(0);\n opacity: 1;\n }\n 100% {\n transform: translateY(-640px) translateX(30px);\n opacity: 0;\n }\n }\n\n .particle {\n position: absolute;\n font-size: 1.2rem;\n pointer-events: none;\n animation: burst 0.8s ease-out forwards;\n }\n\n @keyframes burst {\n 0% {\n opacity: 1;\n transform: translate(0, 0) scale(1);\n }\n 100% {\n opacity: 0;\n transform: translate(var(--tx), var(--ty)) scale(0.3);\n }\n }\n\n .message {\n position: fixed;\n font-size: 0.9rem;\n font-weight: bold;\n color: white;\n text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);\n pointer-events: none;\n animation: fadeOut 1.5s ease-in forwards;\n z-index: 500;\n white-space: nowrap;\n }\n\n @keyframes fadeOut {\n 0% {\n opacity: 1;\n transform: translateY(0);\n }\n 100% {\n opacity: 0;\n transform: translateY(-30px);\n }\n }\n\n #instructionMessage {\n position: fixed;\n top: 40px;\n left: 50%;\n transform: translateX(-50%);\n background: rgba(179, 102, 255, 0.9);\n color: white;\n padding: 15px 25px;\n border-radius: 12px;\n font-size: 1rem;\n font-weight: bold;\n text-align: center;\n z-index: 999;\n pointer-events: none;\n animation: slideDown 0.6s ease-out forwards;\n }\n\n @keyframes slideDown {\n 0% {\n opacity: 0;\n transform: translateX(-50%) translateY(-20px);\n }\n 100% {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n }\n\n #scoreBoard {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n color: rgba(255, 255, 255, 0.3);\n font-size: 1.5rem;\n font-weight: bold;\n z-index: 998;\n pointer-events: none;\n text-align: center;\n text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);\n }\n </style>\n</head>\n<body>\n <div id=\"container\"></div>\n <div id=\"scoreBoard\">0</div>\n\n <script>\n const container = document.getElementById('container');\n const scoreBoardEl = document.getElementById('scoreBoard');\n let hearts = [];\n let score = 0;\n let instructionShown = false;\n\n function showInstruction() {\n if (!instructionShown) {\n const instruction = document.createElement('div');\n instruction.id = 'instructionMessage';\n instruction.textContent = 'Click on the hearts! 💜';\n document.body.appendChild(instruction);\n instructionShown = true;\n\n setTimeout(() => {\n instruction.remove();\n }, 4000);\n }\n }\n\n function updateScore() {\n score++;\n scoreBoardEl.textContent = score;\n }\n\n function createHeart() {\n const heart = document.createElement('div');\n heart.className = 'heart';\n heart.textContent = '💜';\n \n const startX = Math.random() * window.innerWidth;\n const duration = 4 + Math.random() * 3;\n \n heart.style.left = startX + 'px';\n heart.style.top = window.innerHeight + 'px';\n heart.style.animationDuration = duration + 's';\n \n container.appendChild(heart);\n \n heart.addEventListener('click', (e) => {\n e.stopPropagation();\n const rect = heart.getBoundingClientRect();\n explodeHeart(heart, rect);\n showMessage(rect);\n updateScore();\n });\n \n setTimeout(() => {\n if (heart.parentNode) {\n heart.remove();\n }\n }, duration * 1000);\n }\n\n function explodeHeart(heart, rect) {\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n\n // Create particles\n for (let i = 0; i < 8; i++) {\n const particle = document.createElement('div');\n particle.className = 'particle';\n particle.textContent = '💜';\n \n const angle = (i / 8) * Math.PI * 2;\n const distance = 80 + Math.random() * 40;\n const tx = Math.cos(angle) * distance;\n const ty = Math.sin(angle) * distance;\n \n particle.style.left = centerX + 'px';\n particle.style.top = centerY + 'px';\n particle.style.setProperty('--tx', tx + 'px');\n particle.style.setProperty('--ty', ty + 'px');\n \n document.body.appendChild(particle);\n \n setTimeout(() => {\n particle.remove();\n }, 800);\n }\n\n heart.remove();\n }\n\n function showMessage(rect) {\n const message = document.createElement('div');\n message.className = 'message';\n message.textContent = 'Go Build Something';\n message.style.left = (rect.left + rect.width / 2) + 'px';\n message.style.top = (rect.top - 10) + 'px';\n message.style.transform = 'translateX(-50%)';\n document.body.appendChild(message);\n \n setTimeout(() => {\n message.remove();\n }, 1500);\n }\n\n // Show instruction on load\n showInstruction();\n\n // Spawn hearts continuously\n setInterval(createHeart, 800);\n\n // Spawn initial heart\n createHeart();\n </script>\n</body>\n</html>"}]}

v3

@oconnorfranca · 6/5/2026, 11:24:32 PM

Diff against v2.

{"scenes":[{"id":"s1","text":"","media":{"type":"video","value":"https://customer-ivwo8uur2trcf08m.cloudflarestream.com/3b882b21df1a1517e4ba748749ac8a25/manifest/video.m3u8"},"title":"Go Build Something!","overlay":"<!DOCTYPE html>\n<html lang=\"pt-BR\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Flying Hearts</title>\n <style>\n html, body {\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n overflow: hidden;\n background: transparent;\n box-sizing: border-box;\n }\n\n #container {\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n background: transparent;\n }\n\n .heart {\n position: absolute;\n font-size: 1.8rem;\n color: #b366ff;\n cursor: pointer;\n user-select: none;\n pointer-events: auto;\n animation: float 6s infinite ease-in-out;\n }\n\n @keyframes float {\n 0% {\n transform: translateY(0) translateX(0);\n opacity: 1;\n }\n 100% {\n transform: translateY(-640px) translateX(30px);\n opacity: 0;\n }\n }\n\n .particle {\n position: absolute;\n font-size: 1.2rem;\n pointer-events: none;\n animation: burst 0.8s ease-out forwards;\n }\n\n @keyframes burst {\n 0% {\n opacity: 1;\n transform: translate(0, 0) scale(1);\n }\n 100% {\n opacity: 0;\n transform: translate(var(--tx), var(--ty)) scale(0.3);\n }\n }\n\n .message {\n position: fixed;\n font-size: 0.9rem;\n font-weight: bold;\n color: white;\n text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);\n pointer-events: none;\n animation: fadeOut 1.5s ease-in forwards;\n z-index: 500;\n white-space: nowrap;\n }\n\n @keyframes fadeOut {\n 0% {\n opacity: 1;\n transform: translateY(0);\n }\n 100% {\n opacity: 0;\n transform: translateY(-30px);\n }\n }\n\n #instructionMessage {\n position: fixed;\n top: 40px;\n left: 50%;\n transform: translateX(-50%);\n background: rgba(179, 102, 255, 0.9);\n color: white;\n padding: 15px 25px;\n border-radius: 12px;\n font-size: 1rem;\n font-weight: bold;\n text-align: center;\n z-index: 999;\n pointer-events: none;\n animation: slideDown 0.6s ease-out forwards;\n }\n\n @keyframes slideDown {\n 0% {\n opacity: 0;\n transform: translateX(-50%) translateY(-20px);\n }\n 100% {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n }\n\n #scoreBoard {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n color: rgba(255, 255, 255, 0.3);\n font-size: 1.5rem;\n font-weight: bold;\n z-index: 998;\n pointer-events: none;\n text-align: center;\n text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);\n }\n </style>\n</head>\n<body>\n <div id=\"container\"></div>\n <div id=\"scoreBoard\">0</div>\n\n <script>\n const container = document.getElementById('container');\n const scoreBoardEl = document.getElementById('scoreBoard');\n let hearts = [];\n let score = 0;\n let instructionShown = false;\n\n function showInstruction() {\n if (!instructionShown) {\n const instruction = document.createElement('div');\n instruction.id = 'instructionMessage';\n instruction.textContent = 'Click on the hearts! 💜';\n document.body.appendChild(instruction);\n instructionShown = true;\n\n setTimeout(() => {\n instruction.remove();\n }, 4000);\n }\n }\n\n function updateScore() {\n score++;\n scoreBoardEl.textContent = score;\n }\n\n function createHeart() {\n const heart = document.createElement('div');\n heart.className = 'heart';\n heart.textContent = '💜';\n \n const startX = Math.random() * window.innerWidth;\n const duration = 4 + Math.random() * 3;\n \n heart.style.left = startX + 'px';\n heart.style.top = window.innerHeight + 'px';\n heart.style.animationDuration = duration + 's';\n \n container.appendChild(heart);\n \n heart.addEventListener('click', (e) => {\n e.stopPropagation();\n const rect = heart.getBoundingClientRect();\n explodeHeart(heart, rect);\n showMessage(rect);\n updateScore();\n });\n \n setTimeout(() => {\n if (heart.parentNode) {\n heart.remove();\n }\n }, duration * 1000);\n }\n\n function explodeHeart(heart, rect) {\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n\n // Create particles\n for (let i = 0; i < 8; i++) {\n const particle = document.createElement('div');\n particle.className = 'particle';\n particle.textContent = '💜';\n \n const angle = (i / 8) * Math.PI * 2;\n const distance = 80 + Math.random() * 40;\n const tx = Math.cos(angle) * distance;\n const ty = Math.sin(angle) * distance;\n \n particle.style.left = centerX + 'px';\n particle.style.top = centerY + 'px';\n particle.style.setProperty('--tx', tx + 'px');\n particle.style.setProperty('--ty', ty + 'px');\n \n document.body.appendChild(particle);\n \n setTimeout(() => {\n particle.remove();\n }, 800);\n }\n\n heart.remove();\n }\n\n function showMessage(rect) {\n const message = document.createElement('div');\n message.className = 'message';\n message.textContent = 'Go Build Something';\n message.style.left = (rect.left + rect.width / 2) + 'px';\n message.style.top = (rect.top - 10) + 'px';\n message.style.transform = 'translateX(-50%)';\n document.body.appendChild(message);\n \n setTimeout(() => {\n message.remove();\n }, 1500);\n }\n\n // Show instruction on load\n showInstruction();\n\n // Spawn hearts continuously\n setInterval(createHeart, 800);\n\n // Spawn initial heart\n createHeart();\n </script>\n</body>\n</html>"}]}
← Version history