commit 8db43efd5d7ec061b24a7ccf8231736d5e3c2c29
Author: root <root@hub.scroll.pub> Date: 2025-01-01 10:54:13 +0000 Subject: Initial commit diff --git a/body.html b/body.html new file mode 100644 index 0000000..cf4502e --- /dev/null +++ b/body.html @@ -0,0 +1,49 @@ +<header> + <nav class="container"> + <h1>Speak<span>Sum</span></h1> + <div class="theme-toggle"> + <button id="themeToggle" aria-label="Toggle dark mode">🌓</button> + </div> + </nav> +</header> + +<main class="container"> + <section class="hero"> + <h2>Convert Speech to Text & 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="startRecording" class="primary-btn"> + <span class="icon">🎤</span> Start Recording + </button> + <button id="stopRecording" class="secondary-btn" disabled> + <span class="icon">⏹</span> Stop Recording + </button> + </div> + + <div class="output-container"> + <div class="output-box"> + <h3>Transcription</h3> + <div id="transcription" class="content" contenteditable="true" role="textbox" aria-label="Transcription output"></div> + </div> + + <div class="output-box"> + <h3>Summary</h3> + <div id="summary" class="content" role="textbox" aria-label="Summary output"></div> + </div> + </div> + </section> +</main> + +<footer> + <div class="container"> + <p>Made with 🎙️ by SpeakSum</p> + <nav> + <a href="/privacy">Privacy</a> + <a href="/terms">Terms</a> + <a href="/contact">Contact</a> + </nav> + </div> +</footer> diff --git a/index.scroll b/index.scroll new file mode 100644 index 0000000..9854eeb --- /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 Generator +style.css +body.html +script.js diff --git a/prompt.json b/prompt.json new file mode 100644 index 0000000..c0b3e43 --- /dev/null +++ b/prompt.json @@ -0,0 +1,20 @@ +{ + "id": "msg_01XqvHUJFKKf5ZKJRfKKUX5m", + "type": "message", + "role": "assistant", + "model": "claude-3-5-sonnet-20241022", + "content": [ + { + "type": "text", + "text": "Here's a website design for a speech-to-text converter and summarizer:\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 Generator\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n<header>\n <nav class=\"container\">\n <h1>Speak<span>Sum</span></h1>\n <div class=\"theme-toggle\">\n <button id=\"themeToggle\" aria-label=\"Toggle dark mode\">🌓</button>\n </div>\n </nav>\n</header>\n\n<main class=\"container\">\n <section class=\"hero\">\n <h2>Convert Speech to Text & 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=\"startRecording\" class=\"primary-btn\">\n <span class=\"icon\">🎤</span> Start Recording\n </button>\n <button id=\"stopRecording\" class=\"secondary-btn\" disabled>\n <span class=\"icon\">⏹</span> Stop Recording\n </button>\n </div>\n\n <div class=\"output-container\">\n <div class=\"output-box\">\n <h3>Transcription</h3>\n <div id=\"transcription\" class=\"content\" contenteditable=\"true\" role=\"textbox\" aria-label=\"Transcription output\"></div>\n </div>\n \n <div class=\"output-box\">\n <h3>Summary</h3>\n <div id=\"summary\" class=\"content\" role=\"textbox\" aria-label=\"Summary output\"></div>\n </div>\n </div>\n </section>\n</main>\n\n<footer>\n <div class=\"container\">\n <p>Made with 🎙️ by SpeakSum</p>\n <nav>\n <a href=\"/privacy\">Privacy</a>\n <a href=\"/terms\">Terms</a>\n <a href=\"/contact\">Contact</a>\n </nav>\n </div>\n</footer>\n\n---style.css---\n:root {\n --primary-color: #6366f1;\n --secondary-color: #818cf8;\n --bg-color: #ffffff;\n --text-color: #1f2937;\n --border-color: #e5e7eb;\n --container-width: 1200px;\n --border-radius: 12px;\n --transition: all 0.3s ease;\n}\n\n[data-theme=\"dark\"] {\n --bg-color: #111827;\n --text-color: #f3f4f6;\n --border-color: #374151;\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-color: var(--bg-color);\n color: var(--text-color);\n line-height: 1.6;\n transition: var(--transition);\n}\n\n.container {\n max-width: var(--container-width);\n margin: 0 auto;\n padding: 0 1.5rem;\n}\n\nheader {\n padding: 1.5rem 0;\n border-bottom: 1px solid var(--border-color);\n}\n\nheader nav {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\nh1 {\n font-size: 2rem;\n font-weight: 700;\n}\n\nh1 span {\n color: var(--primary-color);\n}\n\n.theme-toggle button {\n background: none;\n border: none;\n font-size: 1.5rem;\n cursor: pointer;\n padding: 0.5rem;\n border-radius: 50%;\n transition: var(--transition);\n}\n\n.theme-toggle button:hover {\n background-color: var(--border-color);\n}\n\n.hero {\n text-align: center;\n padding: 4rem 0;\n}\n\n.hero h2 {\n font-size: 2.5rem;\n margin-bottom: 1rem;\n background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n}\n\n.converter {\n margin: 2rem 0;\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: 0.75rem 1.5rem;\n border-radius: var(--border-radius);\n border: none;\n font-size: 1rem;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n transition: var(--transition);\n}\n\n.primary-btn {\n background-color: var(--primary-color);\n color: white;\n}\n\n.secondary-btn {\n background-color: var(--border-color);\n color: var(--text-color);\n}\n\n.primary-btn:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.2);\n}\n\n.secondary-btn:hover {\n transform: translateY(-2px);\n}\n\n.primary-btn:disabled, .secondary-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.output-container {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 2rem;\n margin-top: 2rem;\n}\n\n.output-box {\n background-color: var(--bg-color);\n border: 1px solid var(--border-color);\n border-radius: var(--border-radius);\n padding: 1.5rem;\n height: 300px;\n}\n\n.output-box h3 {\n margin-bottom: 1rem;\n color: var(--primary-color);\n}\n\n.content {\n height: calc(100% - 2rem);\n overflow-y: auto;\n padding: 1rem;\n background-color: var(--bg-color);\n border: 1px solid var(--border-color);\n border-radius: calc(var(--border-radius) - 4px);\n}\n\nfooter {\n margin-top: 4rem;\n padding: 2rem 0;\n border-top: 1px solid var(--border-color);\n}\n\nfooter .container {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\nfooter nav a {\n color: var(--text-color);\n text-decoration: none;\n margin-left: 1.5rem;\n}\n\nfooter nav a:hover {\n color: var(--primary-color);\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 .controls {\n flex-direction: column;\n }\n \n footer .container {\n flex-direction: column;\n gap: 1rem;\n text-align: center;\n }\n \n footer nav a {\n margin: 0 0.75rem;\n }\n}\n\n---script.js---\ndocument.addEventListener('DOMContentLoaded', () => {\n const startButton = document.getElementById('startRecording');\n const stopButton = document.getElementById('stopRecording');\n const transcriptionOutput = document.getElementById('transcription');\n const summaryOutput = document.getElementById('summary');\n const themeToggle = document.getElementById('themeToggle');\n\n let recognition = null;\n let isRecording = false;\n\n // Theme handling\n const toggleTheme = () => {\n const currentTheme = document.documentElement.getAttribute('data-theme');\n const newTheme = currentTheme === 'dark' ? 'light' : 'dark';\n document.documentElement.setAttribute('data-theme', newTheme);\n localStorage.setItem('theme', newTheme);\n };\n\n themeToggle.addEventListener('click', toggleTheme);\n\n // Load saved theme\n const savedTheme = localStorage.getItem('theme');\n if (savedTheme) {\n document.documentElement.setAttribute('data-theme', savedTheme);\n }\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.onstart = () => {\n isRecording = true;\n startButton.disabled = true;\n stopButton.disabled = false;\n startButton.classList.add('recording');\n };\n\n recognition.onend = () => {\n isRecording = false;\n startButton.disabled = false;\n stopButton.disabled = true;\n startButton.classList.remove('recording');\n generateSummary();\n };\n\n recognition.onresult = (event) => {\n let interimTranscript = '';\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 } else {\n interimTranscript += transcript;\n }\n }\n\n transcriptionOutput.innerHTML = finalTranscript + \n '<span class=\"interim\">' + interimTranscript + '</span>';\n };\n\n startButton.addEventListener('click', () => {\n transcriptionOutput.innerHTML = '';\n summaryOutput.innerHTML = '';\n recognition.start();\n });\n\n stopButton.addEventListener('click', () => {\n recognition.stop();\n });\n } else {\n startButton.disabled = true;\n alert('Speech recognition is not supported in your browser. Please use Chrome.');\n }\n\n // Simple summarization function (placeholder)\n function generateSummary() {\n const text = transcriptionOutput.textContent;\n if (text.length > 0) {\n // This is a very basic summary generator\n // In a real application, you'd want to use more sophisticated NLP\n const sentences = text.split(/[.!?]+/).filter(sentence => sentence.trim().length > 0);\n const summary = sentences.slice(0, 2).join('. ') + '.';\n summaryOutput.textContent = summary;\n }\n }\n});\n\n---end---\n\nThis design features:\n- Clean, modern UI with dark/light mode toggle\n- Responsive layout that works on all devices\n- Accessible controls and ARIA labels\n- Real-time speech recognition with WebKit Speech API\n- Basic text summarization (placeholder implementation)\n- Smooth animations and transitions\n- Professional gradient effects\n- Clear visual hierarchy\n- Error handling for unsupported browsers\n- Local storage for theme preference\n- Semantic HTML structure\n- Modern CSS with CSS variables\n- Mobile-first approach\n- Beautiful typography and spacing\n\nThe domain name \"speaksum\" combines \"speak\" and \"sum(mary)\" into a short, memorable name that clearly represents the site's functionality." + } + ], + "stop_reason": "end_turn", + "stop_sequence": null, + "usage": { + "input_tokens": 287, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "output_tokens": 2937 + } +} \ No newline at end of file diff --git a/readme.scroll b/readme.scroll new file mode 100644 index 0000000..1f48b67 --- /dev/null +++ b/readme.scroll @@ -0,0 +1,2 @@ +# speaksum2.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..16142a6 --- /dev/null +++ b/script.js @@ -0,0 +1,90 @@ +document.addEventListener('DOMContentLoaded', () => { + const startButton = document.getElementById('startRecording'); + const stopButton = document.getElementById('stopRecording'); + const transcriptionOutput = document.getElementById('transcription'); + const summaryOutput = document.getElementById('summary'); + const themeToggle = document.getElementById('themeToggle'); + + let recognition = null; + let isRecording = false; + + // Theme handling + const toggleTheme = () => { + const currentTheme = document.documentElement.getAttribute('data-theme'); + const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; + document.documentElement.setAttribute('data-theme', newTheme); + localStorage.setItem('theme', newTheme); + }; + + themeToggle.addEventListener('click', toggleTheme); + + // Load saved theme + const savedTheme = localStorage.getItem('theme'); + if (savedTheme) { + document.documentElement.setAttribute('data-theme', savedTheme); + } + + // Speech recognition setup + if ('webkitSpeechRecognition' in window) { + recognition = new webkitSpeechRecognition(); + recognition.continuous = true; + recognition.interimResults = true; + + recognition.onstart = () => { + isRecording = true; + startButton.disabled = true; + stopButton.disabled = false; + startButton.classList.add('recording'); + }; + + recognition.onend = () => { + isRecording = false; + startButton.disabled = false; + stopButton.disabled = true; + startButton.classList.remove('recording'); + generateSummary(); + }; + + recognition.onresult = (event) => { + let interimTranscript = ''; + 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; + } else { + interimTranscript += transcript; + } + } + + transcriptionOutput.innerHTML = finalTranscript + + '<span class="interim">' + interimTranscript + '</span>'; + }; + + startButton.addEventListener('click', () => { + transcriptionOutput.innerHTML = ''; + summaryOutput.innerHTML = ''; + recognition.start(); + }); + + stopButton.addEventListener('click', () => { + recognition.stop(); + }); + } else { + startButton.disabled = true; + alert('Speech recognition is not supported in your browser. Please use Chrome.'); + } + + // Simple summarization function (placeholder) + function generateSummary() { + const text = transcriptionOutput.textContent; + if (text.length > 0) { + // This is a very basic summary generator + // In a real application, you'd want to use more sophisticated NLP + const sentences = text.split(/[.!?]+/).filter(sentence => sentence.trim().length > 0); + const summary = sentences.slice(0, 2).join('. ') + '.'; + summaryOutput.textContent = summary; + } + } +}); diff --git a/style.css b/style.css new file mode 100644 index 0000000..5901ab6 --- /dev/null +++ b/style.css @@ -0,0 +1,205 @@ +:root { + --primary-color: #6366f1; + --secondary-color: #818cf8; + --bg-color: #ffffff; + --text-color: #1f2937; + --border-color: #e5e7eb; + --container-width: 1200px; + --border-radius: 12px; + --transition: all 0.3s ease; +} + +[data-theme="dark"] { + --bg-color: #111827; + --text-color: #f3f4f6; + --border-color: #374151; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: system-ui, -apple-system, sans-serif; + background-color: var(--bg-color); + color: var(--text-color); + line-height: 1.6; + transition: var(--transition); +} + +.container { + max-width: var(--container-width); + margin: 0 auto; + padding: 0 1.5rem; +} + +header { + padding: 1.5rem 0; + border-bottom: 1px solid var(--border-color); +} + +header nav { + display: flex; + justify-content: space-between; + align-items: center; +} + +h1 { + font-size: 2rem; + font-weight: 700; +} + +h1 span { + color: var(--primary-color); +} + +.theme-toggle button { + background: none; + border: none; + font-size: 1.5rem; + cursor: pointer; + padding: 0.5rem; + border-radius: 50%; + transition: var(--transition); +} + +.theme-toggle button:hover { + background-color: var(--border-color); +} + +.hero { + text-align: center; + padding: 4rem 0; +} + +.hero h2 { + font-size: 2.5rem; + margin-bottom: 1rem; + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.converter { + margin: 2rem 0; +} + +.controls { + display: flex; + gap: 1rem; + justify-content: center; + margin-bottom: 2rem; +} + +.primary-btn, .secondary-btn { + padding: 0.75rem 1.5rem; + border-radius: var(--border-radius); + border: none; + font-size: 1rem; + cursor: pointer; + display: flex; + align-items: center; + gap: 0.5rem; + transition: var(--transition); +} + +.primary-btn { + background-color: var(--primary-color); + color: white; +} + +.secondary-btn { + background-color: var(--border-color); + color: var(--text-color); +} + +.primary-btn:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(99, 102, 241, 0.2); +} + +.secondary-btn:hover { + transform: translateY(-2px); +} + +.primary-btn:disabled, .secondary-btn:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.output-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 2rem; + margin-top: 2rem; +} + +.output-box { + background-color: var(--bg-color); + border: 1px solid var(--border-color); + border-radius: var(--border-radius); + padding: 1.5rem; + height: 300px; +} + +.output-box h3 { + margin-bottom: 1rem; + color: var(--primary-color); +} + +.content { + height: calc(100% - 2rem); + overflow-y: auto; + padding: 1rem; + background-color: var(--bg-color); + border: 1px solid var(--border-color); + border-radius: calc(var(--border-radius) - 4px); +} + +footer { + margin-top: 4rem; + padding: 2rem 0; + border-top: 1px solid var(--border-color); +} + +footer .container { + display: flex; + justify-content: space-between; + align-items: center; +} + +footer nav a { + color: var(--text-color); + text-decoration: none; + margin-left: 1.5rem; +} + +footer nav a:hover { + color: var(--primary-color); +} + +@media (max-width: 768px) { + .output-container { + grid-template-columns: 1fr; + } + + .hero h2 { + font-size: 2rem; + } + + .controls { + flex-direction: column; + } + + footer .container { + flex-direction: column; + gap: 1rem; + text-align: center; + } + + footer nav a { + margin: 0 0.75rem; + } +}