Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>SummAI | Professional Text Summarizer</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet"> | |
| </head> | |
| <body class="bg-gray-50 text-gray-900 font-sans leading-normal tracking-normal"> | |
| <nav class="bg-white shadow-sm border-b border-gray-200 py-4 px-6"> | |
| <div class="max-w-7xl mx-auto flex justify-between items-center"> | |
| <div class="flex items-center space-x-2"> | |
| <i class="fa-solid font-bold text-indigo-600 text-2xl"></i> | |
| <span class="text-xl font-extrabold tracking-tight text-gray-800">Summ<span class="text-indigo-600">AI</span></span> | |
| </div> | |
| <div class="hidden md:flex space-x-6 text-sm font-medium text-gray-500"> | |
| <span class="hover:text-indigo-600 cursor-pointer">Abstractive AI</span> | |
| <span class="hover:text-indigo-600 cursor-pointer">BART Model</span> | |
| </div> | |
| </div> | |
| </nav> | |
| <main class="max-w-6xl mx-auto py-12 px-4 sm:px-6 lg:px-8"> | |
| <div class="text-center mb-12"> | |
| <h1 class="text-4xl font-extrabold text-gray-900 sm:text-5xl"> | |
| Summarize content in <span class="text-indigo-600">seconds.</span> | |
| </h1> | |
| <p class="mt-4 text-lg text-gray-600 max-w-2xl mx-auto"> | |
| Paste long articles, research papers, or reports and let our AI provide a professional-grade summary instantly. | |
| </p> | |
| </div> | |
| <div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> | |
| <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-100"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h3 class="text-lg font-bold text-gray-800">Original Text</h3> | |
| <span id="charCount" class="text-xs text-gray-400 font-medium">0 words</span> | |
| </div> | |
| <textarea id="inputText" | |
| class="w-full h-80 p-4 bg-gray-50 border border-gray-200 rounded-xl focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition resize-none placeholder-gray-400" | |
| placeholder="Paste your text here (minimum 20 words for best results)..."></textarea> | |
| <button id="sumBtn" onclick="summarize()" | |
| class="mt-6 w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-4 rounded-xl transition-all duration-200 flex items-center justify-center space-x-2 shadow-lg shadow-indigo-200"> | |
| <i class="fa-solid fa-wand-sparkles"></i> | |
| <span>Generate Summary</span> | |
| </button> | |
| </div> | |
| <div class="bg-white rounded-2xl shadow-xl p-6 border border-gray-100 flex flex-col"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h3 class="text-lg font-bold text-gray-800">AI Summary</h3> | |
| <button onclick="copyToClipboard()" class="text-indigo-600 hover:text-indigo-800 text-sm font-semibold flex items-center space-x-1"> | |
| <i class="fa-regular fa-copy"></i> | |
| <span>Copy</span> | |
| </button> | |
| </div> | |
| <div id="outputBox" class="flex-grow w-full h-80 p-4 bg-indigo-50/30 border-2 border-dashed border-indigo-100 rounded-xl overflow-y-auto"> | |
| <p id="outputPlaceholder" class="text-gray-400 italic">Your summary will appear here after processing...</p> | |
| <p id="outputText" class="text-gray-700 hidden leading-relaxed"></p> | |
| </div> | |
| <div id="statusMessage" class="mt-4 text-sm text-gray-500 flex items-center space-x-2 opacity-0 transition-opacity"> | |
| <i class="fa-solid fa-circle-notch fa-spin text-indigo-600"></i> | |
| <span>AI is thinking...</span> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <footer class="mt-12 py-8 text-center text-gray-400 text-sm border-t border-gray-100"> | |
| © 2026 SummAI. Powered by Hugging Face Transformers. | |
| </footer> | |
| <script> | |
| // Word counter logic | |
| document.getElementById('inputText').addEventListener('input', function() { | |
| const words = this.value.trim().split(/\s+/).filter(x => x.length > 0).length; | |
| document.getElementById('charCount').innerText = `${words} words`; | |
| }); | |
| async function summarize() { | |
| const inputText = document.getElementById('inputText').value; | |
| const outputText = document.getElementById('outputText'); | |
| const outputPlaceholder = document.getElementById('outputPlaceholder'); | |
| const statusMessage = document.getElementById('statusMessage'); | |
| const btn = document.getElementById('sumBtn'); | |
| if (inputText.split(/\s+/).length < 20) { | |
| alert("Please enter at least 20 words for a meaningful summary."); | |
| return; | |
| } | |
| // Start Loading State | |
| btn.disabled = true; | |
| btn.classList.add('opacity-50', 'cursor-not-allowed'); | |
| statusMessage.classList.add('opacity-100'); | |
| outputPlaceholder.innerText = "Analyzing text and generating summary..."; | |
| outputText.classList.add('hidden'); | |
| try { | |
| const response = await fetch('/summarize', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ text: inputText }) | |
| }); | |
| const data = await response.json(); | |
| if (response.ok) { | |
| outputText.innerText = data.summary; | |
| outputText.classList.remove('hidden'); | |
| outputPlaceholder.classList.add('hidden'); | |
| } else { | |
| alert(data.error || "An error occurred"); | |
| outputPlaceholder.innerText = "Summary failed. Please try again."; | |
| } | |
| } catch (error) { | |
| console.error("Error:", error); | |
| alert("Failed to connect to the server."); | |
| } finally { | |
| // End Loading State | |
| btn.disabled = false; | |
| btn.classList.remove('opacity-50', 'cursor-not-allowed'); | |
| statusMessage.classList.remove('opacity-100'); | |
| } | |
| } | |
| function copyToClipboard() { | |
| const text = document.getElementById('outputText').innerText; | |
| if (!text) return; | |
| navigator.clipboard.writeText(text).then(() => { | |
| alert("Summary copied to clipboard!"); | |
| }); | |
| } | |
| </script> | |
| </body> | |
| </html> |