Building a 9-language reflex game with no backend
Catch the Fly has no server component at all. No database, no API, no account system. That constraint shaped almost every decision below, including some I only arrived at after trying the more obvious approach first and running into its limits.
Translations as a plain object, not a library
With nine interface languages and no backend, I didn't want to pull in a full i18n
library for what amounts to swapping about thirty short strings. The interface text lives
in a single JavaScript object keyed by language code, and switching languages just
re-reads the current selection and rewrites the relevant innerText values on
the page. It's not elegant in the "proper framework" sense, but for a page this size it
means zero dependencies and an instant language switch with no page reload.
The legal text (Privacy Policy and Terms) is translated separately from the UI strings, since it's longer and shown in a modal rather than inline. Keeping the two separate made it much easier to update the legal wording later without hunting through UI strings for it.
Sound effects that don't exist as files
Early on I loaded two short MP3s for the "fly buzzing" and "swat" sounds. It worked, but it added network requests and file weight for something that's really just a couple of tones. I switched to generating both sounds live with the Web Audio API: the flight sound is a sawtooth oscillator sweeping downward through a low-pass filter, and the swat sound layers a quick triangle-wave thump with a short burst of filtered noise for texture. Nothing is downloaded, the files don't need to be hosted anywhere, and the sound is generated fresh in your browser the instant it's needed.
A mistake worth mentioning: obfuscating the source
For a while, the game's JavaScript was run through a code obfuscator before publishing, mostly out of a vague instinct to "protect" the source. In hindsight that was the wrong call for a project like this — it made the code harder for me to maintain, added no real protection against someone determined to copy a small hobby game, and there's a reasonable argument that heavily obfuscated client-side code just looks more suspicious to anyone (human or automated) reviewing the site than a small, readable script would. The current version ships as plain, readable JavaScript instead.
Two visual themes, one set of markup
Rather than maintaining two separate layouts for the "Classic" sketch style and the
"Modern" icon style, both themes share the same HTML and swap CSS classes on the
<body> element. The fly itself is drawn as inline SVG paths for the
Classic look, and swapped for a plain emoji in Modern mode — a small detail, but it kept
the two themes visually distinct without doubling the markup.
More devlog posts as I keep working on this — see the blog index for the rest.