Issue 001 · May 2026 · ArticleTech · 14 May 2026
Tech · 14 May 2026

Why Fifteen Kilobytes Is Enough

Every game on this site loads in about 15 kilobytes. The average web page is 170 times larger. Here is what the browser already provides — and why we chose to use only that.

The average web page as of 2026 weighs around 2.5 megabytes. The average Hage Game game page weighs about 15 kilobytes, of which roughly 8 kilobytes is the shared stylesheet and JavaScript. The game itself — its logic, its rendering, its audio, its local storage interface — fits in 7 kilobytes or less. This is not an accident or an aesthetic choice. It is the natural result of building on the web platform without adding anything the web platform does not provide.

What the modern browser already gives you

Modern browser APIs are comprehensive enough that a small, self-contained game needs almost nothing from outside. The Canvas API handles 2D rendering at arbitrary resolution with hardware acceleration. The Web Audio API synthesises sounds — oscillators, filters, envelopes — in real time without any audio files. The pointer events API unifies mouse, touch and stylus input under a single interface. localStorage persists data between sessions without a server. requestAnimationFrame provides a 60Hz game loop that pauses when the tab is hidden. None of this requires an import.

The games in this issue use exactly those five APIs. Every game is a single HTML file with inline styles and inline JavaScript. The total HTML including markup, styles and game code is typically between 12 and 20 kilobytes. The shared stylesheet adds another 8 kilobytes, loaded once and cached for the session. That is the entire technical stack.

What this means for load time

On a 4G mobile connection (around 10 megabits per second in practice), a 15-kilobyte page loads in under 15 milliseconds, excluding DNS and connection overhead. Including that overhead, a first-time load takes roughly 200 to 400 milliseconds. A return visit, when the shared stylesheet is already cached, typically under 100 milliseconds. Compare this to the typical mobile game that requires a 200-megabyte download before you can play anything. The difference in friction is not linear; it is the difference between "I will try this" and "I will bookmark this and come back later" — and "come back later" almost never happens.

What 15 kilobytes cannot do

It is worth being honest about the constraints. Fifteen kilobytes cannot store complex game state — our games save a best score or best time, nothing more. It cannot serve a sophisticated matchmaking system, a persistent progression, a social leaderboard or an in-app purchase. It cannot play an audio file. It cannot load a texture. It cannot display a photograph. Every asset used in a Hage Game game was either computed programmatically (the Canvas drawing calls) or synthesised in real time (the Web Audio oscillators). Games that depend on rich media — platformers with hand-drawn sprites, narrative games with recorded dialogue, music games with licensed tracks — cannot be built at this scale.

We think this constraint is almost entirely a feature. It forced us to design games around mechanics rather than assets. A game where the player cannot tell that the audio is synthesised rather than recorded (Sound Match scores well in informal tests) is a better game than one that hides a thin mechanic behind elaborate audiovisual production. The mechanic either holds attention or it does not. Fifteen kilobytes makes that honesty mandatory.

The dependency-free choice

The single biggest factor in keeping our pages small was choosing not to use any JavaScript framework, bundler, or game engine. A minimal React application adds roughly 40 kilobytes of framework code before you have written a single line of game logic. A minimal Phaser.js scene adds around 1 megabyte. We used none of these. Every line of JavaScript in every Hage Game page was written for that page and does exactly what that page needs. The tradeoff is development time — writing a collision detection routine from scratch is slower than calling a library function — but the result is code we understand completely and can debug in a browser's developer tools in a single tab, without a build step, without a server.

This is, in a sense, a return to how the web was built before frameworks became the default. We do not think frameworks are bad — for large applications they are essential — but for a small, self-contained game that needs to load in under a second on any device, the dependency-free path is clearly the right one.


Published · 14 May 2026 · Written and signed by Bill


Published · 14 May 2026 · Written and signed by Bill