commit d5b119ca9b4429df8be9e7573430219635ae4562
Author: root <root@hub.scroll.pub>
Date: 2025-01-01 10:53:32 +0000
Subject: Initial commit
diff --git a/.stats.json b/.stats.json
new file mode 100644
index 0000000..b174054
--- /dev/null
+++ b/.stats.json
@@ -0,0 +1,21 @@
+{
+ "files": [
+ "body.html",
+ "index.scroll",
+ "prompt.json",
+ "readme.scroll",
+ "script.js",
+ "style.css"
+ ],
+ "hasSslCert": false,
+ "stats": {
+ "folder": "speaksum1.scroll.pub",
+ "folderLink": "http://speaksum1.scroll.pub",
+ "created": "2025-01-01T10:53:01.000Z",
+ "revised": "2025-01-01T10:53:01.000Z",
+ "files": 6,
+ "mb": 1,
+ "revisions": 1,
+ "hash": "0e173ddf50"
+ }
+}
\ No newline at end of file
diff --git a/body.html b/body.html
index a3d0bf6..d644ab1 100644
--- a/body.html
+++ b/body.html
@@ -1,41 +1,50 @@
<header>
<nav>
- <h1>Speak<span>Sum</span></h1>
+ <div class="logo">SpeakSum</div>
+ <button class="theme-toggle" aria-label="Toggle dark mode">
+ <span class="sun">☀️</span>
+ <span class="moon">🌙</span>
+ </button>
</nav>
</header>
<main>
<section class="hero">
- <h2>Convert Speech to Text and Get Instant Summaries</h2>
- <p>Speak naturally and get both transcription and smart summaries in seconds</p>
+ <h1>Transform Speech to Text & Get Instant Summaries</h1>
+ <p>Speak naturally and get both transcription and summarization in real-time</p>
</section>
<section class="converter">
<div class="controls">
<button id="startBtn" class="primary-btn">
- <span class="icon">🎤</span>
- Start Speaking
+ <span class="mic-icon">🎤</span>
+ Start Recording
</button>
- <button id="stopBtn" class="secondary-btn" disabled>
- <span class="icon">⏹️</span>
- Stop
+ <button id="stopBtn" class="primary-btn" disabled>
+ <span class="stop-icon">⬛</span>
+ Stop Recording
</button>
</div>
<div class="output-container">
- <div class="transcript-box">
- <h3>Transcript</h3>
- <div id="transcript" contenteditable="true" class="output-box"></div>
+ <div class="transcription-box">
+ <h2>Transcription</h2>
+ <div id="transcription" class="text-output" contenteditable="true" role="textbox" aria-label="Transcription output"></div>
</div>
<div class="summary-box">
- <h3>Summary</h3>
- <div id="summary" class="output-box"></div>
+ <h2>Summary</h2>
+ <div id="summary" class="text-output" role="textbox" aria-label="Summary output"></div>
</div>
</div>
</section>
</main>
<footer>
- <p>Made with care by SpeakSum</p>
+ <p>Built with care by SpeakSum team</p>
+ <nav>
+ <a href="/privacy">Privacy Policy</a>
+ <a href="/terms">Terms of Use</a>
+ <a href="/contact">Contact</a>
+ </nav>
</footer>
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..09c843e
--- /dev/null
+++ b/index.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>SpeakSum - Speech to Text & Summary</title>
+ <script>/* This HTML was generated by 📜 Scroll v164.11.0. https://scroll.pub */</script>
+ <style>@media print {.doNotPrint {display: none !important;}}</style>
+ <link rel="canonical" href="https://speaksum.scroll.pub/index.html">
+ <meta name="viewport" content="width=device-width,initial-scale=1">
+ <meta name="description" content="">
+ <meta name="generator" content="Scroll v164.11.0">
+ <meta property="og:title" content="SpeakSum - Speech to Text & Summary">
+ <meta property="og:description" content="">
+ <meta property="og:image" content="">
+
+ <link rel="source" type="application/git" title="Source Code Repository" href="index.scroll">
+
+ <meta name="twitter:card" content="summary_large_image">
+</head>
+<body>
+<style>.abstractIconButtonParser {position:absolute;top:0.25rem; }.abstractIconButtonParser svg {fill: rgba(204,204,204,.8);width:1.875rem;height:1.875rem; padding: 0 7px;} .abstractIconButtonParser:hover svg{fill: #333;}</style><a href="/edit.html" class="doNotPrint abstractIconButtonParser" style="right:2rem;"><svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M21.1213 2.70705C19.9497 1.53548 18.0503 1.53547 16.8787 2.70705L15.1989 4.38685L7.29289 12.2928C7.16473 12.421 7.07382 12.5816 7.02986 12.7574L6.02986 16.7574C5.94466 17.0982 6.04451 17.4587 6.29289 17.707C6.54127 17.9554 6.90176 18.0553 7.24254 17.9701L11.2425 16.9701C11.4184 16.9261 11.5789 16.8352 11.7071 16.707L19.5556 8.85857L21.2929 7.12126C22.4645 5.94969 22.4645 4.05019 21.2929 2.87862L21.1213 2.70705ZM18.2929 4.12126C18.6834 3.73074 19.3166 3.73074 19.7071 4.12126L19.8787 4.29283C20.2692 4.68336 20.2692 5.31653 19.8787 5.70705L18.8622 6.72357L17.3068 5.10738L18.2929 4.12126ZM15.8923 6.52185L17.4477 8.13804L10.4888 15.097L8.37437 15.6256L8.90296 13.5112L15.8923 6.52185ZM4 7.99994C4 7.44766 4.44772 6.99994 5 6.99994H10C10.5523 6.99994 11 6.55223 11 5.99994C11 5.44766 10.5523 4.99994 10 4.99994H5C3.34315 4.99994 2 6.34309 2 7.99994V18.9999C2 20.6568 3.34315 21.9999 5 21.9999H16C17.6569 21.9999 19 20.6568 19 18.9999V13.9999C19 13.4477 18.5523 12.9999 18 12.9999C17.4477 12.9999 17 13.4477 17 13.9999V18.9999C17 19.5522 16.5523 19.9999 16 19.9999H5C4.44772 19.9999 4 19.5522 4 18.9999V7.99994Z"/></svg></a>
+<link rel="stylesheet" type="text/css" href="style.css">
+<header>
+ <nav>
+ <h1>Speak<span>Sum</span></h1>
+ </nav>
+</header>
+
+<main>
+ <section class="hero">
+ <h2>Convert Speech to Text and Get Instant Summaries</h2>
+ <p>Speak naturally and get both transcription and smart summaries in seconds</p>
+ </section>
+
+ <section class="converter">
+ <div class="controls">
+ <button id="startBtn" class="primary-btn">
+ <span class="icon">🎤</span>
+ Start Speaking
+ </button>
+ <button id="stopBtn" class="secondary-btn" disabled>
+ <span class="icon">⏹️</span>
+ Stop
+ </button>
+ </div>
+
+ <div class="output-container">
+ <div class="transcript-box">
+ <h3>Transcript</h3>
+ <div id="transcript" contenteditable="true" class="output-box"></div>
+ </div>
+
+ <div class="summary-box">
+ <h3>Summary</h3>
+ <div id="summary" class="output-box"></div>
+ </div>
+ </div>
+ </section>
+</main>
+
+<footer>
+ <p>Made with care by SpeakSum</p>
+</footer>
+
+<script src="script.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/index.scroll b/index.scroll
index b421912..2171cdc 100644
--- a/index.scroll
+++ b/index.scroll
@@ -1,8 +1,10 @@
buildHtml
baseUrl https://speaksum.scroll.pub
metaTags
+ description "Convert speech to text and get instant summaries. Free, fast, and easy to use speech recognition and text summarization tool."
+ keywords "speech to text, voice recognition, text summarization, speech summarization, voice to text"
editButton /edit.html
-title SpeakSum - Speech to Text & Summary
+title SpeakSum - Speech to Text & Summarization
style.css
body.html
script.js
diff --git a/prompt.json b/prompt.json
index 8fd2020..63af20e 100644
--- a/prompt.json
+++ b/prompt.json
@@ -1,12 +1,12 @@
{
- "id": "msg_01BQzZ9qbe816kSHp4bKrvjE",
+ "id": "msg_01L9zz6dGoctbUB71NCQPkgg",
"type": "message",
"role": "assistant",
"model": "claude-3-5-sonnet-20241022",
"content": [
{
"type": "text",
- "text": "Here's a complete website design for a speech-to-text conversion and summarization tool:\n\n---domain---\nspeaksum.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://speaksum.scroll.pub\nmetaTags\neditButton /edit.html\ntitle SpeakSum - Speech to Text & Summary\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n<header>\n <nav>\n <h1>Speak<span>Sum</span></h1>\n </nav>\n</header>\n\n<main>\n <section class=\"hero\">\n <h2>Convert Speech to Text and Get Instant Summaries</h2>\n <p>Speak naturally and get both transcription and smart summaries in seconds</p>\n </section>\n\n <section class=\"converter\">\n <div class=\"controls\">\n <button id=\"startBtn\" class=\"primary-btn\">\n <span class=\"icon\">🎤</span>\n Start Speaking\n </button>\n <button id=\"stopBtn\" class=\"secondary-btn\" disabled>\n <span class=\"icon\">⏹️</span>\n Stop\n </button>\n </div>\n\n <div class=\"output-container\">\n <div class=\"transcript-box\">\n <h3>Transcript</h3>\n <div id=\"transcript\" contenteditable=\"true\" class=\"output-box\"></div>\n </div>\n \n <div class=\"summary-box\">\n <h3>Summary</h3>\n <div id=\"summary\" class=\"output-box\"></div>\n </div>\n </div>\n </section>\n</main>\n\n<footer>\n <p>Made with care by SpeakSum</p>\n</footer>\n\n---style.css---\n:root {\n --primary-color: #4a90e2;\n --secondary-color: #2c3e50;\n --accent-color: #e74c3c;\n --background: #f5f6fa;\n --text-color: #2c3e50;\n --box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: 'Segoe UI', system-ui, sans-serif;\n line-height: 1.6;\n color: var(--text-color);\n background: var(--background);\n}\n\nheader {\n background: white;\n padding: 1rem;\n box-shadow: var(--box-shadow);\n}\n\nh1 {\n font-size: 2rem;\n color: var(--secondary-color);\n}\n\nh1 span {\n color: var(--primary-color);\n}\n\n.hero {\n text-align: center;\n padding: 4rem 2rem;\n background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));\n color: white;\n}\n\n.hero h2 {\n font-size: 2.5rem;\n margin-bottom: 1rem;\n}\n\n.converter {\n max-width: 1200px;\n margin: 2rem auto;\n padding: 0 1rem;\n}\n\n.controls {\n display: flex;\n gap: 1rem;\n justify-content: center;\n margin-bottom: 2rem;\n}\n\n.primary-btn, .secondary-btn {\n padding: 1rem 2rem;\n border: none;\n border-radius: 50px;\n cursor: pointer;\n font-size: 1rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n transition: transform 0.2s;\n}\n\n.primary-btn {\n background: var(--primary-color);\n color: white;\n}\n\n.secondary-btn {\n background: var(--secondary-color);\n color: white;\n}\n\n.primary-btn:hover, .secondary-btn:hover {\n transform: translateY(-2px);\n}\n\n.output-container {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 2rem;\n}\n\n.output-box {\n background: white;\n border-radius: 10px;\n padding: 1rem;\n min-height: 300px;\n box-shadow: var(--box-shadow);\n}\n\nh3 {\n margin-bottom: 1rem;\n color: var(--secondary-color);\n}\n\nfooter {\n text-align: center;\n padding: 2rem;\n background: white;\n margin-top: 4rem;\n}\n\n@media (max-width: 768px) {\n .output-container {\n grid-template-columns: 1fr;\n }\n \n .hero h2 {\n font-size: 2rem;\n }\n}\n\n---script.js---\ndocument.addEventListener('DOMContentLoaded', () => {\n const startBtn = document.getElementById('startBtn');\n const stopBtn = document.getElementById('stopBtn');\n const transcript = document.getElementById('transcript');\n const summary = document.getElementById('summary');\n\n let recognition = null;\n \n if ('webkitSpeechRecognition' in window) {\n recognition = new webkitSpeechRecognition();\n recognition.continuous = true;\n recognition.interimResults = true;\n } else {\n startBtn.disabled = true;\n transcript.innerHTML = 'Speech recognition is not supported in this browser.';\n }\n\n function summarizeText(text) {\n // Simple summarization algorithm (example)\n const sentences = text.split(/[.!?]+/);\n const significantSentences = sentences\n .filter(sentence => sentence.length > 10)\n .slice(0, 3);\n return significantSentences.join('. ') + '.';\n }\n\n if (recognition) {\n recognition.onresult = (event) => {\n let finalTranscript = '';\n \n for (let i = event.resultIndex; i < event.results.length; i++) {\n const transcript = event.results[i][0].transcript;\n if (event.results[i].isFinal) {\n finalTranscript += transcript + ' ';\n }\n }\n\n if (finalTranscript) {\n transcript.textContent = finalTranscript;\n summary.textContent = summarizeText(finalTranscript);\n }\n };\n\n startBtn.addEventListener('click', () => {\n transcript.textContent = '';\n summary.textContent = '';\n recognition.start();\n startBtn.disabled = true;\n stopBtn.disabled = false;\n });\n\n stopBtn.addEventListener('click', () => {\n recognition.stop();\n startBtn.disabled = false;\n stopBtn.disabled = true;\n });\n\n recognition.onerror = (event) => {\n console.error('Speech recognition error:', event.error);\n startBtn.disabled = false;\n stopBtn.disabled = true;\n };\n }\n});\n\n---end---\n\nThis implementation features:\n\n1. Clean, semantic HTML5 structure\n2. Beautiful gradient-based design with smooth animations\n3. Responsive layout that works well on mobile devices\n4. Real-time speech recognition using the Web Speech API\n5. Basic text summarization functionality\n6. Accessible controls and ARIA-compliant markup\n7. Modern CSS with variables and flexible layouts\n8. Error handling and browser compatibility checks\n9. Smooth transitions and hover effects\n10. Professional typography and spacing\n\nThe site uses a two-column layout for desktop that gracefully collapses to a single column on mobile devices. The color scheme is professional and modern, with careful attention to contrast and readability."
+ "text": "Here's a speech-to-text conversion and summarization website:\n\n---domain---\nspeaksum.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://speaksum.scroll.pub\nmetaTags\n description \"Convert speech to text and get instant summaries. Free, fast, and easy to use speech recognition and text summarization tool.\"\n keywords \"speech to text, voice recognition, text summarization, speech summarization, voice to text\"\neditButton /edit.html\ntitle SpeakSum - Speech to Text & Summarization\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n<header>\n <nav>\n <div class=\"logo\">SpeakSum</div>\n <button class=\"theme-toggle\" aria-label=\"Toggle dark mode\">\n <span class=\"sun\">☀️</span>\n <span class=\"moon\">🌙</span>\n </button>\n </nav>\n</header>\n\n<main>\n <section class=\"hero\">\n <h1>Transform Speech to Text & Get Instant Summaries</h1>\n <p>Speak naturally and get both transcription and summarization in real-time</p>\n </section>\n\n <section class=\"converter\">\n <div class=\"controls\">\n <button id=\"startBtn\" class=\"primary-btn\">\n <span class=\"mic-icon\">🎤</span>\n Start Recording\n </button>\n <button id=\"stopBtn\" class=\"primary-btn\" disabled>\n <span class=\"stop-icon\">⬛</span>\n Stop Recording\n </button>\n </div>\n\n <div class=\"output-container\">\n <div class=\"transcription-box\">\n <h2>Transcription</h2>\n <div id=\"transcription\" class=\"text-output\" contenteditable=\"true\" role=\"textbox\" aria-label=\"Transcription output\"></div>\n </div>\n \n <div class=\"summary-box\">\n <h2>Summary</h2>\n <div id=\"summary\" class=\"text-output\" role=\"textbox\" aria-label=\"Summary output\"></div>\n </div>\n </div>\n </section>\n</main>\n\n<footer>\n <p>Built with care by SpeakSum team</p>\n <nav>\n <a href=\"/privacy\">Privacy Policy</a>\n <a href=\"/terms\">Terms of Use</a>\n <a href=\"/contact\">Contact</a>\n </nav>\n</footer>\n\n---style.css---\n:root {\n --primary-color: #6366f1;\n --bg-color: #ffffff;\n --text-color: #1f2937;\n --border-color: #e5e7eb;\n --box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\n --gradient: linear-gradient(135deg, #6366f1, #8b5cf6);\n}\n\n[data-theme=\"dark\"] {\n --bg-color: #1f2937;\n --text-color: #f3f4f6;\n --border-color: #374151;\n --box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: system-ui, -apple-system, sans-serif;\n background: var(--bg-color);\n color: var(--text-color);\n line-height: 1.6;\n transition: background-color 0.3s, color 0.3s;\n}\n\nheader {\n padding: 1rem;\n background: var(--bg-color);\n box-shadow: var(--box-shadow);\n position: sticky;\n top: 0;\n z-index: 100;\n}\n\nnav {\n max-width: 1200px;\n margin: 0 auto;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.logo {\n font-size: 1.5rem;\n font-weight: bold;\n background: var(--gradient);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n}\n\n.theme-toggle {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 1.2rem;\n}\n\nmain {\n max-width: 1200px;\n margin: 0 auto;\n padding: 2rem 1rem;\n}\n\n.hero {\n text-align: center;\n margin-bottom: 3rem;\n}\n\n.hero h1 {\n font-size: 2.5rem;\n margin-bottom: 1rem;\n background: var(--gradient);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n}\n\n.controls {\n display: flex;\n gap: 1rem;\n justify-content: center;\n margin-bottom: 2rem;\n}\n\n.primary-btn {\n padding: 0.75rem 1.5rem;\n border: none;\n border-radius: 0.5rem;\n background: var(--gradient);\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 1rem;\n transition: transform 0.2s, opacity 0.2s;\n}\n\n.primary-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.primary-btn:not(:disabled):hover {\n transform: translateY(-2px);\n}\n\n.output-container {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 2rem;\n}\n\n.text-output {\n min-height: 300px;\n padding: 1rem;\n border: 1px solid var(--border-color);\n border-radius: 0.5rem;\n background: var(--bg-color);\n margin-top: 1rem;\n}\n\nfooter {\n text-align: center;\n padding: 2rem;\n background: var(--bg-color);\n border-top: 1px solid var(--border-color);\n}\n\nfooter nav {\n display: flex;\n justify-content: center;\n gap: 2rem;\n margin-top: 1rem;\n}\n\nfooter a {\n color: var(--text-color);\n text-decoration: none;\n}\n\n@media (max-width: 768px) {\n .output-container {\n grid-template-columns: 1fr;\n }\n \n .hero h1 {\n font-size: 2rem;\n }\n}\n\n---script.js---\ndocument.addEventListener('DOMContentLoaded', () => {\n const startBtn = document.getElementById('startBtn');\n const stopBtn = document.getElementById('stopBtn');\n const transcriptionOutput = document.getElementById('transcription');\n const summaryOutput = document.getElementById('summary');\n const themeToggle = document.querySelector('.theme-toggle');\n \n let recognition = null;\n let isRecording = false;\n\n // Theme handling\n const toggleTheme = () => {\n const isDark = document.body.getAttribute('data-theme') === 'dark';\n document.body.setAttribute('data-theme', isDark ? 'light' : 'dark');\n localStorage.setItem('theme', isDark ? 'light' : 'dark');\n };\n\n themeToggle.addEventListener('click', toggleTheme);\n\n // Set initial theme\n const savedTheme = localStorage.getItem('theme') || 'light';\n document.body.setAttribute('data-theme', savedTheme);\n\n // Speech recognition setup\n if ('webkitSpeechRecognition' in window) {\n recognition = new webkitSpeechRecognition();\n recognition.continuous = true;\n recognition.interimResults = true;\n\n recognition.onresult = (event) => {\n let finalTranscript = '';\n \n for (let i = event.resultIndex; i < event.results.length; i++) {\n const transcript = event.results[i][0].transcript;\n if (event.results[i].isFinal) {\n finalTranscript += transcript;\n }\n }\n\n if (finalTranscript) {\n transcriptionOutput.textContent = finalTranscript;\n generateSummary(finalTranscript);\n }\n };\n\n recognition.onerror = (event) => {\n console.error('Speech recognition error:', event.error);\n stopRecording();\n };\n }\n\n // Recording controls\n const startRecording = () => {\n if (!recognition) {\n alert('Speech recognition is not supported in your browser.');\n return;\n }\n\n recognition.start();\n isRecording = true;\n startBtn.disabled = true;\n stopBtn.disabled = false;\n startBtn.style.opacity = '0.6';\n };\n\n const stopRecording = () => {\n if (recognition) {\n recognition.stop();\n }\n isRecording = false;\n startBtn.disabled = false;\n stopBtn.disabled = true;\n startBtn.style.opacity = '1';\n };\n\n // Simple summarization function (basic implementation)\n const generateSummary = (text) => {\n // Split into sentences\n const sentences = text.match(/[^.!?]+[.!?]+/g) || [];\n \n // Basic summary: take first 2 sentences or 20% of total sentences\n const summaryLength = Math.max(2, Math.ceil(sentences.length * 0.2));\n const summary = sentences.slice(0, summaryLength).join(' ');\n \n summaryOutput.textContent = summary || 'Not enough content for summary';\n };\n\n startBtn.addEventListener('click', startRecording);\n stopBtn.addEventListener('click', stopRecording);\n});\n\n---end---\n\nThis implementation features:\n\n1. A clean, modern UI with dark/light theme support\n2. Real-time speech-to-text conversion using the Web Speech API\n3. Basic text summarization (can be enhanced with more sophisticated algorithms)\n4. Responsive design that works on all devices\n5. Accessible controls and ARIA labels\n6. Smooth animations and transitions\n7. Professional gradient accents and modern typography\n8. Error handling and browser compatibility checks\n9. Local storage for theme preference\n10. SEO-optimized meta tags\n\nThe design is minimal yet sophisticated, with a focus on usability and visual appeal. The color scheme uses modern indigo/purple gradients that work well in both light and dark modes."
}
],
"stop_reason": "end_turn",
@@ -15,6 +15,6 @@
"input_tokens": 287,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
- "output_tokens": 1953
+ "output_tokens": 2708
}
}
\ No newline at end of file
diff --git a/script.js b/script.js
index 32e3727..659c502 100644
--- a/script.js
+++ b/script.js
@@ -1,64 +1,90 @@
document.addEventListener('DOMContentLoaded', () => {
const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
- const transcript = document.getElementById('transcript');
- const summary = document.getElementById('summary');
-
- let recognition = null;
+ const transcriptionOutput = document.getElementById('transcription');
+ const summaryOutput = document.getElementById('summary');
+ const themeToggle = document.querySelector('.theme-toggle');
+ let recognition = null;
+ let isRecording = false;
+
+ // Theme handling
+ const toggleTheme = () => {
+ const isDark = document.body.getAttribute('data-theme') === 'dark';
+ document.body.setAttribute('data-theme', isDark ? 'light' : 'dark');
+ localStorage.setItem('theme', isDark ? 'light' : 'dark');
+ };
+
+ themeToggle.addEventListener('click', toggleTheme);
+
+ // Set initial theme
+ const savedTheme = localStorage.getItem('theme') || 'light';
+ document.body.setAttribute('data-theme', savedTheme);
+
+ // Speech recognition setup
if ('webkitSpeechRecognition' in window) {
recognition = new webkitSpeechRecognition();
recognition.continuous = true;
recognition.interimResults = true;
- } else {
- startBtn.disabled = true;
- transcript.innerHTML = 'Speech recognition is not supported in this browser.';
- }
-
- function summarizeText(text) {
- // Simple summarization algorithm (example)
- const sentences = text.split(/[.!?]+/);
- const significantSentences = sentences
- .filter(sentence => sentence.length > 10)
- .slice(0, 3);
- return significantSentences.join('. ') + '.';
- }
- if (recognition) {
recognition.onresult = (event) => {
let finalTranscript = '';
for (let i = event.resultIndex; i < event.results.length; i++) {
const transcript = event.results[i][0].transcript;
if (event.results[i].isFinal) {
- finalTranscript += transcript + ' ';
+ finalTranscript += transcript;
}
}
if (finalTranscript) {
- transcript.textContent = finalTranscript;
- summary.textContent = summarizeText(finalTranscript);
+ transcriptionOutput.textContent = finalTranscript;
+ generateSummary(finalTranscript);
}
};
- startBtn.addEventListener('click', () => {
- transcript.textContent = '';
- summary.textContent = '';
- recognition.start();
- startBtn.disabled = true;
- stopBtn.disabled = false;
- });
-
- stopBtn.addEventListener('click', () => {
- recognition.stop();
- startBtn.disabled = false;
- stopBtn.disabled = true;
- });
-
recognition.onerror = (event) => {
console.error('Speech recognition error:', event.error);
- startBtn.disabled = false;
- stopBtn.disabled = true;
+ stopRecording();
};
}
+
+ // Recording controls
+ const startRecording = () => {
+ if (!recognition) {
+ alert('Speech recognition is not supported in your browser.');
+ return;
+ }
+
+ recognition.start();
+ isRecording = true;
+ startBtn.disabled = true;
+ stopBtn.disabled = false;
+ startBtn.style.opacity = '0.6';
+ };
+
+ const stopRecording = () => {
+ if (recognition) {
+ recognition.stop();
+ }
+ isRecording = false;
+ startBtn.disabled = false;
+ stopBtn.disabled = true;
+ startBtn.style.opacity = '1';
+ };
+
+ // Simple summarization function (basic implementation)
+ const generateSummary = (text) => {
+ // Split into sentences
+ const sentences = text.match(/[^.!?]+[.!?]+/g) || [];
+
+ // Basic summary: take first 2 sentences or 20% of total sentences
+ const summaryLength = Math.max(2, Math.ceil(sentences.length * 0.2));
+ const summary = sentences.slice(0, summaryLength).join(' ');
+
+ summaryOutput.textContent = summary || 'Not enough content for summary';
+ };
+
+ startBtn.addEventListener('click', startRecording);
+ stopBtn.addEventListener('click', stopRecording);
});
diff --git a/style.css b/style.css
index 21954ec..7210b4e 100644
--- a/style.css
+++ b/style.css
@@ -1,10 +1,17 @@
:root {
- --primary-color: #4a90e2;
- --secondary-color: #2c3e50;
- --accent-color: #e74c3c;
- --background: #f5f6fa;
- --text-color: #2c3e50;
- --box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+ --primary-color: #6366f1;
+ --bg-color: #ffffff;
+ --text-color: #1f2937;
+ --border-color: #e5e7eb;
+ --box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
+ --gradient: linear-gradient(135deg, #6366f1, #8b5cf6);
+}
+
+[data-theme="dark"] {
+ --bg-color: #1f2937;
+ --text-color: #f3f4f6;
+ --border-color: #374151;
+ --box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
}
* {
@@ -14,43 +21,62 @@
}
body {
- font-family: 'Segoe UI', system-ui, sans-serif;
- line-height: 1.6;
+ font-family: system-ui, -apple-system, sans-serif;
+ background: var(--bg-color);
color: var(--text-color);
- background: var(--background);
+ line-height: 1.6;
+ transition: background-color 0.3s, color 0.3s;
}
header {
- background: white;
padding: 1rem;
+ background: var(--bg-color);
box-shadow: var(--box-shadow);
+ position: sticky;
+ top: 0;
+ z-index: 100;
}
-h1 {
- font-size: 2rem;
- color: var(--secondary-color);
+nav {
+ max-width: 1200px;
+ margin: 0 auto;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.logo {
+ font-size: 1.5rem;
+ font-weight: bold;
+ background: var(--gradient);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
}
-h1 span {
- color: var(--primary-color);
+.theme-toggle {
+ background: none;
+ border: none;
+ cursor: pointer;
+ font-size: 1.2rem;
+}
+
+main {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 2rem 1rem;
}
.hero {
text-align: center;
- padding: 4rem 2rem;
- background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
- color: white;
+ margin-bottom: 3rem;
}
-.hero h2 {
+.hero h1 {
font-size: 2.5rem;
margin-bottom: 1rem;
-}
-
-.converter {
- max-width: 1200px;
- margin: 2rem auto;
- padding: 0 1rem;
+ background: var(--gradient);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
}
.controls {
@@ -60,29 +86,26 @@ h1 span {
margin-bottom: 2rem;
}
-.primary-btn, .secondary-btn {
- padding: 1rem 2rem;
+.primary-btn {
+ padding: 0.75rem 1.5rem;
border: none;
- border-radius: 50px;
+ border-radius: 0.5rem;
+ background: var(--gradient);
+ color: white;
cursor: pointer;
- font-size: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
- transition: transform 0.2s;
-}
-
-.primary-btn {
- background: var(--primary-color);
- color: white;
+ font-size: 1rem;
+ transition: transform 0.2s, opacity 0.2s;
}
-.secondary-btn {
- background: var(--secondary-color);
- color: white;
+.primary-btn:disabled {
+ opacity: 0.6;
+ cursor: not-allowed;
}
-.primary-btn:hover, .secondary-btn:hover {
+.primary-btn:not(:disabled):hover {
transform: translateY(-2px);
}
@@ -92,24 +115,32 @@ h1 span {
gap: 2rem;
}
-.output-box {
- background: white;
- border-radius: 10px;
- padding: 1rem;
+.text-output {
min-height: 300px;
- box-shadow: var(--box-shadow);
-}
-
-h3 {
- margin-bottom: 1rem;
- color: var(--secondary-color);
+ padding: 1rem;
+ border: 1px solid var(--border-color);
+ border-radius: 0.5rem;
+ background: var(--bg-color);
+ margin-top: 1rem;
}
footer {
text-align: center;
padding: 2rem;
- background: white;
- margin-top: 4rem;
+ background: var(--bg-color);
+ border-top: 1px solid var(--border-color);
+}
+
+footer nav {
+ display: flex;
+ justify-content: center;
+ gap: 2rem;
+ margin-top: 1rem;
+}
+
+footer a {
+ color: var(--text-color);
+ text-decoration: none;
}
@media (max-width: 768px) {
@@ -117,7 +148,7 @@ footer {
grid-template-columns: 1fr;
}
- .hero h2 {
+ .hero h1 {
font-size: 2rem;
}
}
commit 0e173ddf50f9dc8c4e5a27aeec73b86e5dc53af3
Author: root <root@hub.scroll.pub>
Date: 2025-01-01 10:53:01 +0000
Subject: Initial commit
diff --git a/body.html b/body.html
new file mode 100644
index 0000000..a3d0bf6
--- /dev/null
+++ b/body.html
@@ -0,0 +1,41 @@
+<header>
+ <nav>
+ <h1>Speak<span>Sum</span></h1>
+ </nav>
+</header>
+
+<main>
+ <section class="hero">
+ <h2>Convert Speech to Text and Get Instant Summaries</h2>
+ <p>Speak naturally and get both transcription and smart summaries in seconds</p>
+ </section>
+
+ <section class="converter">
+ <div class="controls">
+ <button id="startBtn" class="primary-btn">
+ <span class="icon">🎤</span>
+ Start Speaking
+ </button>
+ <button id="stopBtn" class="secondary-btn" disabled>
+ <span class="icon">⏹️</span>
+ Stop
+ </button>
+ </div>
+
+ <div class="output-container">
+ <div class="transcript-box">
+ <h3>Transcript</h3>
+ <div id="transcript" contenteditable="true" class="output-box"></div>
+ </div>
+
+ <div class="summary-box">
+ <h3>Summary</h3>
+ <div id="summary" class="output-box"></div>
+ </div>
+ </div>
+ </section>
+</main>
+
+<footer>
+ <p>Made with care by SpeakSum</p>
+</footer>
diff --git a/index.scroll b/index.scroll
new file mode 100644
index 0000000..b421912
--- /dev/null
+++ b/index.scroll
@@ -0,0 +1,8 @@
+buildHtml
+baseUrl https://speaksum.scroll.pub
+metaTags
+editButton /edit.html
+title SpeakSum - Speech to Text & Summary
+style.css
+body.html
+script.js
diff --git a/prompt.json b/prompt.json
new file mode 100644
index 0000000..8fd2020
--- /dev/null
+++ b/prompt.json
@@ -0,0 +1,20 @@
+{
+ "id": "msg_01BQzZ9qbe816kSHp4bKrvjE",
+ "type": "message",
+ "role": "assistant",
+ "model": "claude-3-5-sonnet-20241022",
+ "content": [
+ {
+ "type": "text",
+ "text": "Here's a complete website design for a speech-to-text conversion and summarization tool:\n\n---domain---\nspeaksum.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://speaksum.scroll.pub\nmetaTags\neditButton /edit.html\ntitle SpeakSum - Speech to Text & Summary\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n<header>\n <nav>\n <h1>Speak<span>Sum</span></h1>\n </nav>\n</header>\n\n<main>\n <section class=\"hero\">\n <h2>Convert Speech to Text and Get Instant Summaries</h2>\n <p>Speak naturally and get both transcription and smart summaries in seconds</p>\n </section>\n\n <section class=\"converter\">\n <div class=\"controls\">\n <button id=\"startBtn\" class=\"primary-btn\">\n <span class=\"icon\">🎤</span>\n Start Speaking\n </button>\n <button id=\"stopBtn\" class=\"secondary-btn\" disabled>\n <span class=\"icon\">⏹️</span>\n Stop\n </button>\n </div>\n\n <div class=\"output-container\">\n <div class=\"transcript-box\">\n <h3>Transcript</h3>\n <div id=\"transcript\" contenteditable=\"true\" class=\"output-box\"></div>\n </div>\n \n <div class=\"summary-box\">\n <h3>Summary</h3>\n <div id=\"summary\" class=\"output-box\"></div>\n </div>\n </div>\n </section>\n</main>\n\n<footer>\n <p>Made with care by SpeakSum</p>\n</footer>\n\n---style.css---\n:root {\n --primary-color: #4a90e2;\n --secondary-color: #2c3e50;\n --accent-color: #e74c3c;\n --background: #f5f6fa;\n --text-color: #2c3e50;\n --box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: 'Segoe UI', system-ui, sans-serif;\n line-height: 1.6;\n color: var(--text-color);\n background: var(--background);\n}\n\nheader {\n background: white;\n padding: 1rem;\n box-shadow: var(--box-shadow);\n}\n\nh1 {\n font-size: 2rem;\n color: var(--secondary-color);\n}\n\nh1 span {\n color: var(--primary-color);\n}\n\n.hero {\n text-align: center;\n padding: 4rem 2rem;\n background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));\n color: white;\n}\n\n.hero h2 {\n font-size: 2.5rem;\n margin-bottom: 1rem;\n}\n\n.converter {\n max-width: 1200px;\n margin: 2rem auto;\n padding: 0 1rem;\n}\n\n.controls {\n display: flex;\n gap: 1rem;\n justify-content: center;\n margin-bottom: 2rem;\n}\n\n.primary-btn, .secondary-btn {\n padding: 1rem 2rem;\n border: none;\n border-radius: 50px;\n cursor: pointer;\n font-size: 1rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n transition: transform 0.2s;\n}\n\n.primary-btn {\n background: var(--primary-color);\n color: white;\n}\n\n.secondary-btn {\n background: var(--secondary-color);\n color: white;\n}\n\n.primary-btn:hover, .secondary-btn:hover {\n transform: translateY(-2px);\n}\n\n.output-container {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 2rem;\n}\n\n.output-box {\n background: white;\n border-radius: 10px;\n padding: 1rem;\n min-height: 300px;\n box-shadow: var(--box-shadow);\n}\n\nh3 {\n margin-bottom: 1rem;\n color: var(--secondary-color);\n}\n\nfooter {\n text-align: center;\n padding: 2rem;\n background: white;\n margin-top: 4rem;\n}\n\n@media (max-width: 768px) {\n .output-container {\n grid-template-columns: 1fr;\n }\n \n .hero h2 {\n font-size: 2rem;\n }\n}\n\n---script.js---\ndocument.addEventListener('DOMContentLoaded', () => {\n const startBtn = document.getElementById('startBtn');\n const stopBtn = document.getElementById('stopBtn');\n const transcript = document.getElementById('transcript');\n const summary = document.getElementById('summary');\n\n let recognition = null;\n \n if ('webkitSpeechRecognition' in window) {\n recognition = new webkitSpeechRecognition();\n recognition.continuous = true;\n recognition.interimResults = true;\n } else {\n startBtn.disabled = true;\n transcript.innerHTML = 'Speech recognition is not supported in this browser.';\n }\n\n function summarizeText(text) {\n // Simple summarization algorithm (example)\n const sentences = text.split(/[.!?]+/);\n const significantSentences = sentences\n .filter(sentence => sentence.length > 10)\n .slice(0, 3);\n return significantSentences.join('. ') + '.';\n }\n\n if (recognition) {\n recognition.onresult = (event) => {\n let finalTranscript = '';\n \n for (let i = event.resultIndex; i < event.results.length; i++) {\n const transcript = event.results[i][0].transcript;\n if (event.results[i].isFinal) {\n finalTranscript += transcript + ' ';\n }\n }\n\n if (finalTranscript) {\n transcript.textContent = finalTranscript;\n summary.textContent = summarizeText(finalTranscript);\n }\n };\n\n startBtn.addEventListener('click', () => {\n transcript.textContent = '';\n summary.textContent = '';\n recognition.start();\n startBtn.disabled = true;\n stopBtn.disabled = false;\n });\n\n stopBtn.addEventListener('click', () => {\n recognition.stop();\n startBtn.disabled = false;\n stopBtn.disabled = true;\n });\n\n recognition.onerror = (event) => {\n console.error('Speech recognition error:', event.error);\n startBtn.disabled = false;\n stopBtn.disabled = true;\n };\n }\n});\n\n---end---\n\nThis implementation features:\n\n1. Clean, semantic HTML5 structure\n2. Beautiful gradient-based design with smooth animations\n3. Responsive layout that works well on mobile devices\n4. Real-time speech recognition using the Web Speech API\n5. Basic text summarization functionality\n6. Accessible controls and ARIA-compliant markup\n7. Modern CSS with variables and flexible layouts\n8. Error handling and browser compatibility checks\n9. Smooth transitions and hover effects\n10. Professional typography and spacing\n\nThe site uses a two-column layout for desktop that gracefully collapses to a single column on mobile devices. The color scheme is professional and modern, with careful attention to contrast and readability."
+ }
+ ],
+ "stop_reason": "end_turn",
+ "stop_sequence": null,
+ "usage": {
+ "input_tokens": 287,
+ "cache_creation_input_tokens": 0,
+ "cache_read_input_tokens": 0,
+ "output_tokens": 1953
+ }
+}
\ No newline at end of file
diff --git a/readme.scroll b/readme.scroll
new file mode 100644
index 0000000..1af7c16
--- /dev/null
+++ b/readme.scroll
@@ -0,0 +1,2 @@
+# speaksum1.scroll.pub
+Website generated by Claude from prompt: I want to create a website for converting speech to text and summarizing the speech content
\ No newline at end of file
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..32e3727
--- /dev/null
+++ b/script.js
@@ -0,0 +1,64 @@
+document.addEventListener('DOMContentLoaded', () => {
+ const startBtn = document.getElementById('startBtn');
+ const stopBtn = document.getElementById('stopBtn');
+ const transcript = document.getElementById('transcript');
+ const summary = document.getElementById('summary');
+
+ let recognition = null;
+
+ if ('webkitSpeechRecognition' in window) {
+ recognition = new webkitSpeechRecognition();
+ recognition.continuous = true;
+ recognition.interimResults = true;
+ } else {
+ startBtn.disabled = true;
+ transcript.innerHTML = 'Speech recognition is not supported in this browser.';
+ }
+
+ function summarizeText(text) {
+ // Simple summarization algorithm (example)
+ const sentences = text.split(/[.!?]+/);
+ const significantSentences = sentences
+ .filter(sentence => sentence.length > 10)
+ .slice(0, 3);
+ return significantSentences.join('. ') + '.';
+ }
+
+ if (recognition) {
+ recognition.onresult = (event) => {
+ let finalTranscript = '';
+
+ for (let i = event.resultIndex; i < event.results.length; i++) {
+ const transcript = event.results[i][0].transcript;
+ if (event.results[i].isFinal) {
+ finalTranscript += transcript + ' ';
+ }
+ }
+
+ if (finalTranscript) {
+ transcript.textContent = finalTranscript;
+ summary.textContent = summarizeText(finalTranscript);
+ }
+ };
+
+ startBtn.addEventListener('click', () => {
+ transcript.textContent = '';
+ summary.textContent = '';
+ recognition.start();
+ startBtn.disabled = true;
+ stopBtn.disabled = false;
+ });
+
+ stopBtn.addEventListener('click', () => {
+ recognition.stop();
+ startBtn.disabled = false;
+ stopBtn.disabled = true;
+ });
+
+ recognition.onerror = (event) => {
+ console.error('Speech recognition error:', event.error);
+ startBtn.disabled = false;
+ stopBtn.disabled = true;
+ };
+ }
+});
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..21954ec
--- /dev/null
+++ b/style.css
@@ -0,0 +1,123 @@
+:root {
+ --primary-color: #4a90e2;
+ --secondary-color: #2c3e50;
+ --accent-color: #e74c3c;
+ --background: #f5f6fa;
+ --text-color: #2c3e50;
+ --box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: 'Segoe UI', system-ui, sans-serif;
+ line-height: 1.6;
+ color: var(--text-color);
+ background: var(--background);
+}
+
+header {
+ background: white;
+ padding: 1rem;
+ box-shadow: var(--box-shadow);
+}
+
+h1 {
+ font-size: 2rem;
+ color: var(--secondary-color);
+}
+
+h1 span {
+ color: var(--primary-color);
+}
+
+.hero {
+ text-align: center;
+ padding: 4rem 2rem;
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
+ color: white;
+}
+
+.hero h2 {
+ font-size: 2.5rem;
+ margin-bottom: 1rem;
+}
+
+.converter {
+ max-width: 1200px;
+ margin: 2rem auto;
+ padding: 0 1rem;
+}
+
+.controls {
+ display: flex;
+ gap: 1rem;
+ justify-content: center;
+ margin-bottom: 2rem;
+}
+
+.primary-btn, .secondary-btn {
+ padding: 1rem 2rem;
+ border: none;
+ border-radius: 50px;
+ cursor: pointer;
+ font-size: 1rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ transition: transform 0.2s;
+}
+
+.primary-btn {
+ background: var(--primary-color);
+ color: white;
+}
+
+.secondary-btn {
+ background: var(--secondary-color);
+ color: white;
+}
+
+.primary-btn:hover, .secondary-btn:hover {
+ transform: translateY(-2px);
+}
+
+.output-container {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 2rem;
+}
+
+.output-box {
+ background: white;
+ border-radius: 10px;
+ padding: 1rem;
+ min-height: 300px;
+ box-shadow: var(--box-shadow);
+}
+
+h3 {
+ margin-bottom: 1rem;
+ color: var(--secondary-color);
+}
+
+footer {
+ text-align: center;
+ padding: 2rem;
+ background: white;
+ margin-top: 4rem;
+}
+
+@media (max-width: 768px) {
+ .output-container {
+ grid-template-columns: 1fr;
+ }
+
+ .hero h2 {
+ font-size: 2rem;
+ }
+}