Implement the following plan:
XKCD 2347 Jenga Game
A browser-based 2D physics Jenga game styled after XKCD 2347 ("Dependency"). A tower of blocks representing software dependencies, with one tiny "Nebraska" block near the base holding everything up. You drag blocks out with your mouse and watch the tower (hopefully not) collapse. Hosted on GitHub Pages -- pure static files, no build step.
Tech Stack
- Matter.js (CDN) -- 2D physics engine. Has built-in
MouseConstraint for drag interaction, Composites.stack() for building block towers, and sleeping support for stable stacking. Best option for this use case by a wide margin over Planck.js or p2.js.
- Rough.js (CDN) -- Hand-drawn rendering library. Draws rectangles/lines with a wobbly sketch style that matches the XKCD aesthetic. Uses
seed per shape for consistent strokes across frames.
- xkcd-script font -- The handwriting font from ipython/xkcd-font repo, loaded via
@font-face.
- No npm, no build tools, no inline styles or scripts.
File Structure
index.html -- canvas, overlays, CDN script tags
css/style.css -- layout, @font-face, overlay styling
js/game.js -- all game logic
fonts/xkcd-script.woff2 -- hand-drawn font
Game Design
Tower layout: Mirrors the comic's shape. A wide messy mass of blocks at top ("All modern digital infrastructure") narrows toward the bottom, until one tiny block near the base is labeled "A project some random person in Nebraska has been mass maintaining since 2003". Blocks are labeled with real dependency names (OpenSSL, zlib, curl, SQLite, etc.) and end-user systems (Your bank, GPS, Email, etc.).
Interaction: Click and drag blocks to pull them out. Low stiffness on the mouse constraint (0.2) so it feels like tugging a block from a tight stack rather than teleporting it.
Collapse detection: After releasing a dragged block, monitor the tower for a few seconds. If blocks fall significantly from their original positions or leave the canvas, declare collapse.
Messages:
- On collapse: "You removed [block label]! Everything that depended on it came crashing down." with a list of fallen blocks.
- On successful removal: "Somehow, everything still works. Nobody knows why."
- Score: count of blocks removed before collapse.
- Reset button to rebuild.
Physics tuning: High friction (0.8), high static friction (1.2), very low restitution (0.05), sleeping enabled. Tower built bottom-up with careful positioning so it starts stable.
Rendering: Custom requestAnimationFrame loop that reads body positions from Matter.js and draws them through Rough.js. Each block uses seed: body.id for consistent hand-drawn strokes. Text labels in xkcd-script font. An annotation arrow pointing to the Nebraska block like the original comic.
Implementation Steps
- Set up
index.html, css/style.css with font loading, canvas layout, overlay markup
- Download xkcd-script font to
fonts/
- Build
js/game.js: Matter.js engine, world, ground, mouse constraint
- Define block data (positions, sizes, labels, tiers) and create the tower
- Replace default renderer with custom Rough.js drawing loop
- Implement drag tracking, collapse detection, and UI messages
- Add reset functionality, score counter, annotation arrow
- Test in browser, tune physics parameters until tower is stable but removable
Verification
- Open
index.html in a browser (or serve with python3 -m http.server)
- Tower should stand stable on load
- Dragging a non-critical block should sometimes succeed without collapse
- Dragging the Nebraska block should almost always cause collapse
- Reset button should rebuild the tower
- Works on GitHub Pages (all paths relative, no server-side dependencies)
If you need specific details from before exiting plan mode (like exact code snippets, error messages, or content you generated), read the full transcript at: /Users/andrew/.claude/projects/-Users-andrew-code-xkcd-2347/81aac8c4-a31c-4d6d-8379-c4ec870a84fa.jsonl