Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
The world's largest online jigsaw puzzle: 1,000,000 pieces on one shared canvas, solved together in real time, free, with no download or account needed.
GamesTypeScript · VueGitHub @MillionPiecePuzzleOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The world's largest online jigsaw puzzle. One million pieces on a single shared board.
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
A community-built online jigsaw puzzle: 1,000,000 pieces on a single shared canvas, all shuffled from the start, solved together in real time. A long-form, non-commercial, open-source event with no time limit.
v1.4.2 is out: production serves the 1,000,000-piece earth-mosaic board ahead of the public event. Work is tracked in ROADMAP.md.Read the full README ↗A community-built online jigsaw puzzle: 1,000,000 pieces on a single shared canvas, all shuffled from the start, solved together in real time. A long-form, non-commercial, open-source event with no time limit.
Play at app.millionpiecepuzzle.com
v1.4.2 is out: production serves the 1,000,000-piece earth-mosaic board ahead of the public event. Work is tracked in ROADMAP.md.
Every player, guest or signed in, connects over a single WebSocket path. Past a global connection cap an admission queue holds new arrivals in a first-in-first-out wait, so the server sheds load into an orderly queue instead of accepting connections until it falls over.
A restart is announced rather than suffered: the server tells every connected player it is going down before it drops the sockets, and the app switches to a maintenance screen (served by Cloudflare Pages, so it survives the backend being gone) that reloads itself back into the board once the server answers again.
Piece events are tiered by cost:
| Event | Scope |
|---|---|
| Drag | Broadcast to viewport-neighbor clients, never persisted |
| Drop | Redis write, viewport broadcast |
| Snap | Redis write, Mongo log, global broadcast |
Pieces belong to clusters. Every piece starts as its own cluster; when two pieces of compatible neighboring positions meet at the correct relative offset, their clusters merge and their relative positions freeze. Grabbing any piece grabs its whole cluster, and the wire format carries one absolute position plus a group id rather than N piece positions.
The puzzle frame is the anchor. A cluster locks permanently when a human drop brings its origin within snap tolerance of the frame origin, or when it merges with an already locked cluster. Locked pieces never move again: no undo, no griefing.
Piece geometry is neither stored nor sent. Bezier silhouettes and canonical offsets derive from a server-only generation seed and are baked into each pre-masked tile by the slicer. The client renders from those tiles plus per-piece offsets, so it never holds anything a solver could use.
The source image carries no AI-generated content, a community commitment.
@auth/express, Google), database sessions, internal per-IP login rate limitingpackages/
shared/ # Shared TypeScript types (WS messages, piece and user schemas)
frontend/ # Vue + PixiJS + OpenSeadragon
server/ # Node + WebSocket + Redis/Mongo handlers
load-test/ # WS load/soak harness (bots + admission gate)
git clone https://github.com/MillionPiecePuzzle/million-piece-puzzle.git
cd million-piece-puzzle
npm install
cp .env.example .env
docker compose up --build -d
Frontend on http://localhost:5173, WebSocket server on ws://localhost:8080/, anonymous landing data on http://localhost:8080/landing, http://localhost:8080/live and http://localhost:8080/interested.
.env is gitignored and never committed. Fill it in before bringing the stack up:
AUTH_SECRET, a 32+ character random string, e.g. openssl rand -hex 32. Without it the /auth routes fail, so the SPA cannot read its session back and mints a fresh guest on every visit.AUTH_GOOGLE_ID and AUTH_GOOGLE_SECRET, from a Google OAuth client whose authorized redirect URI is http://localhost:8080/auth/callback/google. Without them the server still runs and guest play works end to end; only Google sign-in and guest claiming are unavailable.The non-secret auth config (AUTH_URL, AUTH_COOKIE_DOMAIN, MPP_APP_ORIGIN) has local defaults.
| Command | Purpose |
|---|---|
npm run build | Build shared, then server, then frontend |
npm run typecheck | Typecheck every workspace |
npm test | Run the Vitest suite |
npm run lint | ESLint over the monorepo |
npm run format | Prettier write |
npm run dev:frontend | Vite dev server, outside Docker |
npm run dev:server | Server in watch mode, outside Docker |
The image pipeline carries its own scripts (slice, mosaic, upload, validate:generation); see package.json.
The wire protocol (v10), schema, and gameplay are frozen for the public event. Code contributions are welcome, but please open an issue first to discuss the change before sending a pull request.
CLAUDE.md holds the working conventions, ROADMAP.md the tasks and their exit criteria, and DECISIONS.md the non-obvious trade-offs along with what would make each worth revisiting.
Bug reports and feedback go to GitHub Issues or the Discord.
MIT. See LICENSE.