commit b01b37e7c1d8f27bd37a7d35000a0ce22e288570
Author: Breck Yunits <breck7@gmail.com>
Date: 2025-01-01 08:39:56 -0800
Subject: Initial commit
diff --git a/body.html b/body.html
new file mode 100644
index 0000000..fe8374c
--- /dev/null
+++ b/body.html
@@ -0,0 +1,38 @@
+<header>
+ <h1>WriteFlow</h1>
+ <button id="darkModeToggle" aria-label="Toggle dark mode">
+ <span class="moon">🌙</span>
+ <span class="sun">☀️</span>
+ </button>
+</header>
+
+<main>
+ <textarea id="editor" placeholder="Start writing..." aria-label="Text editor"></textarea>
+
+ <div class="stats">
+ <div class="stat">
+ <span class="label">Words</span>
+ <span id="wordCount">0</span>
+ </div>
+ <div class="stat">
+ <span class="label">Characters</span>
+ <span id="charCount">0</span>
+ </div>
+ <div class="stat">
+ <span class="label">Sentences</span>
+ <span id="sentenceCount">0</span>
+ </div>
+ <div class="stat">
+ <span class="label">WPM</span>
+ <span id="typeSpeed">0</span>
+ </div>
+ <div class="stat">
+ <span class="label">Reading Level</span>
+ <span id="readingLevel">-</span>
+ </div>
+ </div>
+</main>
+
+<footer>
+ <p>WriteFlow - Focus on your writing</p>
+</footer>
diff --git a/index.scroll b/index.scroll
new file mode 100644
index 0000000..4f140d4
--- /dev/null
+++ b/index.scroll
@@ -0,0 +1,8 @@
+buildHtml
+baseUrl https://writeflow.scroll.pub
+metaTags
+editButton /edit.html
+title WriteFlow - Distraction-free Writing with Analytics
+style.css
+body.html
+script.js
diff --git a/prompt.json b/prompt.json
new file mode 100644
index 0000000..fc8cb7e
--- /dev/null
+++ b/prompt.json
@@ -0,0 +1,20 @@
+{
+ "id": "msg_01LbFeyrdBfoMKJraVfZWrwX",
+ "type": "message",
+ "role": "assistant",
+ "model": "claude-3-5-sonnet-20241022",
+ "content": [
+ {
+ "type": "text",
+ "text": "Here's a clean, elegant writing app that meets your requirements:\n\n---domain---\nwriteflow.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://writeflow.scroll.pub\nmetaTags\neditButton /edit.html\ntitle WriteFlow - Distraction-free Writing with Analytics\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n<header>\n <h1>WriteFlow</h1>\n <button id=\"darkModeToggle\" aria-label=\"Toggle dark mode\">\n <span class=\"moon\">🌙</span>\n <span class=\"sun\">☀️</span>\n </button>\n</header>\n\n<main>\n <textarea id=\"editor\" placeholder=\"Start writing...\" aria-label=\"Text editor\"></textarea>\n \n <div class=\"stats\">\n <div class=\"stat\">\n <span class=\"label\">Words</span>\n <span id=\"wordCount\">0</span>\n </div>\n <div class=\"stat\">\n <span class=\"label\">Characters</span>\n <span id=\"charCount\">0</span>\n </div>\n <div class=\"stat\">\n <span class=\"label\">Sentences</span>\n <span id=\"sentenceCount\">0</span>\n </div>\n <div class=\"stat\">\n <span class=\"label\">WPM</span>\n <span id=\"typeSpeed\">0</span>\n </div>\n <div class=\"stat\">\n <span class=\"label\">Reading Level</span>\n <span id=\"readingLevel\">-</span>\n </div>\n </div>\n</main>\n\n<footer>\n <p>WriteFlow - Focus on your writing</p>\n</footer>\n\n---style.css---\n:root {\n --bg-light: #ffffff;\n --text-light: #2c3e50;\n --primary: #3498db;\n --stats-bg-light: #f8f9fa;\n --stats-border-light: #e9ecef;\n \n --bg-dark: #1a1a1a;\n --text-dark: #e0e0e0;\n --stats-bg-dark: #2d2d2d;\n --stats-border-dark: #404040;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n background: var(--bg-light);\n color: var(--text-light);\n transition: background-color 0.3s, color 0.3s;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n}\n\nbody.dark-mode {\n background: var(--bg-dark);\n color: var(--text-dark);\n}\n\nheader {\n padding: 1rem;\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-bottom: 1px solid var(--stats-border-light);\n}\n\n.dark-mode header {\n border-color: var(--stats-border-dark);\n}\n\nh1 {\n font-size: 1.5rem;\n font-weight: 600;\n}\n\n#darkModeToggle {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 1.2rem;\n padding: 0.5rem;\n border-radius: 50%;\n transition: background-color 0.3s;\n}\n\n#darkModeToggle:hover {\n background: rgba(0, 0, 0, 0.1);\n}\n\n.dark-mode #darkModeToggle:hover {\n background: rgba(255, 255, 255, 0.1);\n}\n\n.sun { display: none; }\n.dark-mode .moon { display: none; }\n.dark-mode .sun { display: inline; }\n\nmain {\n flex: 1;\n padding: 1rem;\n max-width: 900px;\n margin: 0 auto;\n width: 100%;\n}\n\n#editor {\n width: 100%;\n height: calc(100vh - 250px);\n padding: 1rem;\n font-size: 1.1rem;\n line-height: 1.6;\n border: none;\n border-radius: 8px;\n background: var(--bg-light);\n color: var(--text-light);\n resize: none;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n transition: background-color 0.3s, color 0.3s;\n}\n\n.dark-mode #editor {\n background: var(--bg-dark);\n color: var(--text-dark);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n}\n\n#editor:focus {\n outline: 2px solid var(--primary);\n}\n\n.stats {\n display: flex;\n gap: 1rem;\n flex-wrap: wrap;\n margin-top: 1rem;\n padding: 1rem;\n background: var(--stats-bg-light);\n border-radius: 8px;\n border: 1px solid var(--stats-border-light);\n}\n\n.dark-mode .stats {\n background: var(--stats-bg-dark);\n border-color: var(--stats-border-dark);\n}\n\n.stat {\n display: flex;\n flex-direction: column;\n align-items: center;\n min-width: 80px;\n}\n\n.label {\n font-size: 0.8rem;\n opacity: 0.7;\n}\n\nfooter {\n text-align: center;\n padding: 1rem;\n font-size: 0.9rem;\n opacity: 0.7;\n}\n\n@media (max-width: 600px) {\n .stats {\n gap: 0.5rem;\n }\n \n .stat {\n min-width: 70px;\n }\n \n #editor {\n height: calc(100vh - 300px);\n }\n}\n\n---script.js---\ndocument.addEventListener('DOMContentLoaded', () => {\n const editor = document.getElementById('editor');\n const darkModeToggle = document.getElementById('darkModeToggle');\n \n // Load saved content\n editor.value = localStorage.getItem('writeflow-content') || '';\n \n // Load dark mode preference\n if (localStorage.getItem('writeflow-dark-mode') === 'true') {\n document.body.classList.add('dark-mode');\n }\n \n let lastKeyPress = Date.now();\n let wordCount = 0;\n let charCount = 0;\n let typeSpeed = 0;\n let words = [];\n \n function updateStats() {\n const text = editor.value;\n \n // Word count\n words = text.trim().split(/\\s+/).filter(word => word.length > 0);\n wordCount = words.length;\n document.getElementById('wordCount').textContent = wordCount;\n \n // Character count\n charCount = text.length;\n document.getElementById('charCount').textContent = charCount;\n \n // Sentence count\n const sentences = text.split(/[.!?]+/).filter(sentence => sentence.trim().length > 0);\n document.getElementById('sentenceCount').textContent = sentences.length;\n \n // Reading level (simplified Flesch-Kincaid)\n if (words.length > 0 && sentences.length > 0) {\n const avgWordsPerSentence = words.length / sentences.length;\n const avgSyllablesPerWord = words.reduce((sum, word) => {\n return sum + countSyllables(word);\n }, 0) / words.length;\n \n const readingLevel = Math.max(1, Math.min(12,\n Math.round(0.39 * avgWordsPerSentence + 11.8 * avgSyllablesPerWord - 15.59)\n ));\n document.getElementById('readingLevel').textContent = `Grade ${readingLevel}`;\n }\n \n // Save content\n localStorage.setItem('writeflow-content', text);\n }\n \n function updateTypeSpeed() {\n const now = Date.now();\n const timeDiff = (now - lastKeyPress) / 1000; // seconds\n if (timeDiff < 5) { // Only update if actively typing\n typeSpeed = Math.round((wordCount / timeDiff) * 60);\n document.getElementById('typeSpeed').textContent = Math.min(typeSpeed, 999);\n }\n }\n \n function countSyllables(word) {\n word = word.toLowerCase();\n if (word.length <= 3) return 1;\n return word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '')\n .match(/[aeiouy]{1,2}/g)?.length || 1;\n }\n \n editor.addEventListener('input', () => {\n updateStats();\n lastKeyPress = Date.now();\n });\n \n setInterval(updateTypeSpeed, 1000);\n \n darkModeToggle.addEventListener('click', () => {\n document.body.classList.toggle('dark-mode');\n localStorage.setItem('writeflow-dark-mode', document.body.classList.contains('dark-mode'));\n });\n \n // Initial stats update\n updateStats();\n});\n\n---end---\n\nThis implementation provides a clean, modern writing environment with:\n- Dark/light mode toggle with persistence\n- Auto-saving to localStorage\n- Real-time statistics (words, characters, sentences)\n- Type speed calculation (WPM)\n- Reading level estimation\n- Fully responsive design\n- Smooth transitions and animations\n- Accessible controls and semantic HTML\n- Clean, professional aesthetics\n- No external dependencies\n\nThe domain name \"writeflow\" suggests both writing and the smooth, flowing experience the app provides."
+ }
+ ],
+ "stop_reason": "end_turn",
+ "stop_sequence": null,
+ "usage": {
+ "input_tokens": 316,
+ "cache_creation_input_tokens": 0,
+ "cache_read_input_tokens": 0,
+ "output_tokens": 2580
+ }
+}
\ No newline at end of file
diff --git a/readme.scroll b/readme.scroll
new file mode 100644
index 0000000..72d0364
--- /dev/null
+++ b/readme.scroll
@@ -0,0 +1,2 @@
+# writeflow.scroll.pub
+Website generated by Claude from prompt: a website that gives me a textarea and dark mode and allows me to write. it saves writing to local storage. it shows me letter count and word count and type speed. and sentence count. and some type of reading level perhaps.
\ No newline at end of file
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..ff0009e
--- /dev/null
+++ b/script.js
@@ -0,0 +1,82 @@
+document.addEventListener('DOMContentLoaded', () => {
+ const editor = document.getElementById('editor');
+ const darkModeToggle = document.getElementById('darkModeToggle');
+
+ // Load saved content
+ editor.value = localStorage.getItem('writeflow-content') || '';
+
+ // Load dark mode preference
+ if (localStorage.getItem('writeflow-dark-mode') === 'true') {
+ document.body.classList.add('dark-mode');
+ }
+
+ let lastKeyPress = Date.now();
+ let wordCount = 0;
+ let charCount = 0;
+ let typeSpeed = 0;
+ let words = [];
+
+ function updateStats() {
+ const text = editor.value;
+
+ // Word count
+ words = text.trim().split(/\s+/).filter(word => word.length > 0);
+ wordCount = words.length;
+ document.getElementById('wordCount').textContent = wordCount;
+
+ // Character count
+ charCount = text.length;
+ document.getElementById('charCount').textContent = charCount;
+
+ // Sentence count
+ const sentences = text.split(/[.!?]+/).filter(sentence => sentence.trim().length > 0);
+ document.getElementById('sentenceCount').textContent = sentences.length;
+
+ // Reading level (simplified Flesch-Kincaid)
+ if (words.length > 0 && sentences.length > 0) {
+ const avgWordsPerSentence = words.length / sentences.length;
+ const avgSyllablesPerWord = words.reduce((sum, word) => {
+ return sum + countSyllables(word);
+ }, 0) / words.length;
+
+ const readingLevel = Math.max(1, Math.min(12,
+ Math.round(0.39 * avgWordsPerSentence + 11.8 * avgSyllablesPerWord - 15.59)
+ ));
+ document.getElementById('readingLevel').textContent = `Grade ${readingLevel}`;
+ }
+
+ // Save content
+ localStorage.setItem('writeflow-content', text);
+ }
+
+ function updateTypeSpeed() {
+ const now = Date.now();
+ const timeDiff = (now - lastKeyPress) / 1000; // seconds
+ if (timeDiff < 5) { // Only update if actively typing
+ typeSpeed = Math.round((wordCount / timeDiff) * 60);
+ document.getElementById('typeSpeed').textContent = Math.min(typeSpeed, 999);
+ }
+ }
+
+ function countSyllables(word) {
+ word = word.toLowerCase();
+ if (word.length <= 3) return 1;
+ return word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '')
+ .match(/[aeiouy]{1,2}/g)?.length || 1;
+ }
+
+ editor.addEventListener('input', () => {
+ updateStats();
+ lastKeyPress = Date.now();
+ });
+
+ setInterval(updateTypeSpeed, 1000);
+
+ darkModeToggle.addEventListener('click', () => {
+ document.body.classList.toggle('dark-mode');
+ localStorage.setItem('writeflow-dark-mode', document.body.classList.contains('dark-mode'));
+ });
+
+ // Initial stats update
+ updateStats();
+});
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..ff34d04
--- /dev/null
+++ b/style.css
@@ -0,0 +1,154 @@
+:root {
+ --bg-light: #ffffff;
+ --text-light: #2c3e50;
+ --primary: #3498db;
+ --stats-bg-light: #f8f9fa;
+ --stats-border-light: #e9ecef;
+
+ --bg-dark: #1a1a1a;
+ --text-dark: #e0e0e0;
+ --stats-bg-dark: #2d2d2d;
+ --stats-border-dark: #404040;
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
+ background: var(--bg-light);
+ color: var(--text-light);
+ transition: background-color 0.3s, color 0.3s;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+}
+
+body.dark-mode {
+ background: var(--bg-dark);
+ color: var(--text-dark);
+}
+
+header {
+ padding: 1rem;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 1px solid var(--stats-border-light);
+}
+
+.dark-mode header {
+ border-color: var(--stats-border-dark);
+}
+
+h1 {
+ font-size: 1.5rem;
+ font-weight: 600;
+}
+
+#darkModeToggle {
+ background: none;
+ border: none;
+ cursor: pointer;
+ font-size: 1.2rem;
+ padding: 0.5rem;
+ border-radius: 50%;
+ transition: background-color 0.3s;
+}
+
+#darkModeToggle:hover {
+ background: rgba(0, 0, 0, 0.1);
+}
+
+.dark-mode #darkModeToggle:hover {
+ background: rgba(255, 255, 255, 0.1);
+}
+
+.sun { display: none; }
+.dark-mode .moon { display: none; }
+.dark-mode .sun { display: inline; }
+
+main {
+ flex: 1;
+ padding: 1rem;
+ max-width: 900px;
+ margin: 0 auto;
+ width: 100%;
+}
+
+#editor {
+ width: 100%;
+ height: calc(100vh - 250px);
+ padding: 1rem;
+ font-size: 1.1rem;
+ line-height: 1.6;
+ border: none;
+ border-radius: 8px;
+ background: var(--bg-light);
+ color: var(--text-light);
+ resize: none;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ transition: background-color 0.3s, color 0.3s;
+}
+
+.dark-mode #editor {
+ background: var(--bg-dark);
+ color: var(--text-dark);
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
+}
+
+#editor:focus {
+ outline: 2px solid var(--primary);
+}
+
+.stats {
+ display: flex;
+ gap: 1rem;
+ flex-wrap: wrap;
+ margin-top: 1rem;
+ padding: 1rem;
+ background: var(--stats-bg-light);
+ border-radius: 8px;
+ border: 1px solid var(--stats-border-light);
+}
+
+.dark-mode .stats {
+ background: var(--stats-bg-dark);
+ border-color: var(--stats-border-dark);
+}
+
+.stat {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ min-width: 80px;
+}
+
+.label {
+ font-size: 0.8rem;
+ opacity: 0.7;
+}
+
+footer {
+ text-align: center;
+ padding: 1rem;
+ font-size: 0.9rem;
+ opacity: 0.7;
+}
+
+@media (max-width: 600px) {
+ .stats {
+ gap: 0.5rem;
+ }
+
+ .stat {
+ min-width: 70px;
+ }
+
+ #editor {
+ height: calc(100vh - 300px);
+ }
+}