How this site works.
No framework, no build step, no bundler for the page itself. It's plain HTML, CSS and JavaScript on GitHub Pages, plus one small Cloudflare Worker for the live bits. Here's what's under the hood, for the curious.
Boring tech, on purpose.
Every page is a static file. The JavaScript is ES5-style, one file per feature, each wrapped in its own scope. They talk through a tiny window.RW API (toast, confetti, terminal commands, an egg() event), so a feature can be added or deleted without touching the others.
| index.html | The whole page, hand-written and semantic, with JSON-LD for search engines and an llms.txt for AI agents. | ~860 lines |
| css/site.css | One stylesheet built on design tokens (--blue, --surface…). The terminal's theme command re-skins everything by swapping four of them. | ~16 KB gz |
| js/site.js | Nav, reveals, the typed hero, the GitHub squares, LeBronify, the Fetch player, the terminal, confetti, and the RW API the others use. | ~16 KB gz |
| js/eggs.js | Achievements and the trophy case, terminal tricks, end credits, Mile A Day mode, Gameday scores, the console note. | ~11 KB gz |
| js/live.js | Live cursors, the dot-matrix visitor map, the guestbook and the Letterboxd card. | ~10 KB gz |
| js/dog.js | The fetch game: a 3D dog from my game, a thrown logo, and physics. | ~8 KB gz |
| js/pool.js | Turns the About cards into a pool rack and breaks it. | ~9 KB gz |
| workers/live/ | A Cloudflare Worker and one SQLite-backed Durable Object: WebSockets, visit counts, the guestbook, a Letterboxd proxy. | ~420 lines |
Static page, live edges.
The page itself is static. Each live feature is a layer on top that fails quietly: if an API is down, you get the static version (a counted-up streak, an empty map, a link to GitHub) instead of an error.
One Durable Object, everyone's cursor.
Every visitor connects to the same Durable Object called "global". It uses Cloudflare's hibernation API, so an idle room costs nothing, and pings are answered without waking it up.
- Cursors go up about 15 times a second as fractions of the page, so they land in the right spot on any screen size. The server clamps, size-limits (200 bytes) and rate-limits (30/s) every message before relaying it, and the client smooths each one between updates.
- Location comes from Cloudflare's
request.cf: city, region and country, with latitude and longitude rounded to a tenth of a degree. No IP is ever stored or sent to anyone. - Visits are counted once per browser per day. The browser makes up a random id, and the server stores only a hash of that id plus the date, so it's useless by tomorrow.
- The map is
world-atlasland shapes, rasterized at 3× onto a hidden canvas, then sampled into a grid of rounded squares, the same visual language as the GitHub squares. - The guestbook takes plain text only (no links), one note per browser per day. Every note waits in a queue until I approve it.
Straight out of my game.
Type dog and one of the five dogs from Fetch runs onto the page. They're the game's own rigged models, put through a small pipeline to make them web-sized:
# 5–6 MB each → 300–700 KB: 512px WebP textures, quantized vertices gltf-transform optimize luna.glb assets/dogs/luna.glb \ --texture-compress webp --texture-size 512 --compress quantize # just the parts of three.js the dog needs, as one script (~145 KB gzipped) esbuild entry.js --bundle --minify --format=iife --global-name=RWThree
A camera in CSS pixels
An orthographic camera maps the WebGL strip 1:1 to the page, so the 2D fetch physics (gravity, bounces, the throw arc) didn't change at all. Only the drawing did.
The game's walk cycle
The rig's own animation blends in with speed and plays as fast as the dog is really moving. A procedural tail wag and a head that follows the ball sit on top.
A mouth socket
The logo rides an empty object parented to the head bone, placed using each dog's mouth_grip from the game's data, so it stays in their teeth mid-leap.
The About cards break.
Type break (I shoot in an APA league, so this one's personal). The cards fly into a 15-ball rack on a canvas felt, and the physics is real: equal-mass elastic collisions with overlap correction, 14 sub-steps per frame so fast balls don't tunnel through each other, cushions that bounce with damping, rolling friction and pocket mouths. Each ball is shaded by hand and its stripe rolls with it. When it settles, every card glides back to exactly where it was.
Every egg is an event.
Features call RW.egg('pool') and know nothing about achievements. eggs.js listens for rw:egg events, shows the Xbox-style popup and saves progress in localStorage. Finding all of them unlocks a phone wallpaper drawn on a canvas. Some of them:
vim traps you until you press Esc and type :wq.rob object waiting for you.Heavy stuff waits its turn.
Load on demand
three.js and a dog model download only on the first whistle. The Fetch game (Godot, WebAssembly) loads only when you press Play. The map waits until it's near the screen.
No idle loops
Every canvas animation (dog, pool, confetti, map pulses) stops its requestAnimationFrame loop when nothing's happening. An untouched page isn't redrawing anything.
Reduced motion
With prefers-reduced-motion on, the physics, confetti, pulses and wave effects step aside, and every egg still unlocks.
Green before it ships.
With this much going on, a small change can quietly break something three sections away. Every pull request runs a GitHub Actions job: Playwright drives the real page in Chromium at desktop and phone sizes, with every outside API mocked. It checks for script errors, sideways scrolling, terminal commands, achievements, the pool break and the dog cleaning up after themselves, and the live features. A Lighthouse run keeps an eye on performance and accessibility.
Curious, not creepy.
No cookies, no ad trackers, no analytics scripts. The Worker keeps visit counts by city, the site that linked you here (just the domain, never the full address), and tags I add to links I send out, like ?r=acme on an application, so I know which ones got opened. Then it tidies that tag out of your address bar. Everything else lives in your own browser's storage.
Claude Code, GitHub Pages, Cloudflare Workers, three.js, gltf-transform, Playwright, Font Awesome, and Saira, Inter and JetBrains Mono. Designed and built in South Jersey.
Back to the site Read the source