commit 81d6dd8096c772eb272e4b2d4df5e5583492a74e
Author: root <root@hub.scroll.pub> Date: 2024-12-27 17:35:28 +0000 Subject: Initial commit diff --git a/body.html b/body.html new file mode 100644 index 0000000..9d83d38 --- /dev/null +++ b/body.html @@ -0,0 +1,38 @@ +<header> + <nav> + <div class="logo">SoundVault</div> + <button id="loginBtn" class="nav-btn">Login</button> + </nav> +</header> + +<main> + <section id="loginSection" class="card"> + <h1>Login to Access Files</h1> + <form id="loginForm"> + <input type="password" id="password" placeholder="Enter password" required> + <button type="submit">Enter Vault</button> + </form> + </section> + + <section id="uploadSection" class="card hidden"> + <h2>Upload New Audio</h2> + <form id="uploadForm"> + <div class="upload-area"> + <input type="file" id="audioFile" accept="audio/*" required> + <label for="audioFile">Choose audio file or drag here</label> + </div> + <button type="submit">Upload</button> + </form> + </section> + + <section id="audioList" class="card hidden"> + <h2>Your Audio Files</h2> + <div class="list-container"> + <!-- Audio files will be dynamically inserted here --> + </div> + </section> +</main> + +<footer> + <p>SoundVault - Secure Audio File Storage</p> +</footer> diff --git a/index.scroll b/index.scroll new file mode 100644 index 0000000..635906c --- /dev/null +++ b/index.scroll @@ -0,0 +1,8 @@ +buildHtml +baseUrl https://soundvault.scroll.pub +metaTags +editButton /edit.html +title SoundVault - Secure Audio File Hosting +style.css +body.html +script.js diff --git a/prompt.json b/prompt.json new file mode 100644 index 0000000..a10ea81 --- /dev/null +++ b/prompt.json @@ -0,0 +1,20 @@ +{ + "id": "msg_01HYZGEoSsD219zwkXqwRqND", + "type": "message", + "role": "assistant", + "model": "claude-3-5-sonnet-20241022", + "content": [ + { + "type": "text", + "text": "Let me create a secure audio file hosting website.\n\n---domain---\nsoundvault.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://soundvault.scroll.pub\nmetaTags\neditButton /edit.html\ntitle SoundVault - Secure Audio File Hosting\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n<header>\n <nav>\n <div class=\"logo\">SoundVault</div>\n <button id=\"loginBtn\" class=\"nav-btn\">Login</button>\n </nav>\n</header>\n\n<main>\n <section id=\"loginSection\" class=\"card\">\n <h1>Login to Access Files</h1>\n <form id=\"loginForm\">\n <input type=\"password\" id=\"password\" placeholder=\"Enter password\" required>\n <button type=\"submit\">Enter Vault</button>\n </form>\n </section>\n\n <section id=\"uploadSection\" class=\"card hidden\">\n <h2>Upload New Audio</h2>\n <form id=\"uploadForm\">\n <div class=\"upload-area\">\n <input type=\"file\" id=\"audioFile\" accept=\"audio/*\" required>\n <label for=\"audioFile\">Choose audio file or drag here</label>\n </div>\n <button type=\"submit\">Upload</button>\n </form>\n </section>\n\n <section id=\"audioList\" class=\"card hidden\">\n <h2>Your Audio Files</h2>\n <div class=\"list-container\">\n <!-- Audio files will be dynamically inserted here -->\n </div>\n </section>\n</main>\n\n<footer>\n <p>SoundVault - Secure Audio File Storage</p>\n</footer>\n\n---style.css---\n:root {\n --primary: #2a6cbb;\n --secondary: #1d4d8a;\n --background: #f5f7fa;\n --text: #2c3e50;\n --shadow: 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: system-ui, -apple-system, sans-serif;\n background: var(--background);\n color: var(--text);\n line-height: 1.6;\n}\n\nheader {\n background: linear-gradient(135deg, var(--primary), var(--secondary));\n padding: 1rem;\n box-shadow: 0 2px 10px var(--shadow);\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 color: white;\n}\n\n.nav-btn {\n background: transparent;\n border: 2px solid white;\n color: white;\n padding: 0.5rem 1rem;\n border-radius: 25px;\n cursor: pointer;\n transition: all 0.3s ease;\n}\n\n.nav-btn:hover {\n background: white;\n color: var(--primary);\n}\n\nmain {\n max-width: 800px;\n margin: 2rem auto;\n padding: 0 1rem;\n}\n\n.card {\n background: white;\n border-radius: 10px;\n padding: 2rem;\n margin-bottom: 2rem;\n box-shadow: 0 4px 6px var(--shadow);\n transition: transform 0.3s ease;\n}\n\n.card:hover {\n transform: translateY(-2px);\n}\n\nh1, h2 {\n color: var(--primary);\n margin-bottom: 1.5rem;\n}\n\nform {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\ninput {\n padding: 0.8rem;\n border: 2px solid #e1e1e1;\n border-radius: 5px;\n font-size: 1rem;\n}\n\nbutton {\n background: var(--primary);\n color: white;\n padding: 0.8rem;\n border: none;\n border-radius: 5px;\n font-size: 1rem;\n cursor: pointer;\n transition: background 0.3s ease;\n}\n\nbutton:hover {\n background: var(--secondary);\n}\n\n.upload-area {\n border: 2px dashed #e1e1e1;\n padding: 2rem;\n text-align: center;\n border-radius: 5px;\n position: relative;\n}\n\n.upload-area input {\n opacity: 0;\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n cursor: pointer;\n}\n\n.upload-area label {\n color: var(--text);\n pointer-events: none;\n}\n\n.list-container {\n display: grid;\n gap: 1rem;\n}\n\n.audio-item {\n display: flex;\n align-items: center;\n gap: 1rem;\n padding: 1rem;\n background: #f8f9fa;\n border-radius: 5px;\n}\n\n.hidden {\n display: none;\n}\n\nfooter {\n text-align: center;\n padding: 2rem;\n background: white;\n margin-top: 4rem;\n}\n\n@media (max-width: 600px) {\n .card {\n padding: 1.5rem;\n }\n \n .upload-area {\n padding: 1rem;\n }\n}\n\n---script.js---\ndocument.addEventListener('DOMContentLoaded', () => {\n const VAULT_PASSWORD = 'demo123'; // In production, use proper authentication\n const loginSection = document.getElementById('loginSection');\n const uploadSection = document.getElementById('uploadSection');\n const audioList = document.getElementById('audioList');\n const loginBtn = document.getElementById('loginBtn');\n \n let isLoggedIn = false;\n \n // Login handling\n document.getElementById('loginForm').addEventListener('submit', (e) => {\n e.preventDefault();\n const password = document.getElementById('password').value;\n \n if (password === VAULT_PASSWORD) {\n isLoggedIn = true;\n loginSection.classList.add('hidden');\n uploadSection.classList.remove('hidden');\n audioList.classList.remove('hidden');\n loginBtn.textContent = 'Logout';\n loadAudioFiles();\n } else {\n alert('Invalid password');\n }\n });\n \n // Login/Logout button\n loginBtn.addEventListener('click', () => {\n if (isLoggedIn) {\n isLoggedIn = false;\n loginSection.classList.remove('hidden');\n uploadSection.classList.add('hidden');\n audioList.classList.add('hidden');\n loginBtn.textContent = 'Login';\n document.getElementById('password').value = '';\n }\n });\n \n // File upload handling\n document.getElementById('uploadForm').addEventListener('submit', (e) => {\n e.preventDefault();\n const file = document.getElementById('audioFile').files[0];\n if (file) {\n uploadAudioFile(file);\n }\n });\n \n // Drag and drop handling\n const uploadArea = document.querySelector('.upload-area');\n \n uploadArea.addEventListener('dragover', (e) => {\n e.preventDefault();\n uploadArea.style.borderColor = var(--primary);\n });\n \n uploadArea.addEventListener('dragleave', () => {\n uploadArea.style.borderColor = '#e1e1e1';\n });\n \n uploadArea.addEventListener('drop', (e) => {\n e.preventDefault();\n uploadArea.style.borderColor = '#e1e1e1';\n const file = e.dataTransfer.files[0];\n if (file.type.startsWith('audio/')) {\n uploadAudioFile(file);\n } else {\n alert('Please upload audio files only');\n }\n });\n \n function uploadAudioFile(file) {\n // In production, implement actual file upload to server\n const audioFiles = JSON.parse(localStorage.getItem('audioFiles') || '[]');\n audioFiles.push({\n name: file.name,\n date: new Date().toISOString(),\n size: file.size\n });\n localStorage.setItem('audioFiles', JSON.stringify(audioFiles));\n loadAudioFiles();\n }\n \n function loadAudioFiles() {\n const container = document.querySelector('.list-container');\n container.innerHTML = '';\n \n const audioFiles = JSON.parse(localStorage.getItem('audioFiles') || '[]');\n audioFiles.sort((a, b) => new Date(b.date) - new Date(a.date));\n \n audioFiles.forEach(file => {\n const item = document.createElement('div');\n item.className = 'audio-item';\n item.innerHTML = `\n <span>${file.name}</span>\n <span>${new Date(file.date).toLocaleDateString()}</span>\n <span>${formatFileSize(file.size)}</span>\n `;\n container.appendChild(item);\n });\n }\n \n function formatFileSize(bytes) {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n }\n});\n\n---end---\n\nThis implementation provides:\n1. Password protection\n2. Clean, modern UI with smooth animations\n3. Drag-and-drop file upload\n4. Responsive design\n5. File listing sorted by date\n6. File size formatting\n7. Accessibility features\n8. Semantic HTML structure\n9. Modern CSS with variables and gradients\n10. Local storage for demo purposes (in production, implement proper backend storage)\n\nNote: This is a frontend-only implementation. In a production environment, you would need to:\n- Implement proper authentication\n- Add server-side storage and file handling\n- Add proper security measures\n- Implement file streaming/playback\n- Add proper error handling\n- Add loading states\n- Implement proper file validation\n\nThe design is modern and professional while maintaining simplicity and usability." + } + ], + "stop_reason": "end_turn", + "stop_sequence": null, + "usage": { + "input_tokens": 307, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "output_tokens": 2672 + } +} \ No newline at end of file diff --git a/readme.scroll b/readme.scroll new file mode 100644 index 0000000..ced0047 --- /dev/null +++ b/readme.scroll @@ -0,0 +1,2 @@ +# soundvault.scroll.pub +Website generated by Claude from prompt: I would like a website to post audio files and protected with secured password. The user should be able to upload an audio file and the website would list the available audiofiles listed by date \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..36b8aae --- /dev/null +++ b/script.js @@ -0,0 +1,109 @@ +document.addEventListener('DOMContentLoaded', () => { + const VAULT_PASSWORD = 'demo123'; // In production, use proper authentication + const loginSection = document.getElementById('loginSection'); + const uploadSection = document.getElementById('uploadSection'); + const audioList = document.getElementById('audioList'); + const loginBtn = document.getElementById('loginBtn'); + + let isLoggedIn = false; + + // Login handling + document.getElementById('loginForm').addEventListener('submit', (e) => { + e.preventDefault(); + const password = document.getElementById('password').value; + + if (password === VAULT_PASSWORD) { + isLoggedIn = true; + loginSection.classList.add('hidden'); + uploadSection.classList.remove('hidden'); + audioList.classList.remove('hidden'); + loginBtn.textContent = 'Logout'; + loadAudioFiles(); + } else { + alert('Invalid password'); + } + }); + + // Login/Logout button + loginBtn.addEventListener('click', () => { + if (isLoggedIn) { + isLoggedIn = false; + loginSection.classList.remove('hidden'); + uploadSection.classList.add('hidden'); + audioList.classList.add('hidden'); + loginBtn.textContent = 'Login'; + document.getElementById('password').value = ''; + } + }); + + // File upload handling + document.getElementById('uploadForm').addEventListener('submit', (e) => { + e.preventDefault(); + const file = document.getElementById('audioFile').files[0]; + if (file) { + uploadAudioFile(file); + } + }); + + // Drag and drop handling + const uploadArea = document.querySelector('.upload-area'); + + uploadArea.addEventListener('dragover', (e) => { + e.preventDefault(); + uploadArea.style.borderColor = var(--primary); + }); + + uploadArea.addEventListener('dragleave', () => { + uploadArea.style.borderColor = '#e1e1e1'; + }); + + uploadArea.addEventListener('drop', (e) => { + e.preventDefault(); + uploadArea.style.borderColor = '#e1e1e1'; + const file = e.dataTransfer.files[0]; + if (file.type.startsWith('audio/')) { + uploadAudioFile(file); + } else { + alert('Please upload audio files only'); + } + }); + + function uploadAudioFile(file) { + // In production, implement actual file upload to server + const audioFiles = JSON.parse(localStorage.getItem('audioFiles') || '[]'); + audioFiles.push({ + name: file.name, + date: new Date().toISOString(), + size: file.size + }); + localStorage.setItem('audioFiles', JSON.stringify(audioFiles)); + loadAudioFiles(); + } + + function loadAudioFiles() { + const container = document.querySelector('.list-container'); + container.innerHTML = ''; + + const audioFiles = JSON.parse(localStorage.getItem('audioFiles') || '[]'); + audioFiles.sort((a, b) => new Date(b.date) - new Date(a.date)); + + audioFiles.forEach(file => { + const item = document.createElement('div'); + item.className = 'audio-item'; + item.innerHTML = ` + <span>${file.name}</span> + <span>${new Date(file.date).toLocaleDateString()}</span> + <span>${formatFileSize(file.size)}</span> + `; + container.appendChild(item); + }); + } + + function formatFileSize(bytes) { + if (bytes === 0) return '0 Bytes'; + const k = 1024; + const sizes = ['Bytes', 'KB', 'MB', 'GB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + } +}); diff --git a/style.css b/style.css new file mode 100644 index 0000000..e2c55ac --- /dev/null +++ b/style.css @@ -0,0 +1,165 @@ +:root { + --primary: #2a6cbb; + --secondary: #1d4d8a; + --background: #f5f7fa; + --text: #2c3e50; + --shadow: rgba(0, 0, 0, 0.1); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: system-ui, -apple-system, sans-serif; + background: var(--background); + color: var(--text); + line-height: 1.6; +} + +header { + background: linear-gradient(135deg, var(--primary), var(--secondary)); + padding: 1rem; + box-shadow: 0 2px 10px var(--shadow); +} + +nav { + max-width: 1200px; + margin: 0 auto; + display: flex; + justify-content: space-between; + align-items: center; +} + +.logo { + font-size: 1.5rem; + font-weight: bold; + color: white; +} + +.nav-btn { + background: transparent; + border: 2px solid white; + color: white; + padding: 0.5rem 1rem; + border-radius: 25px; + cursor: pointer; + transition: all 0.3s ease; +} + +.nav-btn:hover { + background: white; + color: var(--primary); +} + +main { + max-width: 800px; + margin: 2rem auto; + padding: 0 1rem; +} + +.card { + background: white; + border-radius: 10px; + padding: 2rem; + margin-bottom: 2rem; + box-shadow: 0 4px 6px var(--shadow); + transition: transform 0.3s ease; +} + +.card:hover { + transform: translateY(-2px); +} + +h1, h2 { + color: var(--primary); + margin-bottom: 1.5rem; +} + +form { + display: flex; + flex-direction: column; + gap: 1rem; +} + +input { + padding: 0.8rem; + border: 2px solid #e1e1e1; + border-radius: 5px; + font-size: 1rem; +} + +button { + background: var(--primary); + color: white; + padding: 0.8rem; + border: none; + border-radius: 5px; + font-size: 1rem; + cursor: pointer; + transition: background 0.3s ease; +} + +button:hover { + background: var(--secondary); +} + +.upload-area { + border: 2px dashed #e1e1e1; + padding: 2rem; + text-align: center; + border-radius: 5px; + position: relative; +} + +.upload-area input { + opacity: 0; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + cursor: pointer; +} + +.upload-area label { + color: var(--text); + pointer-events: none; +} + +.list-container { + display: grid; + gap: 1rem; +} + +.audio-item { + display: flex; + align-items: center; + gap: 1rem; + padding: 1rem; + background: #f8f9fa; + border-radius: 5px; +} + +.hidden { + display: none; +} + +footer { + text-align: center; + padding: 2rem; + background: white; + margin-top: 4rem; +} + +@media (max-width: 600px) { + .card { + padding: 1.5rem; + } + + .upload-area { + padding: 1rem; + } +}