Every technical decision behind Galaxtarus, in one place. Why file://. Why vanilla. Why MIDI. Why hand-carved wood. The choices, and the trade-offs we accepted.
And if it doesn't — statistically more likely — the game still runs anyway. When Steam shuts down. When a mandatory patch turns a work of art into an error page. When a dev loses interest and their site goes down. When the storefronts close.
Worst case it works. Best case, it works anyway.
So Galaxtarus has no build step. No bundler. No npm. No server. No DRM. No telemetry. No mandatory updates. A folder of files, double-click the HTML, the game runs. From a USB stick. From a hard drive. From a laptop on solar panels, off the grid, after the internet stutters.
| Layer | Choice | Trade-off accepted |
|---|---|---|
| Language | Vanilla ES6 JavaScript | No TypeScript. No compile step. Boilerplate eaten by hand. |
| Modules | None — global namespace window.GALAXTARUS |
ES6 modules need a server (file:// blocks them via CORS). We use script tags loaded in order. |
| Rendering | Canvas 2D | No WebGL. No 3D. 2D works on anything since 2005. 3D ages badly. |
| Audio | Tone.js + raw MIDI option | Procedural synthesis means no sample bank. MIDI fallback ~5 KB per track. |
| Network | None | No multiplayer. No leaderboard. No cloud saves. The game is yours, alone. |
| Persistence | localStorage | No accounts. Save data lives in the browser. Backup is copy-paste. |
| Build | None | No tree-shaking, no minification. Trade-off: zero risk of build breakage at 2am. |
| Dependencies | Tone.js (bundled locally), nothing else | No npm hell. No dependency tree. One library, included as a single file. |
Everything in the engine is a class. No procedural blobs. No hidden globals. Two non-negotiable rules govern every file.
Rule 1 — namespace = file path. A class in src/entities/Ship.js is exposed as GALAXTARUS.entities.Ship. If you know the namespace, you know the file. If you know the file, you know the namespace. No exceptions.
Rule 2 — injected instances, no global singletons. Classes go on window.GALAXTARUS. Instances get created at boot and passed around in a single game context object. No hidden coupling. Any project built with this engine swaps whatever it wants.
// src/entities/Ship.js class Ship { constructor(wx, wy) { this.wx = wx; this.wy = wy; this.vx = 0; this.vy = 0; } update(input, dt) { // inertia, boost, overheat — all here, no hidden state } render(ctx, camera, t) { /* ... */ } } window.GALAXTARUS = window.GALAXTARUS || {}; window.GALAXTARUS.entities = window.GALAXTARUS.entities || {}; window.GALAXTARUS.entities.Ship = Ship;
// boot — galaxtarus.html
const G = window.GALAXTARUS;
const bus = new G.core.EventBus();
const clock = new G.core.SimulationClock();
const ship = new G.entities.Ship(0, 0);
const game = Object.freeze({ bus, clock, ship, /* etc */ });
// every system gets game. Nothing leaks via globals.
const combat = new G.systems.Combat(game);
const ai = new G.systems.AiDirector(game);
Why no engine like Godot or Phaser? Because they have install steps, version mismatches, and dependencies that age. We wanted a folder of text files that opens in any browser, today and in twenty years. The trade-off: less features out of the box. The win: full control, full readability, full longevity.
Why 2D and not 3D? A 2D game from 1992 still runs. A 3D game from 2002 often doesn't (driver issues, dead shaders, dead engines). 2D is the tech that survives decades. It's also faster to develop, easier to read, more portable, and historically the home of indie classics — Celeste, Hollow Knight, Hades, Stardew Valley, Undertale.
Why MIDI? A piano sample is 50 MB. A piano MIDI is 5 KB. MIDI files open in any sequencer made since 1983. The pitch and timing are independent of the synth — you can swap the instrument, save the file as a text snapshot, modify the notes by hand. It's the most resilient music format that exists. Tone.js renders it procedurally in the browser, so no sound assets need to ship with the game.
Why hand-carved wood? Because Raphaël is also a chip carver, internationally recognized. The Kickstarter collector tier deserves an object made the same way the rest of the project was: by hand, slowly, with care. Wood and code share more than people think. Both are slow. Both are quiet. Both leave marks.
What runs Galaxtarus? Any computer with a modern browser — Chrome, Firefox, Edge, Safari. Linux, Windows, macOS, ChromeOS. Old laptops. Refurbished hardware. Off-the-grid setups with solar power. The minimum bar is whatever your browser needs. The maximum bar is — well, it doesn't get harder than this.