
23/6/2026 · 7:26
Claude Did Not Just Make Quake: the Three.js Port That Worked Because It Stayed File-by-File
A technical case study of mrdoob's Claude-assisted Three.js port of Quake. It breaks down why the successful version was not a blank-page FPS prompt, but a constrained file-by-file port that preserved Quake's original architecture, data formats, input paths, and failure boundaries.
The public hook is almost too neat: "Okay Claude, can you help me port Quake to Three.js?", followed by "... One hour later" and a playable-looking browser demo from mrdoob, the creator of Three.js 1. The repo tells a more useful story for AI game builders: this was not magic prompt dust, but a source-to-source port that used Claude as an accelerant while keeping the original Quake architecture visible 2.
The interesting case-study question is not "Can Claude make Quake?" It is: what shape of work made Claude useful on a 1996 FPS codebase without letting the port dissolve into hallucinated glue?
Cargando tarjeta de contenido…
Case snapshot
| Field | What is publicly documented |
|---|---|
| Game | three-quake, a browser-playable port of id Software's Quake to Three.js 2 |
| AI tool context | The README credits the Three.js port to mrdoob "with @claude", and the dev log frames the starting ask as a Claude-assisted port 3 1 |
| Playable evidence | The project links to a live GitHub Pages build at mrdoob.github.io/three-quake/ 4. |
| Source evidence | The repo is public, GPL v2, and contains JavaScript/TypeScript/HTML files plus maps, pak0.pak, and server code 2 |
| Build-process evidence | In a Reddit reply, mrdoob said the first attempt "got out of control" after a couple of days; the second attempt worked better when he asked Claude to do a 1:1 port of every file 5 |
The channel focus here fits unusually well: first-person shooter, real demo link, visible code, named AI tool, exact public starting prompt, and a disclosed failure mode. The only thing missing is a full prompt transcript. We should not pretend one exists.
What the player actually gets
The repo describes the project plainly as "A port of Quake to Three.js" and includes the shareware
pak0.pak for Episode 1; players who own the registered game can replace it with their own pak0.pak for the full game 6. That matters because the project is not a Quake-inspired clone with approximate mechanics. It is trying to preserve the original game's data path.
mainmenu.png asset, shown here as a real project file rather than a generated illustration 7. The public repo also points back to id Software's original Quake source as the base credit 8. So the right mental model is not "Claude designed a new FPS". It is closer to "Claude helped port a known C-era engine into a browser-native JavaScript/Three.js runtime, with a senior graphics programmer steering the work".
The architectural bet: preserve file boundaries
The most transferable decision is the one mrdoob disclosed in the Reddit thread. The first attempt failed structurally: after a couple of days, it "got out of control". The second attempt constrained Claude with a clearer transformation rule: do a 1:1 port of every file 5.
That is a small sentence with a large implication. A porting task gives the model a map. Instead of asking for a new architecture, the human gives Claude a checklist of source files, module names, and unfinished surfaces. When a file remains unported or half-ported, the gap is inspectable. When the model invents behavior, the original file can be used as a reference point.
You can see that preservation strategy in the repository layout. The
src/ folder contains many modules whose names mirror Quake subsystems: client.js, server.js, world.js, gl_rmain.js, gl_rsurf.js, snd_mix.js, host.js, cmd.js, cvar.js, pak.js, and more 9. The project is not organized as one giant vibe-coded game.js. It keeps the old engine's separations alive enough that each subsystem can be ported and debugged as a unit.Cargando tarjeta de contenido…
That also explains why this case is more instructive than many "one prompt game" clips. The prompt made the demo visible; the file-by-file constraint made the work auditable.
The browser stack underneath the demo
The repo's language breakdown is mostly JavaScript, with TypeScript used in the server side and a small amount of HTML 2. The top-level entry point imports Quake-like systems such as
Sys_Init, Host_Init, Host_Frame, COM_FetchPak, and rendering state from Three.js-backed modules, then runs the game loop through renderer.setAnimationLoop() so the same frame path can work with WebXR sessions 10.A few implementation choices are worth copying in other AI-assisted ports:
- Keep original data formats explicit. The project includes BSP-format definitions such as lump types, map bounds, contents flags, and texture constants in
bspfile.js11. That reduces the temptation to approximate map loading with a made-up scene graph. - Wrap the old rendering assumptions instead of deleting them. The
glquake.jslayer imports Three.js, tracks game textures, and maps old GL texture-filtering behavior onto Three.js texture settings 12. - Treat input as a platform problem. The web input layer covers keyboard, pointer lock, mouse, mobile touch, gamepad, and WebXR control paths 13. That is the boring work that decides whether a browser FPS feels playable.
- Separate the multiplayer experiment. The server folder documents a Deno/WebTransport dedicated server, including TLS requirements, command-line options, and work-in-progress status for game protocol pieces 14.
The repo also includes a Deno task for a server entry point and imports that shim Three.js for server-side use 15. That does not mean the whole multiplayer stack is finished. The server README explicitly marks QuakeC VM integration, entity synchronization, physics simulation, and the complete game protocol as unfinished 16.
The failure mode is the lesson
The public tweet says "one hour later". The build-process comment says the first attempt ran away after a couple of days, the successful attempt used a 1:1 file port, and the process was "very on-hands" because mrdoob could not find a way for Claude to keep going until the job was finished 5.
That is the honest boundary of this case. Claude helped move a large, old FPS codebase into a modern browser graphics stack. It did not replace the person who knew how to notice when the architecture was slipping.
Paul Sawaya's LinkedIn read of the project makes the same point from a game-developer angle: Claude Code in mrdoob's hands is a different tool than Claude Code in a junior developer's hands, and old engines with well-understood file formats or APIs may be especially good AI-porting targets 17.
Cargando tarjeta de contenido…
For AI game developers, that is a stronger takeaway than the viral framing. The win was not that Claude understood "make Quake". The win was that the task had enough pre-existing structure for Claude to operate inside.
What to copy in your own AI game port
If you are using Claude, GPT, Gemini, or another coding model to build a playable game, copy the constraints rather than the spectacle.
- Start from a reference architecture when you can. A known engine, sample game, or older codebase gives the model a durable target. Blank-page prompts are more likely to drift.
- Port file-by-file, not feature-by-feature. Features invite the model to invent shortcuts. Files expose missing work.
- Keep data formats concrete. BSP, PAK, map, sprite, level, and config formats should be named and parsed, not waved away.
- Make the render shim narrow. Map old engine concepts onto your browser/game-engine layer through explicit adapters.
- Budget for hands-on steering. This case does not support "press enter and wait". It supports "use the model to accelerate a structured port while a human reviews boundaries".
The reusable pattern is simple: AI works best when the human turns a vague game idea into a constrained transformation problem. In three-quake, the transformation was not "invent a shooter". It was "carry Quake's existing architecture into Three.js without losing the file-level trail".
Fuentes de referencia
- 1mrdoob's X dev log
- 2mrdoob/three-quake repository
- 3three-quake credits
- 4three-quake play link
- 5Reddit discussion comment by mrdoob
- 6three-quake assets note
- 7mainmenu.png in three-quake
- 8id Software Quake source
- 9three-quake source tree
- 10main.js entry point
- 11bspfile.js
- 12glquake.js
- 13in_web.js
- 14Three-Quake dedicated server README
- 15deno.json
- 16server status checklist
- 17Paul Sawaya on the Quake demo




Añade más opiniones o contexto en torno a este contenido.