1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta name="description" content="A lightweight AI assistant to provide help directly alongside your CMS. Made by David Bauer and Claude for Republik."> 7 8 <!-- Open Graph / Facebook --> 9 <meta property="og:type" content="website"> 10 <meta property="og:title" content="Sidekick â Lightweight AI Assistant (Bookmarklet)"> 11 <meta property="og:description" content="A lightweight AI assistant to provide help directly alongside your CMS. Made by David Bauer and Claude for Republik."> 12 <meta property="og:image" content="https://labs.davidbauer.ch/apps/sidekick/social.png"> 13 14 15 <title>Sidekick â Lightweight AI Assistant for Writers (Bookmarklet)</title> 16 <link rel="icon" type="image/x-icon" href="favicon.ico"> 17 18 <!-- Plausible Analytics --> 19
19<script defer data-domain="davidbauer.ch" src="https://plausible.io/js/plausible.js"></script>
19 20 21 <link rel="preconnect" href="https://fonts.googleapis.com"> 22 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 23 <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet"> 24 <link rel="stylesheet" href="styles.css" id="main-stylesheet"> 25 26 <!-- Initialization in init.js --> 27</head> 28<body> 29 <!-- Landing Page --> 30 <div class="landing-page"> 31 <!-- Landing Header --> 32 <div class="landing-header"> 33 <h1>Sidekick</h1> 34 <p>A lightweight AI assistant for writers that provides help directly alongside your CMS. Made by <a href="https://davidbauer.ch">David Bauer</a> and <a href="https://claude.ai">Claude</a> for <a href="https://www.republik.ch">Republik</a>.</p> 35 </div> 36 37 <!-- Bookmarklet Section --> 38 <div id="bookmarklet-section"> 39 <h2>ð Install bookmarklet</h2> 40 <div class="bookmarklet-content"> 41 <p style="font-size: 13px; color: #666; margin-bottom: 12px;"> 42 Diesen Button in die Bookmarks-Leiste des Browsers ziehen. Dann im Artikeleditor eines unterstützten CMS (Publikator oder Sanity Studio) per Klick aktivieren und nutzen. Keine Inhalte werden für das Training von KI-Modellen genutzt. Bei Fragen: David fragen. 43 </p> 44 <p> 45 <a id="bookmarklet-link" href="#" class="bookmarklet-btn" onclick="return false;"> 46 ðª Sidekick 47 </a> 48 </p> 49 </div> 50 <div class="bookmarklet-overlay" id="bookmarklet-overlay"> 51 <p>â ï¸ Bookmarklet installation is only available for Republik's CMS.</p> 52 </div> 53 </div> 54 55 <!-- Testing Section --> 56 <div class="testing-section"> 57 <br><br> 58 <h2>See how it works</h2> 59 <p>You can test the bookmarklet's features directly on this page (see that nice blue button in the corner?).</p> 60 61 <div class="config-section"> 62 <h2>âï¸ Configuration</h2> 63 <label for="api-key-input">Anthropic API Key</label> 64 <input type="password" id="api-key-input" placeholder="sk-ant-..."> 65 <p class="annotation"> 66 Get your API key from: <a href="https://console.anthropic.com">console.anthropic.com</a>. Your key stays private: It is stored only in your browser's localStorage (so you don't have to enter it again and again) and is sent directly to Anthropic's API. Per <a href="https://privacy.claude.com/en/articles/7996866-how-long-do-you-store-my-organization-s-data">Anthropic's commercial data policy</a>, API inputs and outputs are not used to train their models and are automatically deleted within 30 days. 67 </p> 68 </div> 69 70 <!-- MOCK CMS CONTENT --> 71 <div class="mock-cms"> 72 <h2>ð Content to test with</h2> 73 74 <div class="form-field"> 75 <label for="mock-title">Title</label> 76 <input type="text" id="mock-title" name="title" placeholder=""> 77 </div> 78 79 <div class="form-field"> 80 <label for="mock-lede">Lead / Short Title</label> 81 <input type="text" id="mock-lede" name="shortTitle" placeholder=""> 82 </div> 83 84 <div class="form-field"> 85 <label for="mock-body">Article text</label> 86 <textarea id="mock-body" name="body" placeholder=""></textarea> 87 </div> 88 89 <div class="form-field"> 90 <h2>Example image</h2> 91 <label for="upload-image-1" style="display: block; font-size: 12px; color: #666; margin-bottom: 8px; cursor: pointer;"> 92 ð¤ Upload your own image 93 </label> 94 <input type="file" id="upload-image-1" accept="image/*" style="margin-bottom: 8px; font-size: 13px; font-family: 'JetBrains Mono', monospace;"> 95 <img id="example-image-1" src="example-image.png" alt="" style="max-width: 100%; height: auto; border: 1px solid #ddd; border-radius: 4px; margin-top: 8px;"> 96 <p style="font-size: 12px; color: #999; margin-top: 4px;"> 97 This image has no ALT text and can be tested for ALT text generation. 98 </p> 99 </div> 100 101 <div class="form-field"> 102 <h2>Example chart</h2> 103 <label for="upload-image-2" style="display: block; font-size: 12px; color: #666; margin-bottom: 8px; cursor: pointer;"> 104 ð¤ Upload your own image 105 </label> 106 <input type="file" id="upload-image-2" accept="image/*" style="margin-bottom: 8px; font-size: 13px; font-family: 'JetBrains Mono', monospace;"> 107 <img id="example-image-2" src="example-chart.png" alt="" style="max-width: 100%; height: auto; border: 1px solid #ddd; border-radius: 4px; margin-top: 8px;"> 108 <p style="font-size: 12px; color: #999; margin-top: 4px;"> 109 This chart image has no ALT text and can be tested for ALT text generation. 110 </p> 111 </div> 112 113 114 </div> 115 </div> 116 </div> 117 118 <!-- Sidekick UI --> 119 120 <!-- Floating Action Button & Menu --> 121 <div id="sidekick-overlay"> 122 <div id="sidekick-menu"> 123 <div id="sidekick-menu-header">SIDEKICK</div> 124 <!-- Menu items generated dynamically from usecases/usecases.json --> 125 </div> 126 <button id="sidekick-toggle" class="sidekick-testing-button" title="Sidekick"> 127 ðª Sidekick 128 </button> 129 </div> 130 131 <!-- Sidepanel --> 132 <div id="sidekick-sidepanel"> 133 <div id="sidekick-panel-warning"> 134 â ï¸ Experimental tool â here be dragons 135 </div> 136 <div id="sidekick-panel-header"> 137 <div id="sidekick-panel-title-wrapper"> 138 <h2 id="sidekick-panel-title">Title suggestions</h2> 139 <p id="sidekick-panel-description"></p> 140 </div> 141 <button id="sidekick-panel-close" title="Close"> 142 <svg viewBox="0 0 24 24">
142<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg> 143 </button> 144 </div> 145 146 <div id="sidekick-panel-content"> 147 <!-- Extracted content preview --> 148 <details id="sidekick-extracted-section"> 149 <summary>Show extracted content</summary> 150 <div id="sidekick-extracted-preview"></div> 151 </details> 152 153 <!-- Prompt editor --> 154 <details id="sidekick-prompt-section"> 155 <summary>Edit prompt (not required, but possible)</summary> 156 <textarea id="sidekick-prompt-textarea"></textarea> 157 </details> 158 159 <!-- Actions --> 160 <div id="sidekick-actions"> 161 <button id="sidekick-show-example-btn" class="sidekick-example-btn" style="display: none;"> 162 ð Show Example Response 163 </button> 164 <fieldset id="sidekick-options-fieldset" class="sidekick-options-fieldset" style="display: none;"> 165 <legend class="sidekick-options-legend">Check for</legend> 166 <div id="sidekick-options-list" class="sidekick-options-list"></div> 167 </fieldset> 168 <button id="sidekick-send-btn">Send to Claude</button> 169 <p id="sidekick-model-info"></p> 170 </div> 171 172 <!-- Loading --> 173 <div id="sidekick-loading"> 174 <div class="sidekick-spinner"></div> 175 <div id="sidekick-loading-text">Generating suggestions...</div> 176 </div> 177 178 <!-- Error --> 179 <div id="sidekick-error"></div> 180 181 <!-- Results --> 182 <div id="sidekick-results" style="display: none;"> 183 <div id="sidekick-results-header">Suggestions</div> 184 <div id="sidekick-results-warning">Don't use anything without double-checking. AI is a tool, not a co-author. We bear the responsibility.</div> 185 <div id="sidekick-results-list"></div> 186 </div> 187 </div> 188 </div> 189 190 <!-- Scripts loaded via init.js --> 191
191<script> 192 // Load placeholder article data 193 (async function() { 194 try { 195 const response = await fetch('placeholder-article.json?v=' + Date.now()); 196 if (response.ok) { 197 const placeholder = await response.json(); 198 window.PLACEHOLDER_ARTICLE = placeholder; 199 200 const titleInput = document.getElementById('mock-title'); 201 const ledeInput = document.getElementById('mock-lede'); 202 const bodyTextarea = document.getElementById('mock-body'); 203 204 if (titleInput) titleInput.placeholder = placeholder.title || ''; 205 if (ledeInput) ledeInput.placeholder = placeholder.shortTitle || ''; 206 if (bodyTextarea) bodyTextarea.placeholder = placeholder.body || ''; 207 } 208 } catch (err) { 209 console.warn('Could not load placeholder article:', err); 210 } 211 })(); 212 </script>
212 213
213<script> 214 (function() { 215 var s = document.createElement('script'); 216 s.src = 'init.js' + (['localhost','127.0.0.1',''].includes(location.hostname) ? '?v='+Date.now() : ''); 217 document.body.appendChild(s); 218 })(); 219 </script>
219 220 221 <!-- Footer --> 222 <footer class="site-footer"> 223 <div class="footer-content"> 224 <p>Sidekick is inspired by a similar tool made by <a href="https://www.linkedin.com/in/382462100/">Nico Scordialo</a> at ZEIT. <a href="https://timogrossenbacher.ch/">Timo Grossenbacher</a> and <a href="https://www.linkedin.com/in/beni-buess/">Beni Buess</a> have provided valuable feedback during development.</p> 225 <p>All prompts take inspiration from fellow tinkerers with these kinds of use cases. They include, among many more, <a href="https://www.linkedin.com/in/anne-kathrin-gerstlauer/">Anne-Kathrin Gerstlauer</a>, <a href="https://tk.gg/posts/ai-alt-text">Matt Taylor</a>, <a href="https://olereissmann.com/">Ole Reissmann</a>, <a href="https://lewtan.dev/">Devin Lewtan</a>, <a href="https://www.linkedin.com/in/pae-blue/">Patrick Venetz</a>, <a href="https://www.linkedin.com/in/martin-schori-aftonbladet/">Martin Schori</a>, <a href="https://lex.page/?via=david">Lex</a>.</p> 226 <p>Relevant context: <a href="https://www.republik.ch/2024/09/04/wie-die-republik-zu-kuenstlicher-intelligenz-steht">Wie die Republik zu künstlicher Intelligenz steht</a> | <a href="https://labs.davidbauer.ch/how-i-use-ai/">How I Use AI</a></p> 227 </div> 228 </footer> 229</body> 230</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.