|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>RubberDuck - Debugging Assistant</title> |
|
|
<link rel="icon" type="image/x-icon" href="/static/favicon.ico"> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<script src="https://unpkg.com/feather-icons"></script> |
|
|
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.net.min.js"></script> |
|
|
<script> |
|
|
tailwind.config = { |
|
|
theme: { |
|
|
extend: { |
|
|
colors: { |
|
|
primary: { |
|
|
50: '#f0f9ff', |
|
|
100: '#e0f2fe', |
|
|
200: '#bae6fd', |
|
|
300: '#7dd3fc', |
|
|
400: '#38bdf8', |
|
|
500: '#0ea5e9', |
|
|
600: '#0284c7', |
|
|
700: '#0369a1', |
|
|
800: '#075985', |
|
|
900: '#0c4a6e', |
|
|
}, |
|
|
secondary: { |
|
|
50: '#fefce8', |
|
|
100: '#fef9c3', |
|
|
200: '#fef08a', |
|
|
300: '#fde047', |
|
|
400: '#facc15', |
|
|
500: '#eab308', |
|
|
600: '#ca8a04', |
|
|
700: '#a16207', |
|
|
800: '#854d0e', |
|
|
900: '#713f12', |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
</script> |
|
|
<style> |
|
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); |
|
|
body { |
|
|
font-family: 'Inter', sans-serif; |
|
|
} |
|
|
.typing-cursor { |
|
|
animation: blink 1s infinite; |
|
|
} |
|
|
@keyframes blink { |
|
|
0%, 100% { opacity: 1; } |
|
|
50% { opacity: 0; } |
|
|
} |
|
|
.duck-animation { |
|
|
transition: all 0.3s ease; |
|
|
} |
|
|
.duck-animation:hover { |
|
|
transform: rotate(-5deg) scale(1.05); |
|
|
} |
|
|
.message-bubble { |
|
|
animation: fadeInUp 0.5s ease-out; |
|
|
} |
|
|
@keyframes fadeInUp { |
|
|
from { |
|
|
opacity: 0; |
|
|
transform: translateY(20px); |
|
|
} |
|
|
to { |
|
|
opacity: 1; |
|
|
transform: translateY(0); |
|
|
} |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="bg-gradient-to-br from-primary-50 to-secondary-50 min-h-screen"> |
|
|
<div id="vanta-bg" class="fixed inset-0 z-0"></div> |
|
|
|
|
|
|
|
|
<header class="relative z-10 bg-white/80 backdrop-blur-sm border-b border-primary-200"> |
|
|
<div class="container mx-auto px-4 py-4"> |
|
|
<div class="flex items-center justify-between"> |
|
|
<div class="flex items-center space-x-3"> |
|
|
<div class="bg-primary-500 p-2 rounded-full duck-animation"> |
|
|
<i data-feather="help-circle" class="text-white w-6 h-6"></i> |
|
|
</div> |
|
|
<h1 class="text-2xl font-bold text-primary-800">RubberDuck 🦆</h1> |
|
|
</div> |
|
|
<nav class="hidden md:flex space-x-6"> |
|
|
<a href="#features" class="text-primary-700 hover:text-primary-500 font-medium transition-colors">Features</a> |
|
|
<a href="#how-it-works" class="text-primary-700 hover:text-primary-500 font-medium transition-colors">How It Works</a> |
|
|
<a href="#try-it" class="text-primary-700 hover:text-primary-500 font-medium transition-colors">Try It</a> |
|
|
</nav> |
|
|
<button class="bg-primary-500 text-white px-4 py-2 rounded-lg hover:bg-primary-600 transition-colors font-medium"> |
|
|
Get Started |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</header> |
|
|
|
|
|
|
|
|
<section class="relative z-10 py-20 px-4"> |
|
|
<div class="container mx-auto max-w-4xl text-center"> |
|
|
<div class="bg-white/60 backdrop-blur-sm rounded-2xl p-8 shadow-lg border border-primary-100"> |
|
|
<div class="flex justify-center mb-6"> |
|
|
<div class="bg-gradient-to-r from-primary-400 to-secondary-400 p-4 rounded-full duck-animation"> |
|
|
<i data-feather="message-circle" class="text-white w-12 h-12"></i> |
|
|
</div> |
|
|
</div> |
|
|
<h1 class="text-5xl md:text-6xl font-bold text-primary-900 mb-4"> |
|
|
Talk to Your Rubber Duck |
|
|
</h1> |
|
|
<p class="text-xl text-primary-700 mb-8 max-w-2xl mx-auto"> |
|
|
The ultimate debugging companion that helps you solve problems by explaining them out loud. |
|
|
Because sometimes, the solution is in the explanation. |
|
|
</p> |
|
|
<div class="flex flex-col sm:flex-row gap-4 justify-center"> |
|
|
<button class="bg-primary-500 text-white px-8 py-3 rounded-lg hover:bg-primary-600 transition-colors font-medium text-lg"> |
|
|
Start Debugging |
|
|
</button> |
|
|
<button class="border-2 border-primary-500 text-primary-600 px-8 py-3 rounded-lg hover:bg-primary-50 transition-colors font-medium text-lg"> |
|
|
Learn More |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section id="features" class="relative z-10 py-16 px-4 bg-white/60 backdrop-blur-sm"> |
|
|
<div class="container mx-auto max-w-6xl"> |
|
|
<h2 class="text-4xl font-bold text-center text-primary-900 mb-12">Why RubberDuck Works</h2> |
|
|
<div class="grid md:grid-cols-3 gap-8"> |
|
|
<div class="bg-white p-6 rounded-xl shadow-lg border border-primary-100 message-bubble"> |
|
|
<div class="bg-primary-100 w-12 h-12 rounded-lg flex items-center justify-center mb-4"> |
|
|
<i data-feather="lightbulb" class="text-primary-600 w-6 h-6"></i> |
|
|
</div> |
|
|
<h3 class="text-xl font-semibold text-primary-800 mb-2">Clarity Through Explanation</h3> |
|
|
<p class="text-primary-600">Explaining your problem forces you to organize your thoughts and often reveals the solution.</p> |
|
|
</div> |
|
|
<div class="bg-white p-6 rounded-xl shadow-lg border border-primary-100 message-bubble"> |
|
|
<div class="bg-secondary-100 w-12 h-12 rounded-lg flex items-center justify-center mb-4"> |
|
|
<i data-feather="clock" class="text-secondary-600 w-6 h-6"></i> |
|
|
</div> |
|
|
<h3 class="text-xl font-semibold text-primary-800 mb-2">Save Time</h3> |
|
|
<p class="text-primary-600">Avoid hours of frustration by catching logical errors early in the explanation process.</p> |
|
|
</div> |
|
|
<div class="bg-white p-6 rounded-xl shadow-lg border border-primary-100 message-bubble"> |
|
|
<div class="bg-primary-100 w-12 h-12 rounded-lg flex items-center justify-center mb-4"> |
|
|
<i data-feather="users" class="text-primary-600 w-6 h-6"></i> |
|
|
</div> |
|
|
<h3 class="text-xl font-semibold text-primary-800 mb-2">Always Available</h3> |
|
|
<p class="text-primary-600">Your rubber duck never sleeps, never judges, and is always ready to listen.</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section id="try-it" class="relative z-10 py-16 px-4"> |
|
|
<div class="container mx-auto max-w-4xl"> |
|
|
<div class="bg-white rounded-2xl shadow-xl border border-primary-200 overflow-hidden"> |
|
|
<div class="bg-primary-500 text-white p-6"> |
|
|
<h2 class="text-2xl font-bold">Debugging Session</h2> |
|
|
<p class="opacity-90">Explain your problem to the rubber duck below</p> |
|
|
</div> |
|
|
<div class="p-6"> |
|
|
<div class="flex items-start space-x-4 mb-6"> |
|
|
<div class="bg-secondary-100 p-3 rounded-full"> |
|
|
<i data-feather="user" class="text-secondary-600 w-5 h-5"></i> |
|
|
</div> |
|
|
<div class="bg-primary-100 rounded-lg p-4 flex-1"> |
|
|
<p class="text-primary-800" id="user-message">I'm having trouble with my function that should filter an array, but it's returning unexpected results...</p> |
|
|
</div> |
|
|
</div> |
|
|
<div class="flex items-start space-x-4"> |
|
|
<div class="bg-primary-500 p-3 rounded-full duck-animation"> |
|
|
<i data-feather="help-circle" class="text-white w-5 h-5"></i> |
|
|
</div> |
|
|
<div class="bg-secondary-100 rounded-lg p-4 flex-1"> |
|
|
<p class="text-primary-800" id="duck-response"> |
|
|
<span id="typing-text"></span><span class="typing-cursor">|</span> |
|
|
</p> |
|
|
</div> |
|
|
</div> |
|
|
<div class="mt-6"> |
|
|
<textarea |
|
|
class="w-full border border-primary-200 rounded-lg p-4 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent" |
|
|
rows="4" |
|
|
placeholder="Type your problem here..."></textarea> |
|
|
<button class="bg-primary-500 text-white px-6 py-2 rounded-lg hover:bg-primary-600 transition-colors font-medium mt-3"> |
|
|
Explain to Duck |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<footer class="relative z-10 bg-primary-900 text-white py-8 px-4"> |
|
|
<div class="container mx-auto text-center"> |
|
|
<p class="text-primary-200">Made with ❤️ for developers everywhere</p> |
|
|
<p class="text-primary-300 text-sm mt-2">RubberDuck 🦆 - Your debugging companion since 2024</p> |
|
|
</div> |
|
|
</footer> |
|
|
|
|
|
<script> |
|
|
|
|
|
VANTA.NET({ |
|
|
el: "#vanta-bg", |
|
|
mouseControls: true, |
|
|
touchControls: true, |
|
|
gyroControls: false, |
|
|
minHeight: 200.00, |
|
|
minWidth: 200.00, |
|
|
scale: 1.00, |
|
|
scaleMobile: 1.00, |
|
|
color: 0x0ea5e9, |
|
|
backgroundColor: 0xfefce8, |
|
|
points: 10.00, |
|
|
maxDistance: 25.00 |
|
|
}); |
|
|
|
|
|
|
|
|
const messages = [ |
|
|
"Interesting! Can you walk me through what you expect the function to do?", |
|
|
"Have you checked if your filter condition is working as intended?", |
|
|
"Sometimes stepping through the logic line by line helps. Want to try that?", |
|
|
"I notice you mentioned unexpected results. What exactly are you seeing vs expecting?", |
|
|
"Let's break this down. What's the simplest case that should work but doesn't?" |
|
|
]; |
|
|
|
|
|
let currentMessage = 0; |
|
|
let charIndex = 0; |
|
|
const typingText = document.getElementById('typing-text'); |
|
|
const typingCursor = document.querySelector('.typing-cursor'); |
|
|
|
|
|
function typeWriter() { |
|
|
if (charIndex < messages[currentMessage].length) { |
|
|
typingText.textContent += messages[currentMessage].charAt(charIndex); |
|
|
charIndex++; |
|
|
setTimeout(typeWriter, 50); |
|
|
} else { |
|
|
setTimeout(() => { |
|
|
typingText.textContent = ''; |
|
|
charIndex = 0; |
|
|
currentMessage = (currentMessage + 1) % messages.length; |
|
|
setTimeout(typeWriter, 1000); |
|
|
}, 3000); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
setTimeout(typeWriter, 1000); |
|
|
|
|
|
|
|
|
feather.replace(); |
|
|
|
|
|
|
|
|
document.querySelectorAll('button').forEach(button => { |
|
|
button.addEventListener('mouseenter', function() { |
|
|
this.style.transform = 'translateY(-2px)'; |
|
|
this.style.transition = 'transform 0.2s ease'; |
|
|
}); |
|
|
button.addEventListener('mouseleave', function() { |
|
|
this.style.transform = 'translateY(0)'; |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
</script> |
|
|
</body> |
|
|
</html> |
|
|
|