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
Can't decide? Spin for it. Free games and group tools you play together in one room.
GamesTypeScript · PLpgSQLGitHub @TejuBorichaOnlineOwner 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
Loading the full README. The saved excerpt is shown below.
A party/game-room web app: 14 standalone single-player tools plus a
Supabase-backed multiplayer room feature (chat, live participants, shared
activities synced in real time).
Every tool below works standalone (single-player, at /tools/) and as
a synced multiplayer activity inside a room (/room/[code]):
Two additional room modes bundle several of the above into one room:
Party Mode (all games unlocked) and Classroom (teacher-friendly picks/teams).
Beyond the games themselves, every multiplayer room includes:Read the full README ↗A party/game-room web app: 14 standalone single-player tools plus a Supabase-backed multiplayer room feature (chat, live participants, shared activities synced in real time).
Every tool below works standalone (single-player, at /tools/<name>) and as
a synced multiplayer activity inside a room (/room/[code]):
| Game | Description |
|---|---|
| Team Maker | Build balanced teams instantly |
| Lucky Wheel | Physics-based 3D spinning wheel |
| Name Draw | Random winner picker, with elimination mode |
| Tournament | Single/double elimination and round-robin brackets |
| Coin Flip | Flip a coin, settle debates |
| Dice Roller | Roll custom dice sets |
| Guess Number | Number guessing game with live hints |
| Rock Paper Scissors | Classic showdown with synchronized reveals |
| Truth or Dare | Party question/dare draws |
| Would You Rather | Vote on impossible choices |
| Never Have I Ever | Icebreaker confessions |
| Trivia | Multiple-choice trivia, race to the top score |
| Bingo | Classic number bingo, call and mark |
| Word Scramble | Unscramble the word before anyone else |
Two additional room modes bundle several of the above into one room: Party Mode (all games unlocked) and Classroom (teacher-friendly picks/teams).
Beyond the games themselves, every multiplayer room includes:
@supabase/supabase-js) for multiplayer realtime sync — client-side only, no server/API routes@base-ui/react, vaul)npm install
cp .env.example .env.local # fill in your Supabase project URL + anon key
npm run dev
Open http://localhost:3000.
The multiplayer room feature needs a Supabase project. Without one
configured, the app still runs — rooms fall back to a same-browser-tab demo
mode via BroadcastChannel (see src/lib/supabase/client.ts), which does
not sync across different devices/users.
To enable real multiplayer:
.env.local (see .env.example).supabase/migrations/ in order (61 files as of
this writing) via supabase db push (or supabase link once, then
supabase db push) — this creates the full schema (rooms,
room_participants, chat_messages, moderation, scoring/XP, tournament
state, etc.), enables Row Level Security, and turns on realtime. On
main, .github/workflows/deploy.yml pushes any new migration files
automatically on every push that touches supabase/migrations/** — see
Deployment for the secrets it needs.Spintra uses Supabase Anonymous Auth: each client gets a real
auth.users row (no email/password), and RLS/trigger policies key off
auth.uid() rather than a client-supplied identity. See
supabase/migrations/0001_init_schema_and_rls.sql for the baseline policy
set and later migrations for the moderation/scoring/host-election hardening
built on top of it.
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | For real multiplayer | Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY | For real multiplayer | Supabase anon public key |
NEXT_PUBLIC_SENTRY_DSN | Optional | Error monitoring. Without it, Sentry never initializes (see sentry.*.config.ts) — the app runs exactly the same |
SENTRY_ORG / SENTRY_PROJECT / SENTRY_AUTH_TOKEN | Optional | Only needed to upload source maps for readable production stack traces |
NEXT_PUBLIC_GA_MEASUREMENT_ID | Optional | Google Analytics (GA4). Without it, gtag.js never loads (see src/app/layout.tsx) and the CSP stays unchanged (see next.config.ts) |
| Command | Description |
|---|---|
npm run dev | Start the dev server. For the one preview link of a session use npm run dev -- -p 3200 -H 127.0.0.1 (http://127.0.0.1:3200): it follows the checked-out branch and reloads on every edit |
npm run build | Production build |
npm run start | Serve the production build |
npm run lint | ESLint |
npm run typecheck | tsc --noEmit |
npm run docs:check | Verify docs/ hasn't drifted from the real filesystem |
npm run verify:static | typecheck + lint + docs:check: the static checks that need no network |
npm run verify | verify:static + audit (the static gates CI runs first, so a red dependency audit shows up before the push; the audit needs the network, so it comes last; offline use verify:static and say the audit was not run) |
npm run verify:migration [name] | Confirms a migration's objects actually exist live in the linked Supabase project (not just tracked as "applied") — run after every supabase db push |
npm run test:smoke | Playwright smoke test (room create/join flow): the whole suite |
npm run test:related | Only the Playwright specs that cover the files changed since main (the whole suite for anything it cannot place: shared code, configuration, migrations, dependencies). -- --list shows the plan, -- --full forces everything, Playwright options go after a second --. It runs against this checkout's own preview server if one is running (found through .next/dev/lock), otherwise Playwright builds and starts its own. CI runs the whole suite on every pull request |
npm run test:city-regression | Spintra City release-blocker regression suite — asserts the fixed behaviour for each open blocker, so it stays red until the fix lands. Requires the local Supabase stack. |
npm run audit |
src/app/tools/* standalone single-player game/utility pages
src/app/room/[code]/ multiplayer room (chat, participants, header)
src/app/room/[code]/activities/ per-game room UI, one file per game
src/app/room/[code]/components/ moderation dashboard, scoreboard, room settings
src/app/create/ room creation flow
src/app/explore/ public room discovery / browse
src/app/settings/ user preferences (username, theme, etc.)
src/app/api/health/ liveness endpoint for uptime monitors / deploy checks
src/lib/games.ts single source of truth for the game catalog
src/lib/supabase/client.ts browser Supabase client (returns null if unconfigured)
src/lib/room-user.ts client-side identity, backed by Supabase Anonymous Auth
src/lib/moderation.ts moderation RPC client wrappers (kick/ban/dismiss)
src/lib/xp.ts XP/rank tier calculations
src/lib/tournament-engine.ts bracket generation for all 4 tournament formats
proxy.ts redirects /room?code=X to /room/X
supabase/migrations/ schema + RLS for the Supabase-backed tables
This Next.js version has breaking changes vs. older docs/training data — see
AGENTS.mdandnode_modules/next/dist/docs/before assuming an API works the way you remember. Notably, the routing hook file isproxy.ts(Next 16 renamedmiddleware.ts), notmiddleware.ts.
Playwright specs in tests/: smoke.spec.ts and comprehensive-smoke.spec.ts
(room create/join flow), multiplayer-loop.spec.ts (two genuinely distinct
participants — join, activity sync, moderation), comprehensive-tournament-audit.spec.ts
and tournament-double-elimination.spec.ts (bracket generation and scoring
across all formats).
.github/workflows/ci.yml runs two jobs once per pull request head (and once on main after a merge; a newer push to a pull request cancels the older run, and a branch without a pull request runs nothing): validate (dependency
security audit, typecheck, lint, docs drift check, build, and the Playwright
suite against the demo/BroadcastChannel fallback — no Supabase needed) and
db-integration (spins up an ephemeral local Supabase via Docker, applies
every migration fresh, and re-runs the suite against real RLS/triggers/realtime
instead of the demo fallback).
.github/workflows/db-backup.yml, deploy.yml) require repo secrets
that aren't configured yet — see Deployment.NEXT_PUBLIC_SENTRY_DSN configured yet).Any Next.js host works (e.g. Vercel). Set the
NEXT_PUBLIC_SUPABASE_* (and optionally NEXT_PUBLIC_SENTRY_DSN/SENTRY_*)
environment variables in your hosting provider's dashboard before deploying.
Two GitHub Actions workflows handle Supabase-side operations and need repo secrets to function:
| Workflow | Trigger | Required secrets |
|---|---|---|
deploy.yml | Push to main touching supabase/migrations/** (or manual dispatch) | SUPABASE_ACCESS_TOKEN, SUPABASE_DB_PASSWORD, SUPABASE_PROJECT_ID |
db-backup.yml | Twice a day, 03:00 and 15:00 UTC (+ manual dispatch) | SUPABASE_DB_URL, AWS_BACKUP_ACCESS_KEY_ID, AWS_BACKUP_SECRET_ACCESS_KEY, AWS_BACKUP_S3_BUCKET, AWS_BACKUP_R2_ENDPOINT |
db-backup.yml uploads to Cloudflare R2 (S3-API-compatible, free tier,
zero egress fees) rather than real AWS S3 — AWS_BACKUP_R2_ENDPOINT is the
bucket's R2 endpoint URL, and the region is hardcoded to auto in the
workflow itself (R2's documented value, not a real AWS region).
Without these secrets set (gh secret set <NAME>), both workflows run but
fail every time — migrations must then be pushed manually
(supabase db push) and no backups are retained.
All rights reserved. This repository is source-available for portfolio and reference purposes only — reuse, modification, or redistribution of this code is not permitted without the author's permission.
node scripts/audit-gate.mjs --audit-level=moderate: npm audit at that threshold, plus a short time-boxed allowlist (scripts/audit-allowlist.json) for advisories that have no fix yet — the one place this threshold is set; .github/workflows/ci.yml's CI gate calls this same script rather than hardcoding its own |
npm run ci | verify (which includes the audit) + build + test:smoke (the full CI gate, locally) |