Craft·5 min read

Putting an Entire Game in One File

One file you can email. No install, no server, no broken image paths in five years' time.

A painted satchel and notebook from the Edward and B Bear adventure, laid out as an inventory.

Every game we deliver is one file. Not a folder, not an installer, not a link to a service. One HTML document containing the code, every image, and every sound, which you can email to somebody.

That is an unusual choice and it has real costs. Here is how it is done and why we think the trade is right for work that is meant to be kept.

Why bother

Consider what a normal web game is. An HTML file, a folder of scripts, a folder of images, a folder of audio, served by a host, at an address.

Every one of those is a thing that can go wrong later. The host lapses. The address changes. Somebody copies the HTML file to a memory stick and leaves the folders behind, so it opens to a page of broken images. A path that worked on one machine breaks on another because of a capital letter.

None of that matters for a game somebody plays this week. It matters enormously for a game somebody was given for their sixtieth birthday and wants to show a grandchild in 2034.

A single file has no dependencies to lose. It opens from a downloads folder with no internet connection at all. The failure modes are down to one: losing the file, which is the same failure mode as losing a photograph and one people already understand.

How assets get inside

The mechanism is a data URI: a way of writing a file's contents into a document as text.

An image is normally referenced by a path. Instead, the entire image is encoded into a long string of characters and written where the path would go. The browser decodes it back into an image. As far as everything downstream is concerned it is an ordinary image, because it is one.

The same applies to audio, fonts and anything else. In our builds, assets sit in a single object keyed by name, and each becomes an ordinary image object as the file opens. Drawing code asks for an asset by name and never knows the difference.

The cost is size. The encoding carries three bytes of original data in four characters, so everything is about a third larger than it would be as a separate file. Compression during transfer recovers most of that, because the encoded text compresses well, but the file on disk is genuinely bigger.

A painted satchel and notebook from the Edward and B Bear adventure, laid out as an inventory.
Every painting in that build is inside the file. Nothing is fetched.

Assembling it

Doing this by hand would be miserable, so it is a build step.

Ours reads a configuration file describing the game and a folder of artwork, encodes every asset, substitutes them and the game's text into a template, and writes out the finished document. It uses only what comes with Node, so it runs anywhere without installing anything, which is the same durability argument applied one level up.

The template is a complete, working game with placeholders where the specific content goes: the title, the character's name, the artwork, the level layout, the strings shown at the start and the end. Building a commission is filling those in.

That is the honest structure of the work, and it is worth being plain about. A genuinely novel game per customer cannot be produced reliably at a sensible price. A strong shared engine with bespoke art, levels, names and jokes can, and that is what the tiers describe.

The loading problem

There is one real drawback and it needs handling rather than denying.

A twenty megabyte file is twenty megabytes before anything appears. With separate assets a game can show its first screen and load the rest in the background; with one file, nothing happens until enough of the document has arrived.

For a game opened from a link that has already been downloaded, this is a non-issue. For a game embedded in a web page, it very much is one, which is why the play pages on this site show a still image first and only fetch the game when somebody presses play. Nobody who is reading an article pays for a game they did not ask to play.

It is also why file size is a design constraint rather than an afterthought, and why one of our builds is 104KB and another is twenty megabytes. The arithmetic behind that gap is in why one game is 104KB and another is 20MB.

What it makes easy

Two things fall out of this that were not the goal and turn out to matter.

It works offline, completely. Not through a service worker or a caching strategy, but because there is nothing to fetch. A game on a phone in a car with no signal is the same game.

It is testable as a unit. The whole game is one artefact. A test opens the file, drives it and asserts it can be finished, with no server to start and no fixtures to arrange. That is what makes the acceptance testing in proving a game is actually finished practical rather than aspirational.

What it makes hard

Being fair about the other side.

Updating means resending. There is no patching. A fix is a new file, and anybody holding the old one keeps holding it. For a keepsake that is fine; for anything with ongoing content it would not be.

Nothing is shared between games. Two commissions with the same engine each carry their own copy of it. That is wasteful in the abstract and irrelevant in practice, because the engine is small and the artwork is not.

Large files are awkward to email. Twenty megabytes exceeds some mail limits, so delivery becomes a link to a download rather than an attachment. The file is still a file; only the handover changes.

What this means for a commission

You receive a thing, not access to a thing. The build is yours, it works without us, and it will keep working.

It is the reason file size is discussed at the brief stage. Style, number of scenes and whether music is recorded all land in the same number, and that number decides how the game is delivered.

And it is why the artwork is the budget. The engine is a rounding error. The paintings are the game, which is the trade explored in pixel art or painted.

◆ Questions

Common questions

Can a whole game fit in one HTML file?+

Yes. Images, sound and code can all be embedded directly in the document as text, so the file needs nothing alongside it. Ours range from 104 kilobytes to twenty megabytes and all of them are single files.

What is a data URI?+

A way of writing a file's contents directly into a document as text rather than linking to it. An image becomes a long string that the browser decodes back into the image. It makes the document larger but removes the need for a separate file.

Why not just host the game normally?+

Hosting works until it does not. A folder of assets can lose a file, a host can lapse, a path can break. A single file can be emailed, put on a memory stick, or opened from a downloads folder in ten years and still work.

How much bigger does embedding make a file?+

About a third larger than the raw assets, because the text encoding used carries three bytes of data in four characters. Compression during transfer claws most of that back.

Does a big single file load slowly?+

It loads as one request rather than hundreds, which is usually faster, but nothing appears until enough of it has arrived. That is why we show a poster image first and only load the game when somebody asks for it.

  • craft
  • code
  • delivery
  • process
◆ Keep reading

Related from the journal.