1<!DOCTYPE html> 2<html lang="en" class="dark:bg-neutral-900 font-mono"> 3 <head> 4 <title>Vincent Ritter â founder of Body Beats, Tinylytics & Thunder Clap</title> 5 <meta name="viewport" content="width=device-width,initial-scale=1"> 6 <meta name="description" content="father & husband, gym goer & self-taught developer. founder of Body Beats, Tinylytics, Thunder Clap and others. living a quiet life in Poland."> 7 <meta name="author" content="Vincent Ritter"> 8 <meta name="theme-color" content="#171717" media="(prefers-color-scheme: dark)"> 9 <meta name="theme-color" content="#fafafa" media="(prefers-color-scheme: light)"> 10 <meta name="view-transition" content="same-origin"> 11 12 13 <!-- Open Graph --> 14 <meta property="og:title" content="Vincent Ritter â founder of Body Beats, Tinylytics & Thunder Clap"> 15 <meta property="og:description" content="father & husband, gym goer & self-taught developer. founder of Body Beats, Tinylytics, Thunder Clap and others. living a quiet life in Poland."> 16 <meta property="og:type" content="website"> 17 <meta property="og:url" content="https://vincentritter.com/"> 18 <meta property="og:site_name" content="Vincent Ritter"> 19 20 <!-- Twitter Cards --> 21 <meta name="twitter:card" content="summary"> 22 <meta name="twitter:title" content="Vincent Ritter â founder of Body Beats, Tinylytics & Thunder Clap"> 23 <meta name="twitter:description" content="father & husband, gym goer & self-taught developer. founder of Body Beats, Tinylytics, Thunder Clap and others. living a quiet life in Poland."> 24 <meta name="twitter:site" content="@_vincentritter"> 25 26 <link rel="alternate" type="application/atom+xml" href="/feeds/social.rss" title="Vincent Ritter â Social"> 27 <link rel="canonical" href="https://vincentritter.com/"> 28 <link rel="me" href="https://x.com/_vincentritter"> 29 <link rel="me" href="https://micro.blog/vincent"> 30 <link rel="me" href="https://github.com/vincentritter"> 31 <link rel="me" href="https://blog.vincentritter.com"> 32 33
33<script type="application/ld+json"> 34 { 35 "@context": "https://schema.org", 36 "@type": "Person", 37 "name": "Vincent Ritter", 38 "description": "father \u0026 husband, gym goer \u0026 self-taught developer. founder of Body Beats, Tinylytics, Thunder Clap and others. living a quiet life in Poland.", 39 "url": "https://vincentritter.com", 40 "sameAs": [ 41 "https://x.com/_vincentritter", 42 "https://micro.blog/vincent", 43 "https://github.com/vincentritter", 44 "https://blog.vincentritter.com" 45 ], 46 "jobTitle": "Software Developer", 47 "homeLocation": { 48 "@type": "Place", 49 "name": "Poland" 50 } 51 } 52 </script>
52 53 54 55 56 <link rel="shortcut icon" href="/favicon.ico"> 57 <link rel="icon" type="image/x-icon" sizes="16x16 32x32" href="/favicon.ico"> 58 59 <link rel="stylesheet" href="/assets/application-ad148ae6.css" data-turbo-track="reload" /> 60<link rel="stylesheet" href="/assets/tailwind-db7035da.css" data-turbo-track="reload" /> 61
61<script type="importmap" data-turbo-track="reload">{ 62 "imports": { 63 "application": "/assets/application-bfcdf840.js", 64 "@hotwired/turbo-rails": "/assets/turbo.min-9fd88cd5.js", 65 "@hotwired/stimulus": "/assets/stimulus.min-4b1e420e.js", 66 "@hotwired/stimulus-loading": "/assets/stimulus-loading-1fc53fe7.js", 67 "controllers/application": "/assets/controllers/application-3affb389.js", 68 "controllers/hello_controller": "/assets/controllers/hello_controller-708796bd.js", 69 "controllers": "/assets/controllers/index-ee64e1f1.js", 70 "controllers/omarain_controller": "/assets/controllers/omarain_controller-3d151d14.js", 71 "controllers/omarain_preview_controller": "/assets/controllers/omarain_preview_controller-1ea9ca04.js", 72 "controllers/space_controller": "/assets/controllers/space_controller-ecd154c5.js", 73 "omarain/look_rain": "/assets/omarain/look_rain-a84d8543.js", 74 "omarain/rain_model": "/assets/omarain/rain_model-a94ed749.js" 75 } 76}</script>
76 77<link rel="modulepreload" href="/assets/application-bfcdf840.js"> 78<link rel="modulepreload" href="/assets/turbo.min-9fd88cd5.js"> 79<link rel="modulepreload" href="/assets/stimulus.min-4b1e420e.js"> 80<link rel="modulepreload" href="/assets/stimulus-loading-1fc53fe7.js"> 81<link rel="modulepreload" href="/assets/controllers/application-3affb389.js"> 82<link rel="modulepreload" href="/assets/controllers/hello_controller-708796bd.js"> 83<link rel="modulepreload" href="/assets/controllers/index-ee64e1f1.js"> 84<link rel="modulepreload" href="/assets/controllers/omarain_controller-3d151d14.js"> 85<link rel="modulepreload" href="/assets/controllers/omarain_preview_controller-1ea9ca04.js"> 86<link rel="modulepreload" href="/assets/controllers/space_controller-ecd154c5.js"> 87<link rel="modulepreload" href="/assets/omarain/look_rain-a84d8543.js"> 88<link rel="modulepreload" href="/assets/omarain/rain_model-a94ed749.js">
89<script type="module">import "application"</script>
89 90 91
91<script src="https://tinylytics.app/embed/qMgTqJ6iseB9iPGpa_ue.js?events&beacon&kudos&kudos_effect=random" defer></script>
91 92 </head> 93 94 <body class="dark:bg-neutral-900"> 95 <a href="#main-content" class="skip-link">Skip to content</a> 96 <canvas 97 data-controller="space" 98 data-action="resize@window->space#resize pointermove@window->space#move pointerover@window->space#hover focusin@window->space#hover pointerout@window->space#leave focusout@window->space#leave" 99 class="pointer-events-none fixed inset-0 size-full" 100 aria-hidden="true" 101 ></canvas> 102 103 104 <div class="relative z-10 prose dark:prose-invert prose-p:mt-0 prose-ul:mt-0 my-6 px-4 mx-auto max-w-2xl"> 105 106<header class="flex flex-row gap-4 mb-10 items-center justify-end" style="view-transition-name: site-header"> 107 108 <nav aria-label="Main" class="flex flex-row gap-4 items-center text-xs text-neutral-600 dark:text-neutral-400 mt-[2.3px]"> 109 <a href="/apps" class="no-underline hover:text-neutral-900 dark:hover:text-neutral-100 transition-colors">apps</a> 110 <a href="/social" class="no-underline hover:text-neutral-900 dark:hover:text-neutral-100 transition-colors">social</a> 111 </nav> 112</header> 113 114 115 <main id="main-content"> 116 117<section class="not-prose mb-12"> 118 <div class="flex flex-row items-start justify-between gap-6 sm:gap-10"> 119 <div class="min-w-0 flex-1"> 120 <h1 class="text-3xl sm:text-4xl font-semibold tracking-tight m-0 mb-5 text-neutral-900 dark:text-neutral-50"> 121 <span class="inline-block leading-none" style="view-transition-name: site-name">Vincent Ritter</span> 122 </h1> 123 124 <p class="text-base sm:text-lg leading-relaxed text-neutral-700 dark:text-neutral-300 m-0"> 125 father & husband, gym goer & self-taught developer. founder of 126 <a href="https://bodybeats.fitness?ts=vr" target="_blank" rel="noopener noreferrer" data-project="bodybeats" class="project-link inline-flex items-center gap-1.5 leading-none align-middle whitespace-nowrap no-underline font-medium text-neutral-900 dark:text-neutral-100 hover:text-[var(--bodybeats)] focus-visible:text-[var(--bodybeats)] transition-colors"> 127 <img alt="" class="block size-[1em] shrink-0 rounded-sm" src="/assets/bodybeats-d5289a62.png" /> 128 Body Beats 129 </a>, 130 <a href="https://tinylytics.app?ts=vr" target="_blank" rel="noopener noreferrer" data-project="tinylytics" class="project-link inline-flex items-center gap-1.5 leading-none align-middle whitespace-nowrap no-underline font-medium text-neutral-900 dark:text-neutral-100 hover:text-[var(--tinylytics)] focus-visible:text-[var(--tinylytics)] transition-colors"> 131 <img alt="" class="block size-[1em] shrink-0 rounded-sm" src="/assets/tiny-d38f9fef.png" /> 132 Tinylytics 133 </a>, 134 <a href="https://thunderclap.app?ts=vr" target="_blank" rel="noopener noreferrer" data-project="thunderclap" class="project-link inline-flex items-center gap-1.5 leading-none align-middle whitespace-nowrap no-underline font-medium text-neutral-900 dark:text-neutral-100 hover:text-[var(--thunderclap)] focus-visible:text-[var(--thunderclap)] transition-colors"> 135 <img alt="" class="block size-[1em] shrink-0 rounded-sm" src="/assets/thunder-clap-1117ae64.png" /> 136 Thunder Clap 137 </a> 138 and others. living a quiet life in Poland. 139 </p> 140 </div> 141 142 <img alt="" class="w-20 h-20 sm:w-28 sm:h-28 rounded-xl object-cover shrink-0 mt-1" decoding="async" src="/assets/me-64a7d8b4.jpg" /> 143 </div> 144</section> 145 146<section class="not-prose mb-12" aria-label="Projects"> 147 <div class="grid grid-cols-1 sm:grid-cols-2 gap-2"> 148 <a 149 href="https://bodybeats.fitness?ts=vr" 150 target="_blank" 151 rel="noopener noreferrer" 152 data-tinylytics-event="project.click" 153 data-tinylytics-event-value="Body Beats" 154 data-project="bodybeats" 155 style="--project-accent: var(--bodybeats)" 156 class="project-card flex items-start gap-3 p-3 rounded-lg border border-neutral-200 dark:border-neutral-700 no-underline text-inherit" 157 > 158 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm" src="/assets/bodybeats-d5289a62.png" /> 159 <div class="relative z-10 min-w-0"> 160 <h2 class="m-0 flex flex-wrap items-baseline gap-x-1.5 text-sm font-semibold leading-tight text-neutral-900 dark:text-neutral-50"> 161 Body Beats 162 </h2>
163 <p class="text-xs text-neutral-600 dark:text-neutral-400 m-0 mt-0.5 leading-snug">Workouts at home, at the gym, or anywhere.</p> 164 </div> 165 </a> 166 <a 167 href="https://tinylytics.app?ts=vr" 168 target="_blank" 169 rel="noopener noreferrer" 170 data-tinylytics-event="project.click" 171 data-tinylytics-event-value="Tinylytics" 172 data-project="tinylytics" 173 style="--project-accent: var(--tinylytics)" 174 class="project-card flex items-start gap-3 p-3 rounded-lg border border-neutral-200 dark:border-neutral-700 no-underline text-inherit" 175 > 176 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm" src="/assets/tiny-d38f9fef.png" /> 177 <div class="relative z-10 min-w-0"> 178 <h2 class="m-0 flex flex-wrap items-baseline gap-x-1.5 text-sm font-semibold leading-tight text-neutral-900 dark:text-neutral-50"> 179 Tinylytics 180 </h2> 181 <p class="text-xs text-neutral-600 dar
181k:text-neutral-400 m-0 mt-0.5 leading-snug">Privacy-first analytics for your corner of the web.</p> 182 </div> 183 </a> 184 <a 185 href="https://thunderclap.app?ts=vr" 186 target="_blank" 187 rel="noopener noreferrer" 188 data-tinylytics-event="project.click" 189 data-tinylytics-event-value="Thunder Clap" 190 data-project="thunderclap" 191 style="--project-accent: var(--thunderclap)" 192 class="project-card flex items-start gap-3 p-3 rounded-lg border border-neutral-200 dark:border-neutral-700 no-underline text-inherit" 193 > 194 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm" src="/assets/thunder-clap-1117ae64.png" /> 195 <div class="relative z-10 min-w-0"> 196 <h2 class="m-0 flex flex-wrap items-baseline gap-x-1.5 text-sm font-semibold leading-tight text-neutral-900 dark:text-neutral-50"> 197 Thunder Clap 198 </h2> 199 <p class="text-xs text-neutral-600 dark:text-neutral-400 m-0 mt-0.5 leading-snug">Uptime monitoring with global probes.</p> 200 </div> 201 </a> 202 <a 203 href="https://scribbles.page?ts=vr" 204 target="_blank" 205 rel="noopener noreferrer" 206 data-tinylytics-event="project.click" 207 data-tinylytics-event-value="Scribbles" 208 data-project="scribbles" 209 style="--project-accent: var(--scribbles)" 210 class="project-card flex items-start gap-3 p-3 rounded-lg border border-neutral-200 dark:border-neutral-700 no-underline text-inherit" 211 > 212 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm" src="/assets/scribbles-c8565bd6.png" /> 213 <div class="relative z-10 min-w-0"> 214 <h2 class="m-0 flex flex-wrap items-baseline gap-x-1.5 text-sm font-semibold leading-tight text-neutral-900 dark:text-neutral-50"> 215 Scribbles 216 </h2>
217 <p class="text-xs text-neutral-600 dark:text-neutral-400 m-0 mt-0.5 leading-snug">A nice place to blog â start simple, publish.</p> 218 </div> 219 </a> 220 <div class="project-separator col-span-full flex items-center gap-3 w-1/2 py-2"> 221 <a class="shrink-0 text-xs text-neutral-600 dark:text-neutral-400 no-underline hover:text-neutral-900 dark:hover:text-neutral-100 transition-colors" href="/apps">apps</a> 222 <span class="flex-1 h-px bg-linear-to-r from-neutral-200 to-transparent dark:from-neutral-700" aria-hidden="true"></span> 223 </div> 224 <a 225 href="/apps/tinytray" 226 data-tinylytics-event="project.click" 227 data-tinylytics-event-value="Tinytray" 228 data-project="tinytray" 229 style="--project-accent: var(--tinytray)" 230 class="project-card flex items-start gap-3 p-3 rounded-lg border border-neutral-200 dark:border-neutral-700 no-underline text-inherit" 231 > 232 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm dark:hidden" style="view-transition-name: app-tinytray-icon" src="/assets/apps/tinytray-12d7ef61.svg" /> 233 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm hidden dark:block" style="view-transition-name: app-tinytray-icon" src="/assets/apps/tinytray-dark-f741b20d.svg" /> 234 <div class="relative z-10 min-w-0"> 235 <h2 class="m-0 flex flex-wrap items-baseline gap-x-1.5 text-sm font-semibold leading-tight text-neutral-900 dark:text-neutral-50"> 236 <span style="view-transition-name: app-tinytray-title">Tinytray</span> 237 </h2>
238 <p class="text-xs text-neutral-600 dark:text-neutral-400 m-0 mt-0.5 leading-snug">An opinionated hover drawer for the Omarchy bar.</p> 239 </div> 240 </a> 241 <a 242 href="/apps/omarain" 243 data-tinylytics-event="project.click" 244 data-tinylytics-event-value="Omarain" 245 data-project="omarain" 246 data-controller="omarain-preview" 247 data-action="pointerenter->omarain-preview#enter pointerleave->omarain-preview#leave focus->omarain-preview#enter blur->omarain-preview#leave" 248 style="--project-accent: var(--omarain)" 249 class="project-card flex items-start gap-3 p-3 rounded-lg border border-neutral-200 dark:border-neutral-700 no-underline text-inherit overflow-hidden" 250 > 251 <canvas 252 data-omarain-preview-target="canvas" 253 class="pointer-events-none absolute inset-0 z-0" 254 aria-hidden="true" 255></canvas> 256 257 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm dark:hidden" style="view-transition-name: app-omarain-icon" src="/assets/apps/omarain-4273aa80.svg" /> 258 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm hidden dark:block" style="view-transition-name: app-omarain-icon" src="/assets/apps/omarain-dark-af25880d.svg" /> 259 <div class="relative z-10 min-w-0"> 260 <h2 class="m-0 flex flex-wrap items-baseline gap-x-1.5 text-sm font-semibold leading-tight text-neutral-900 dark:text-neutral-50"> 261 <span style="view-transition-name: app-omarain-title">Omarain</span> 262 </h2>
263 <p class="text-xs text-neutral-600 dark:text-neutral-400 m-0 mt-0.5 leading-snug">A blissful rain overlay on the Omarchy wallpaper.</p> 264 </div> 265 </a> 266 <a 267 href="/apps/photon" 268 data-tinylytics-event="project.click" 269 data-tinylytics-event-value="Photon" 270 data-project="photon" 271 style="--project-accent: var(--photon)" 272 class="project-card flex items-start gap-3 p-3 rounded-lg border border-neutral-200 dark:border-neutral-700 no-underline text-inherit" 273 > 274 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm dark:hidden" style="view-transition-name: app-photon-icon" src="/assets/apps/photon-c975639c.svg" /> 275 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm hidden dark:block" style="view-transition-name: app-photon-icon" src="/assets/apps/photon-dark-455640b7.svg" /> 276 <div class="relative z-10 min-w-0"> 277 <h2 class="m-0 flex flex-wrap items-baseline gap-x-1.5 text-sm font-semibold leading-tight text-neutral-900 dark:text-neutral-50"> 278 <span style="view-transition-name: app-photon-title">Photon</span> 279 <span class="font-normal text-xs text-neutral-400 dark:text-neutral-500">Coming soon</span> 280 </h2>
281 <p class="text-xs text-neutral-600 dark:text-neutral-400 m-0 mt-0.5 leading-snug">An opinionated macOS menu bar app for Micro.blog.</p> 282 </div> 283 </a> 284 <div class="project-separator col-span-full flex items-center gap-3 w-1/2 py-2"> 285 <span class="shrink-0 text-xs text-neutral-600 dark:text-neutral-400">aside</span> 286 <span class="flex-1 h-px bg-linear-to-r from-neutral-200 to-transparent dark:from-neutral-700" aria-hidden="true"></span> 287 </div> 288 <a 289 href="https://sublimefeed.com?ts=vr" 290 target="_blank" 291 rel="noopener noreferrer" 292 data-tinylytics-event="project.click" 293 data-tinylytics-event-value="Sublime Feed" 294 data-project="sublimefeed" 295 style="--project-accent: var(--sublimefeed)" 296 class="project-card flex items-start gap-3 p-3 rounded-lg border border-neutral-200 dark:border-neutral-700 no-underline text-inherit" 297 > 298 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm" src="/assets/sublime-62017e64.png" /> 299 <div class="relative z-10 min-w-0"> 300 <h2 class="m-0 flex flex-wrap items-baseline gap-x-1.5 text-sm font-semibold leading-tight text-neutral-900 dark:text-neutral-50"> 301 Sublime Feed 302 </h2>
303 <p class="text-xs text-neutral-600 dark:text-neutral-400 m-0 mt-0.5 leading-snug">Mindful, distraction-free RSS reading.</p> 304 </div> 305 </a> 306 <a 307 href="https://microblog.dev?ts=vr" 308 target="_blank" 309 rel="noopener noreferrer" 310 data-tinylytics-event="project.click" 311 data-tinylytics-event-value="Build with Micro.blog" 312 data-project="microblog" 313 style="--project-accent: var(--microblog)" 314 class="project-card flex items-start gap-3 p-3 rounded-lg border border-neutral-200 dark:border-neutral-700 no-underline text-inherit" 315 > 316 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm" src="/assets/microblog-dev-2589f200.png" /> 317 <div class="relative z-10 min-w-0"> 318 <h2 class="m-0 flex flex-wrap items-baseline gap-x-1.5 text-sm font-semibold leading-tight text-neutral-900 dark:text-neutral-50"> 319 Build with Micro.blog 320 </h2> 321 <p class="text-xs text-neutral-600 dar
321k:text-neutral-400 m-0 mt-0.5 leading-snug">Unofficial API docs, examples, and app showcases.</p> 322 </div> 323 </a> 324 <a 325 href="https://sublimeads.com?ts=vr" 326 target="_blank" 327 rel="noopener noreferrer" 328 data-tinylytics-event="project.click" 329 data-tinylytics-event-value="Sublime Ads" 330 data-project="sublimeads" 331 style="--project-accent: var(--sublimeads)" 332 class="project-card flex items-start gap-3 p-3 rounded-lg border border-neutral-200 dark:border-neutral-700 no-underline text-inherit" 333 > 334 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm" src="/assets/sublime-ads-5c415ce3.png" /> 335 <div class="relative z-10 min-w-0"> 336 <h2 class="m-0 flex flex-wrap items-baseline gap-x-1.5 text-sm font-semibold leading-tight text-neutral-900 dark:text-neutral-50"> 337 Sublime Ads 338 </h2> 339 <p class="text-xs text-neutral-600 dark:text-neutral-400 m-0 mt-0.5 leading-snug">Contextual ads for LLMs ⢠existing users only</p> 340 </div> 341 </a> 342 <a 343 href="https://shoutouts.page?ts=vr" 344 target="_blank" 345 rel="noopener noreferrer" 346 data-tinylytics-event="project.click" 347 data-tinylytics-event-value="Shoutouts" 348 data-project="shoutouts" 349 style="--project-accent: var(--shoutouts)" 350 class="project-card flex items-start gap-3 p-3 rounded-lg border border-neutral-200 dark:border-neutral-700 no-underline text-inherit" 351 > 352 <img alt="" class="relative z-10 size-6 shrink-0 mt-0.5 rounded-sm" src="/assets/shoutouts-6e209b28.png" /> 353 <div class="relative z-10 min-w-0"> 354 <h2 class="m-0 flex flex-wrap items-baseline gap-x-1.5 text-sm font-semibold leading-tight text-neutral-900 dark:text-neutral-50"> 355 Shoutouts 356 </h2>
357 <p class="text-xs text-neutral-600 dark:text-neutral-400 m-0 mt-0.5 leading-snug">Embed shoutouts for things you like ⢠existing users only</p> 358 </div> 359 </a> 360 </div> 361</section> 362 363 </main> 364 365 <footer class="flex flex-row justify-between items-center mt-12 pb-6 text-xs text-neutral-600 dark:text-neutral-400"> 366 <p class="m-0 mb-0"> 367 <a href="/cdn-cgi/l/email-protection#8ae2eff3cafce3e4e9efe4fef8e3fefeeff8a4e9e5e7" class="no-underline hover:text-neutral-900 dark:hover:text-neutral-100 transition-colors">email</a> 368 · 369 <a href="https://x.com/_vincentritter" target="_blank" rel="noopener noreferrer" class="no-underline hover:text-neutral-900 dark:hover:text-neutral-100 transition-colors">x</a> 370 · 371 <a href="https://micro.blog/vincent" target="_blank" rel="noopener noreferrer" class="no-underline hover:text-neutral-900 dark:hover:text-neutral-100 transition-colors">mb</a> 372 · 373 <span role="img" aria-label="England and Poland">ð´ó §ó ¢ó ¥ó ®ó §ó ¿ ðµð±</span> 374 </p> 375 376 <p class="m-0 mb-0"> 377 <span lang="ja">ãããã</span> 378 · 379 <a href="/tools" class="no-underline hover:text-neutral-900 dark:hover:text-neutral-100 transition-colors">tools</a> 380 </p> 381</footer> 382 383 </div>
vendor: 111 bytes, lines 383-384
383 384 <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>
384</body> 385</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.