| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>IconForge Studio</title> |
| <link rel="icon" type="image/x-icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🎨</text></svg>"> |
| <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.globe.min.js"></script> |
| <style> |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap'); |
| body { |
| font-family: 'Inter', sans-serif; |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| } |
| .card-hover { |
| transition: all 0.3s ease; |
| } |
| .card-hover:hover { |
| transform: translateY(-5px); |
| box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); |
| } |
| .animate-pulse-slow { |
| animation: pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite; |
| } |
| @keyframes pulse { |
| 0%, 100% { opacity: 1; } |
| 50% { opacity: .5; } |
| } |
| </style> |
| </head> |
| <body class="min-h-screen text-gray-900"> |
| |
| <div id="vanta-bg" class="relative h-screen flex items-center justify-center overflow-hidden"> |
| <div class="absolute inset-0 bg-black opacity-70 z-0"></div> |
| <div class="relative z-10 text-center px-4 max-w-4xl"> |
| <h1 class="text-5xl md:text-7xl font-bold text-white mb-6 animate-fade-in"> |
| <span class="block">IconForge</span> |
| <span class="block text-transparent bg-clip-text bg-gradient-to-r from-purple-400 to-pink-600">Studio</span> |
| </h1> |
| <p class="text-xl md:text-2xl text-gray-200 mb-10 max-w-2xl mx-auto"> |
| AI-powered icon generation for language learning applications. Create stunning, culturally-aware icons with precision. |
| </p> |
| <div class="flex flex-col sm:flex-row justify-center gap-4"> |
| <button onclick="scrollToGenerator()" class="px-8 py-4 bg-gradient-to-r from-purple-600 to-indigo-600 text-white font-semibold rounded-full shadow-lg hover:from-purple-700 hover:to-indigo-700 transform hover:scale-105 transition-all duration-300"> |
| Generate Icons |
| </button> |
| <button onclick="scrollToFeatures()" class="px-8 py-4 bg-white bg-opacity-20 backdrop-blur-lg text-white font-semibold rounded-full shadow-lg hover:bg-opacity-30 transition-all duration-300"> |
| Learn More |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <section id="features" class="py-20 bg-white"> |
| <div class="container mx-auto px-4"> |
| <h2 class="text-4xl font-bold text-center mb-16 text-gray-800">Powerful Icon Generation</h2> |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-10"> |
| |
| <div class="bg-gradient-to-br from-gray-50 to-gray-100 p-8 rounded-2xl shadow-lg card-hover"> |
| <div class="w-16 h-16 rounded-full bg-purple-100 flex items-center justify-center mb-6"> |
| <i data-feather="cpu" class="text-purple-600 w-8 h-8"></i> |
| </div> |
| <h3 class="text-2xl font-bold mb-3 text-gray-800">AI-Powered Design</h3> |
| <p class="text-gray-600"> |
| Leverage advanced AI models to generate high-quality, contextually appropriate icons for language learning. |
| </p> |
| </div> |
| |
| |
| <div class="bg-gradient-to-br from-gray-50 to-gray-100 p-8 rounded-2xl shadow-lg card-hover"> |
| <div class="w-16 h-16 rounded-full bg-indigo-100 flex items-center justify-center mb-6"> |
| <i data-feather="globe" class="text-indigo-600 w-8 h-8"></i> |
| </div> |
| <h3 class="text-2xl font-bold mb-3 text-gray-800">Multilingual Support</h3> |
| <p class="text-gray-600"> |
| Generate icons for words in multiple languages with cultural sensitivity and semantic accuracy. |
| </p> |
| </div> |
| |
| |
| <div class="bg-gradient-to-br from-gray-50 to-gray-100 p-8 rounded-2xl shadow-lg card-hover"> |
| <div class="w-16 h-16 rounded-full bg-pink-100 flex items-center justify-center mb-6"> |
| <i data-feather="sliders" class="text-pink-600 w-8 h-8"></i> |
| </div> |
| <h3 class="text-2xl font-bold mb-3 text-gray-800">Customizable Styles</h3> |
| <p class="text-gray-600"> |
| Fine-tune icon appearance with style tags, difficulty levels, and visual parameters. |
| </p> |
| </div> |
| </div> |
| </div> |
| </section> |
|
|
| |
| <section id="generator" class="py-20 bg-gradient-to-br from-gray-50 to-gray-100"> |
| <div class="container mx-auto px-4"> |
| <h2 class="text-4xl font-bold text-center mb-4 text-gray-800">Icon Generator</h2> |
| <p class="text-xl text-center text-gray-600 mb-12 max-w-2xl mx-auto"> |
| Create custom icons by specifying word details and style preferences |
| </p> |
| |
| <div class="max-w-4xl mx-auto bg-white rounded-2xl shadow-xl overflow-hidden"> |
| <div class="md:flex"> |
| <div class="md:w-1/2 p-8"> |
| <form id="iconForm" class="space-y-6"> |
| <div> |
| <label class="block text-gray-700 font-medium mb-2">Turkish Word</label> |
| <input type="text" id="word_tr" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" placeholder="Enter Turkish word" required> |
| </div> |
| |
| <div> |
| <label class="block text-gray-700 font-medium mb-2">Arabic Translation</label> |
| <input type="text" id="word_ar" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" placeholder="Enter Arabic translation" required> |
| </div> |
| |
| <div> |
| <label class="block text-gray-700 font-medium mb-2">Category</label> |
| <select id="category" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent"> |
| <option value="Clothing">Clothing</option> |
| <option value="Food">Food</option> |
| <option value="Transportation">Transportation</option> |
| <option value="Nature">Nature</option> |
| <option value="Technology">Technology</option> |
| </select> |
| </div> |
| |
| <div> |
| <label class="block text-gray-700 font-medium mb-2">CEFR Level</label> |
| <select id="cefr_level" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent"> |
| <option value="A1">A1 - Beginner</option> |
| <option value="A2">A2 - Elementary</option> |
| <option value="B1">B1 - Intermediate</option> |
| <option value="B2">B2 - Upper Intermediate</option> |
| <option value="C1">C1 - Advanced</option> |
| <option value="C2">C2 - Proficiency</option> |
| </select> |
| </div> |
| |
| <div> |
| <label class="block text-gray-700 font-medium mb-2">Difficulty (1-5)</label> |
| <input type="range" id="difficulty" min="1" max="5" value="3" class="w-full"> |
| <div class="flex justify-between text-sm text-gray-600 mt-1"> |
| <span>1</span> |
| <span>2</span> |
| <span>3</span> |
| <span>4</span> |
| <span>5</span> |
| </div> |
| </div> |
| |
| <div> |
| <label class="block text-gray-700 font-medium mb-2">Style Tags (comma separated)</label> |
| <input type="text" id="style_tags" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" placeholder="e.g., friendly, kids, polished"> |
| </div> |
| |
| <div> |
| <label class="block text-gray-700 font-medium mb-2">Turkish Example Sentence</label> |
| <input type="text" id="usage_tr" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" placeholder="e.g., Ceketimi dolaba astım."> |
| </div> |
| |
| <div> |
| <label class="block text-gray-700 font-medium mb-2">Arabic Example Sentence</label> |
| <input type="text" id="usage_ar" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" placeholder="e.g., علّقتُ معطفي في الخزانة."> |
| </div> |
| |
| <button type="submit" class="w-full py-4 bg-gradient-to-r from-purple-600 to-indigo-600 text-white font-semibold rounded-lg shadow-md hover:from-purple-700 hover:to-indigo-700 transform hover:scale-[1.02] transition-all duration-300"> |
| Generate Icon |
| </button> |
| </form> |
| </div> |
| |
| <div class="md:w-1/2 bg-gradient-to-br from-purple-500 to-indigo-600 p-8 flex flex-col items-center justify-center"> |
| <div class="text-center mb-8"> |
| <h3 class="text-2xl font-bold text-white mb-2">Preview</h3> |
| <p class="text-purple-100">Your generated icon will appear here</p> |
| </div> |
| |
| <div class="bg-white bg-opacity-20 backdrop-blur-lg rounded-2xl p-6 w-64 h-64 flex items-center justify-center"> |
| <div id="icon-preview" class="w-48 h-48 bg-gray-200 rounded-xl flex items-center justify-center"> |
| <i data-feather="image" class="text-gray-400 w-12 h-12"></i> |
| </div> |
| </div> |
| |
| <div class="mt-8 text-center"> |
| <p class="text-purple-100 text-sm">1024×1024px | PNG Format</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </section> |
|
|
| |
| <section class="py-20 bg-white"> |
| <div class="container mx-auto px-4"> |
| <h2 class="text-4xl font-bold text-center mb-16 text-gray-800">How It Works</h2> |
| |
| <div class="flex flex-col md:flex-row items-center justify-between gap-12"> |
| <div class="md:w-1/2"> |
| <div class="relative"> |
| <div class="absolute -left-8 top-0 w-16 h-16 rounded-full bg-purple-100 flex items-center justify-center"> |
| <span class="text-purple-600 font-bold text-xl">1</span> |
| </div> |
| <div class="pl-12"> |
| <h3 class="text-2xl font-bold text-gray-800 mb-3">Input Word Details</h3> |
| <p class="text-gray-600"> |
| Enter the word in Turkish and Arabic, select category, CEFR level, difficulty, and style preferences. |
| </p> |
| </div> |
| </div> |
| |
| <div class="relative mt-12"> |
| <div class="absolute -left-8 top-0 w-16 h-16 rounded-full bg-indigo-100 flex items-center justify-center"> |
| <span class="text-indigo-600 font-bold text-xl">2</span> |
| </div> |
| <div class="pl-12"> |
| <h3 class="text-2xl font-bold text-gray-800 mb-3">AI Prompt Generation</h3> |
| <p class="text-gray-600"> |
| Our system creates a precise prompt for the AI image generator based on your inputs and linguistic requirements. |
| </p> |
| </div> |
| </div> |
| |
| <div class="relative mt-12"> |
| <div class="absolute -left-8 top-0 w-16 h-16 rounded-full bg-pink-100 flex items-center justify-center"> |
| <span class="text-pink-600 font-bold text-xl">3</span> |
| </div> |
| <div class="pl-12"> |
| <h3 class="text-2xl font-bold text-gray-800 mb-3">Icon Rendering</h3> |
| <p class="text-gray-600"> |
| The AI generates a high-quality, skeuomorphic 3D icon that meets all specified criteria. |
| </p> |
| </div> |
| </div> |
| </div> |
| |
| <div class="md:w-2/5"> |
| <div class="bg-gradient-to-br from-gray-50 to-gray-100 rounded-2xl p-8 shadow-lg"> |
| <div class="flex justify-center mb-6"> |
| <div class="w-32 h-32 rounded-full bg-gradient-to-br from-purple-400 to-indigo-500 flex items-center justify-center"> |
| <i data-feather="zap" class="text-white w-16 h-16"></i> |
| </div> |
| </div> |
| <h3 class="text-2xl font-bold text-center text-gray-800 mb-4">AI Pipeline</h3> |
| <p class="text-gray-600 text-center"> |
| Powered by Gemini for prompt engineering and ComfyUI for image generation |
| </p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </section> |
| |
| <section class="py-20 bg-gradient-to-br from-gray-50 to-white"> |
| <div class="container mx-auto px-4"> |
| <h2 class="text-4xl font-bold text-center mb-16 text-gray-800">System Status</h2> |
| |
| <div class="max-w-4xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-6"> |
| <div class="bg-white rounded-xl shadow-md p-6"> |
| <div class="flex items-center justify-between mb-4"> |
| <h3 class="text-lg font-semibold text-gray-700">Gemini API</h3> |
| <div id="gemini-status" class="w-3 h-3 rounded-full bg-yellow-400 animate-pulse"></div> |
| </div> |
| <p class="text-sm text-gray-600">Prompt Engineering</p> |
| </div> |
| |
| <div class="bg-white rounded-xl shadow-md p-6"> |
| <div class="flex items-center justify-between mb-4"> |
| <h3 class="text-lg font-semibold text-gray-700">ComfyUI</h3> |
| <div id="comfyui-status" class="w-3 h-3 rounded-full bg-yellow-400 animate-pulse"></div> |
| </div> |
| <p class="text-sm text-gray-600">Image Generation</p> |
| </div> |
| |
| <div class="bg-white rounded-xl shadow-md p-6"> |
| <div class="flex items-center justify-between mb-4"> |
| <h3 class="text-lg font-semibold text-gray-700">Job Queue</h3> |
| <div id="queue-status" class="w-3 h-3 rounded-full bg-green-400"></div> |
| </div> |
| <p class="text-sm text-gray-600">Processing: <span id="queue-count">0</span> jobs</p> |
| </div> |
| </div> |
| |
| <div class="mt-8 text-center"> |
| <button onclick="checkSystemHealth()" class="px-6 py-3 bg-purple-600 text-white font-medium rounded-lg hover:bg-purple-700 transition-colors"> |
| Check Health |
| </button> |
| </div> |
| </div> |
| </section> |
|
|
| |
| <footer class="bg-gray-900 text-white py-12"> |
| <div class="container mx-auto px-4"> |
| <div class="flex flex-col md:flex-row justify-between items-center"> |
| <div class="mb-6 md:mb-0"> |
| <h2 class="text-2xl font-bold flex items-center"> |
| <span class="mr-2">🎨</span> IconForge Studio |
| </h2> |
| <p class="text-gray-400 mt-2">AI-powered icon generation for language learning</p> |
| <div class="flex items-center mt-2 text-sm text-gray-500"> |
| <i data-feather="cpu" class="w-4 h-4 mr-1"></i> |
| <span>Powered by Gemini + ComfyUI</span> |
| </div> |
| </div> |
| |
| <div class="flex space-x-6"> |
| <a href="#" class="text-gray-400 hover:text-white transition-colors"> |
| <i data-feather="github" class="w-6 h-6"></i> |
| </a> |
| <a href="#" class="text-gray-400 hover:text-white transition-colors"> |
| <i data-feather="twitter" class="w-6 h-6"></i> |
| </a> |
| <a href="#" class="text-gray-400 hover:text-white transition-colors"> |
| <i data-feather="linkedin" class="w-6 h-6"></i> |
| </a> |
| </div> |
| </div> |
| |
| <div class="border-t border-gray-800 mt-8 pt-8 text-center text-gray-400"> |
| <p>© 2023 IconForge Studio. All rights reserved.</p> |
| <p class="text-xs mt-2">v1.0.0 | Production Ready</p> |
| </div> |
| </div> |
| </footer> |
| <script> |
| |
| VANTA.GLOBE({ |
| el: "#vanta-bg", |
| mouseControls: true, |
| touchControls: true, |
| gyroControls: false, |
| minHeight: 200.00, |
| minWidth: 200.00, |
| scale: 1.00, |
| scaleMobile: 1.00, |
| color: 0x6a11cb, |
| color2: 0x2575fc, |
| backgroundColor: 0x0 |
| }); |
| |
| |
| feather.replace(); |
| |
| |
| window.addEventListener('load', checkSystemHealth); |
| |
| |
| function checkSystemHealth() { |
| |
| fetch('/api/health/gemini') |
| .then(r => r.json()) |
| .then(data => { |
| const status = document.getElementById('gemini-status'); |
| status.className = `w-3 h-3 rounded-full ${data.status === 'healthy' ? 'bg-green-400' : 'bg-red-400'}`; |
| }) |
| .catch(() => { |
| document.getElementById('gemini-status').className = 'w-3 h-3 rounded-full bg-red-400'; |
| }); |
| |
| |
| fetch('/api/health/comfyui') |
| .then(r => r.json()) |
| .then(data => { |
| const status = document.getElementById('comfyui-status'); |
| status.className = `w-3 h-3 rounded-full ${data.status === 'healthy' ? 'bg-green-400' : 'bg-red-400'}`; |
| }) |
| .catch(() => { |
| document.getElementById('comfyui-status').className = 'w-3 h-3 rounded-full bg-red-400'; |
| }); |
| |
| |
| fetch('/api/queue/status') |
| .then(r => r.json()) |
| .then(data => { |
| document.getElementById('queue-count').textContent = data.pending || 0; |
| const status = document.getElementById('queue-status'); |
| status.className = `w-3 h-3 rounded-full ${data.pending > 0 ? 'bg-yellow-400 animate-pulse' : 'bg-green-400'}`; |
| }) |
| .catch(() => { |
| document.getElementById('queue-status').className = 'w-3 h-3 rounded-full bg-red-400'; |
| }); |
| } |
| |
| document.getElementById('iconForm').addEventListener('submit', function(e) { |
| e.preventDefault(); |
| |
| const word_tr = document.getElementById('word_tr').value; |
| const word_ar = document.getElementById('word_ar').value; |
| const category = document.getElementById('category').value; |
| const cefr_level = document.getElementById('cefr_level').value; |
| const difficulty = document.getElementById('difficulty').value; |
| const style_tags = document.getElementById('style_tags').value.split(',').map(tag => tag.trim()).filter(tag => tag); |
| const usage_tr = document.getElementById('usage_tr').value; |
| const usage_ar = document.getElementById('usage_ar').value; |
| |
| |
| const body = { |
| word_tr, |
| word_ar, |
| category, |
| cefr_level, |
| difficulty: parseInt(difficulty), |
| usage_tr, |
| usage_ar, |
| style_tags |
| }; |
| |
| const preview = document.getElementById('icon-preview'); |
| preview.innerHTML = '<div class="animate-pulse-slow text-gray-500">Generating...</div>'; |
| |
| fetch('/api/generate-icon', { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify(body) |
| }) |
| .then(r => r.json()) |
| .then(data => { |
| if (data.url) { |
| preview.innerHTML = `<img src="${data.url}" class="w-full h-full object-contain rounded-xl" alt="Generated icon">`; |
| } else if (data.job_id) { |
| |
| preview.innerHTML = ` |
| <div class="text-center"> |
| <div class="animate-spin rounded-full h-12 w-12 border-b-2 border-purple-600 mx-auto mb-4"></div> |
| <p class="text-gray-600 text-sm">Job queued: ${data.job_id}</p> |
| <p class="text-gray-500 text-xs mt-2">Generating icon...</p> |
| </div> |
| `; |
| |
| pollJobStatus(data.job_id); |
| } else { |
| throw new Error(data.error || 'Unknown error'); |
| } |
| }) |
| .catch(err => { |
| preview.innerHTML = `<div class="text-red-500 text-sm text-center">${err.message}</div>`; |
| }); |
| |
| |
| function pollJobStatus(jobId) { |
| const pollInterval = setInterval(() => { |
| fetch(`/api/job-status/${jobId}`) |
| .then(r => r.json()) |
| .then(data => { |
| if (data.status === 'completed' && data.url) { |
| clearInterval(pollInterval); |
| preview.innerHTML = `<img src="${data.url}" class="w-full h-full object-contain rounded-xl" alt="Generated icon">`; |
| } else if (data.status === 'failed') { |
| clearInterval(pollInterval); |
| preview.innerHTML = `<div class="text-red-500 text-sm text-center">Generation failed: ${data.error}</div>`; |
| } |
| }) |
| .catch(err => { |
| clearInterval(pollInterval); |
| preview.innerHTML = `<div class="text-red-500 text-sm text-center">Error checking status: ${err.message}</div>`; |
| }); |
| }, 2000); |
| |
| |
| setTimeout(() => clearInterval(pollInterval), 120000); |
| } |
| }); |
| |
| function scrollToGenerator() { |
| document.getElementById('generator').scrollIntoView({ behavior: 'smooth' }); |
| } |
| |
| function scrollToFeatures() { |
| document.getElementById('features').scrollIntoView({ behavior: 'smooth' }); |
| } |
| |
| |
| document.addEventListener('keydown', function(e) { |
| |
| if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { |
| const form = document.getElementById('iconForm'); |
| if (form) form.dispatchEvent(new Event('submit')); |
| } |
| |
| if (e.key === 'Escape') { |
| document.getElementById('iconForm').reset(); |
| document.getElementById('icon-preview').innerHTML = '<i data-feather="image" class="text-gray-400 w-12 h-12"></i>'; |
| feather.replace(); |
| } |
| }); |
| |
| |
| const difficultySlider = document.getElementById('difficulty'); |
| const difficultyValue = document.createElement('div'); |
| difficultyValue.className = 'text-center text-sm font-medium text-purple-600 mt-2'; |
| difficultySlider.parentNode.appendChild(difficultyValue); |
| |
| difficultySlider.addEventListener('input', function() { |
| difficultyValue.textContent = `Difficulty: ${this.value}`; |
| }); |
| difficultyValue.textContent = `Difficulty: ${difficultySlider.value}`; |
| </script> |
| </body> |
| </html> |
|
|