Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>BeatBot - Celebrate GPT-5</title> | |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet"> | |
| <script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/tone@14.7.77/build/Tone.js"></script> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Exo+2:wght@300;400;600&display=swap'); | |
| :root { | |
| --primary: #6366f1; | |
| --secondary: #a855f7; | |
| --accent: #06b6d4; | |
| --dark: #0f172a; | |
| --light: #f8fafc; | |
| } | |
| body { | |
| font-family: 'Exo 2', sans-serif; | |
| background: linear-gradient(135deg, var(--dark) 0%, #1e293b 100%); | |
| color: var(--light); | |
| overflow-x: hidden; | |
| } | |
| .orbitron { | |
| font-family: 'Orbitron', sans-serif; | |
| } | |
| .beat-grid { | |
| display: grid; | |
| grid-template-columns: repeat(8, 1fr); | |
| gap: 0.5rem; | |
| margin: 1rem 0; | |
| } | |
| .beat-pad { | |
| aspect-ratio: 1; | |
| border-radius: 0.5rem; | |
| background: rgba(255, 255, 255, 0.1); | |
| border: 2px solid rgba(255, 255, 255, 0.2); | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| } | |
| .beat-pad.active { | |
| background: var(--accent); | |
| border-color: var(--accent); | |
| box-shadow: 0 0 15px var(--accent); | |
| transform: scale(1.05); | |
| } | |
| .beat-pad.playing { | |
| animation: pulse 0.3s ease; | |
| } | |
| @keyframes pulse { | |
| 0% { transform: scale(1); } | |
| 50% { transform: scale(1.1); } | |
| 100% { transform: scale(1); } | |
| } | |
| .visualizer { | |
| height: 150px; | |
| background: rgba(0, 0, 0, 0.3); | |
| border-radius: 0.5rem; | |
| margin: 2rem 0; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .viz-bar { | |
| position: absolute; | |
| bottom: 0; | |
| width: 4px; | |
| background: var(--primary); | |
| border-radius: 2px 2px 0 0; | |
| transition: height 0.1s ease; | |
| } | |
| .glow-text { | |
| text-shadow: 0 0 10px currentColor, 0 0 20px currentColor; | |
| } | |
| .neon-border { | |
| border: 2px solid var(--primary); | |
| box-shadow: 0 0 10px var(--primary), inset 0 0 10px var(--primary); | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen flex flex-col"> | |
| <!-- Hero Section --> | |
| <header class="text-center py-20 relative overflow-hidden"> | |
| <div class="absolute inset-0 bg-gradient-to-b from-transparent to-black opacity-50"></div> | |
| <div class="container mx-auto px-4 relative z-10"> | |
| <h1 class="orbitron text-5xl md:text-7xl font-black mb-4 glow-text" style="color: var(--accent);" data-aos="fade-down"> | |
| BEAT<span style="color: var(--primary);">BOT</span> | |
| </h1> | |
| <p class="text-xl md:text-2xl mb-8 text-gray-300" data-aos="fade-up" data-aos-delay="200"> | |
| Generate the ultimate beat to celebrate <span class="font-bold text-indigo-300">GPT-5</span> | |
| </p> | |
| <div class="flex justify-center gap-4" data-aos="zoom-in" data-aos-delay="400"> | |
| <button id="play-btn" class="px-8 py-3 bg-indigo-600 hover:bg-indigo-700 rounded-full font-semibold flex items-center gap-2 transition-all hover:scale-105"> | |
| <i data-feather="play"></i> Generate Beat | |
| </button> | |
| <button id="stop-btn" class="px-8 py-3 bg-gray-700 hover:bg-gray-600 rounded-full font-semibold flex items-center gap-2 transition-all"> | |
| <i data-feather="square"></i> Stop | |
| </button> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Main Content --> | |
| <main class="flex-1 container mx-auto px-4 py-12"> | |
| <div class="max-w-4xl mx-auto"> | |
| <!-- Beat Controls --> | |
| <div class="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-6 mb-12 neon-border" data-aos="fade-up"> | |
| <h2 class="orbitron text-2xl mb-6 text-center">Beat Matrix</h2> | |
| <div class="mb-6"> | |
| <label class="block text-sm font-medium mb-2">Tempo: <span id="tempo-value">120</span> BPM</label> | |
| <input type="range" id="tempo" min="60" max="180" value="120" class="w-full h-2 bg-gray-600 rounded-lg appearance-none cursor-pointer"> | |
| </div> | |
| <div class="beat-grid" id="beat-grid"> | |
| <!-- Beat pads will be generated by JS --> | |
| </div> | |
| <div class="mt-6 grid grid-cols-2 md:grid-cols-4 gap-4"> | |
| <button class="px-4 py-2 bg-purple-600 hover:bg-purple-700 rounded-lg transition-colors" onclick="changePattern('techno')">Techno</button> | |
| <button class="px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded-lg transition-colors" onclick="changePattern('hiphop')">Hip Hop</button> | |
| <button class="px-4 py-2 bg-cyan-600 hover:bg-cyan-700 rounded-lg transition-colors" onclick="changePattern('dubstep')">Dubstep</button> | |
| <button class="px-4 py-2 bg-pink-600 hover:bg-pink-700 rounded-lg transition-colors" onclick="changePattern('random')">Random</button> | |
| </div> | |
| </div> | |
| <!-- Visualizer --> | |
| <div class="visualizer" id="visualizer" data-aos="fade-up" data-aos-delay="200"> | |
| <!-- Visualizer bars will be generated by JS --> | |
| </div> | |
| <!-- GPT-5 Celebration Message --> | |
| <div class="text-center mt-16" data-aos="fade-up" data-aos-delay="400"> | |
| <h2 class="orbitron text-3xl mb-4 glow-text" style="color: var(--secondary);">Celebrating GPT-5!</h2> | |
| <p class="text-lg text-gray-300 max-w-2xl mx-auto"> | |
| The future of AI is here! This beat celebrates the incredible advancements and possibilities | |
| that GPT-5 brings to the world. Let the rhythm of innovation move you! | |
| </p> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Footer --> | |
| <footer class="py-8 text-center text-gray-400"> | |
| <p>Made with <i data-feather="heart" class="inline w-4 h-4 text-red-500"></i> for the AI community</p> | |
| </footer> | |
| <script> | |
| // Initialize libraries | |
| AOS.init({ | |
| duration: 800, | |
| once: true | |
| }); | |
| feather.replace(); | |
| // Audio context and synth setup | |
| let audioContext; | |
| let isPlaying = false; | |
| let currentStep = 0; | |
| let interval; | |
| const synth = new Tone.PolySynth(Tone.Synth).toDestination(); | |
| const reverb = new Tone.Reverb(2).toDestination(); | |
| synth.connect(reverb); | |
| // Beat patterns | |
| const patterns = { | |
| techno: [1,0,1,0,1,0,1,0, 0,1,0,1,0,1,0,1, 1,0,1,0,1,0,1,0, 0,1,0,1,0,1,0,1], | |
| hiphop: [1,0,0,0,1,0,0,1, 0,0,1,0,0,0,1,0, 1,0,0,0,1,0,0,1, 0,0,1,0,0,1,0,0], | |
| dubstep: [1,0,0,0,0,0,0,0, 0,0,1,1,0,0,0,0, 1,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,1], | |
| random: Array(32).fill(0).map(() => Math.random() > 0.7 ? 1 : 0) | |
| }; | |
| let currentPattern = patterns.techno; | |
| // Initialize beat grid | |
| function initBeatGrid() { | |
| const grid = document.getElementById('beat-grid'); | |
| grid.innerHTML = ''; | |
| for (let i = 0; i < 32; i++) { | |
| const pad = document.createElement('div'); | |
| pad.className = 'beat-pad'; | |
| pad.dataset.index = i; | |
| pad.addEventListener('click', () => toggleBeat(i)); | |
| grid.appendChild(pad); | |
| } | |
| updateGrid(); | |
| } | |
| function toggleBeat(index) { | |
| currentPattern[index] = currentPattern[index] ? 0 : 1; | |
| updateGrid(); | |
| } | |
| function updateGrid() { | |
| const pads = document.querySelectorAll('.beat-pad'); | |
| pads.forEach((pad, i) => { | |
| pad.classList.toggle('active', currentPattern[i] === 1); | |
| pad.classList.toggle('playing', isPlaying && i === currentStep); | |
| }); | |
| } | |
| function changePattern(type) { | |
| currentPattern = [...patterns[type]]; | |
| updateGrid(); | |
| } | |
| // Visualizer setup | |
| function initVisualizer() { | |
| const visualizer = document.getElementById('visualizer'); | |
| visualizer.innerHTML = ''; | |
| for (let i = 0; i < 32; i++) { | |
| const bar = document.createElement('div'); | |
| bar.className = 'viz-bar'; | |
| bar.style.left = `${i * (100 / 32)}%`; | |
| bar.style.height = '0%'; | |
| visualizer.appendChild(bar); | |
| } | |
| } | |
| function updateVisualizer() { | |
| const bars = document.querySelectorAll('.viz-bar'); | |
| bars.forEach((bar, i) => { | |
| const height = Math.random() * 80 + 20; | |
| bar.style.height = `${height}%`; | |
| bar.style.background = i === currentStep % 32 ? 'var(--accent)' : 'var(--primary)'; | |
| }); | |
| } | |
| // Play/stop functions | |
| document.getElementById('play-btn').addEventListener('click', () => { | |
| if (!audioContext) { | |
| audioContext = new AudioContext(); | |
| Tone.start(); | |
| } | |
| if (isPlaying) { | |
| stopBeat(); | |
| } else { | |
| playBeat(); | |
| } | |
| }); | |
| document.getElementById('stop-btn').addEventListener('click', stopBeat); | |
| function playBeat() { | |
| isPlaying = true; | |
| document.getElementById('play-btn').innerHTML = '<i data-feather="pause"></i> Pause'; | |
| feather.replace(); | |
| const tempo = parseInt(document.getElementById('tempo').value); | |
| const stepDuration = 60 / tempo / 2; | |
| let step = 0; | |
| currentStep = 0; | |
| function playStep() { | |
| if (currentPattern[step]) { | |
| const note = ['C3', 'E3', 'G3', 'B3'][step % 4]; | |
| synth.triggerAttackRelease(note, '8n'); | |
| } | |
| currentStep = step; | |
| updateGrid(); | |
| updateVisualizer(); | |
| step = (step + 1) % 32; | |
| } | |
| // Initial play | |
| playStep(); | |
| // Set interval for subsequent steps | |
| interval = setInterval(playStep, stepDuration * 1000); | |
| } | |
| function stopBeat() { | |
| isPlaying = false; | |
| clearInterval(interval); | |
| document.getElementById('play-btn').innerHTML = '<i data-feather="play"></i> Generate Beat'; | |
| feather.replace(); | |
| currentStep = -1; | |
| updateGrid(); | |
| // Reset visualizer | |
| const bars = document.querySelectorAll('.viz-bar'); | |
| bars.forEach(bar => bar.style.height = '0%'); | |
| } | |
| // Tempo control | |
| document.getElementById('tempo').addEventListener('input', (e) => { | |
| document.getElementById('tempo-value').textContent = e.target.value; | |
| if (isPlaying) { | |
| stopBeat(); | |
| playBeat(); | |
| } | |
| }); | |
| // Initialize | |
| initBeatGrid(); | |
| initVisualizer(); | |
| </script> | |
| </body> | |
| </html> | |