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
Free browser simulator for the Unmatched board game. Play homebrew fan decks head-to-head — no account, no install. Imports from unmatched.cards, the-unmatched.club, and Tabletop Simulator.
GamesTypeScript · JavaScriptGitHub @JollyGrinOnlineOwner 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
Refactoring unbrewed with next 13 & typescript
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Play your favorite Unmatched fan decks online with friends — all you need is a browser.
John Wick vs King Kong, live over websocket. Hover a card to read it, drag tokens around any map.
Unmatched has a thriving homebrew community designing custom decks on unmatched.cards — but playtesting them used to mean printing cards or wrestling with Tabletop Simulator. Unbrewed is a free, open-source virtual tabletop built just for that:Read the full README ↗Play your favorite Unmatched fan decks online with friends — all you need is a browser.
John Wick vs King Kong, live over websocket. Hover a card to read it, drag tokens around any map.
Unmatched has a thriving homebrew community designing custom decks on unmatched.cards — but playtesting them used to mean printing cards or wrestling with Tabletop Simulator. Unbrewed is a free, open-source virtual tabletop built just for that:
Unbrewed is a fan-made hobby project and is not owned by or associated with Restoration Games, LLC.
| Load up your bag | Connect in three steps |
|---|---|
| The Bag — collect decks & maps, star your favorites | Connect — pick a deck, name a lobby, share it with a friend |
A default gameserver is already live, so most players never need to run anything.
# 1. build the Go gameserver
cd gameserver && go build && cd ..
# 2. start the gameserver (ws relay on :1111)
yarn server
# 3. in another terminal, start the web app
yarn install
yarn dev
Open http://localhost:3000, then point the app at your local server on the settings page (http://localhost:1111).
You can run the server on your own machine — free, and independent of Unbrewed's servers ever going offline:
cd gameserver && go buildcd ../ && yarn server — relay now running on localhost:1111yarn grok and copy the public URL it printsWant to run a 24/7 public server for the community? Open an issue or PR so we can add it to the default server list. (Dockerfile.gameserver is included if you like containers — it's what the default relay on Railway builds from.)
The relay can report sandbox room/player lifecycle events (room_opened, player_joined, player_left, hero_seen, room_closed) to unbrewed-telemetry at POST /v1/sandbox-events. It is off unless all three are set; with any unset the relay behaves exactly as before and makes no outbound requests:
| env var | what |
|---|---|
SANDBOX_TELEMETRY_URL | telemetry base URL (events go to {URL}/v1/sandbox-events) |
SANDBOX_TELEMETRY_KEY | bearer credential with the sandbox:submit scope |
SANDBOX_NAME_SALT | secret HMAC salt for player names and lobby names. Required when the other two are set (without it telemetry stays off and the relay logs an error). Player names only leave the relay as a 16-hex playerHash, and lobby names only as lobbyHash on room_opened. Each room sitting is identified by a fresh uuid roomId, because lobby names get reused. |
Events are buffered and posted in batches (every 30s or 200 events), never on the game path: a slow or down telemetry server drops events, it never delays play. With telemetry on, on SIGTERM the relay reports open rooms as room_closed (reason: shutdown) and flushes for up to 3s.
Deploy order: telemetry live and a sandbox:submit credential issued → set SANDBOX_TELEMETRY_URL, SANDBOX_TELEMETRY_KEY, SANDBOX_NAME_SALT on Railway → deploy the relay.
Set ADMIN_KEY and the relay serves a live room monitor on its main port: GET /view (HTML, auto-refreshes every 10s) and GET /view.json. It lists every open room, newest activity first, by lobby name and by its telemetry roomId (to match a row on telemetry.unbrewed.xyz's Sandbox tab), with the room's peakConnections/stateUpdates (plus distinctPlayers and heroesSeen while telemetry is on), and each player who joined, their Discord username and account id while connected (unverified labels the client sends, from the newest connection), their deck/hero/author, zone counts (deck, hand, discard; never card names), and whether they're still connected (×2 = two tabs/devices) or have left. With ADMIN_KEY unset both routes return 404. State is in memory and resets on deploy.
Auth is HTTP Basic: any username, password = ADMIN_KEY. On Railway, add ADMIN_KEY under the relay service's Variables tab (it redeploys), then open https://unbrewed-relay-production.up.railway.app/view and enter the key as the password when the browser prompts. From a shell:
curl -u admin:$ADMIN_KEY https://unbrewed-relay-production.up.railway.app/view.json
flowchart LR
subgraph "Player A's browser"
A["Next.js static app<br/>decks & maps in localStorage"]
end
subgraph "Player B's browser"
B["Next.js static app<br/>decks & maps in localStorage"]
end
S["Go gameserver<br/>(tiny websocket relay,<br/>rooms in memory)"]
A <-- "playerstate / playerposition" --> S
S <-- "playerstate / playerposition" --> B
The server holds no game logic and no database — it just relays each player's state to everyone in the room. All deck data stays in the browser, and the client exports as a fully static site (it runs on GitHub Pages). If unmatched.cards or the default server ever disappear, any static host + one Go binary keeps the game alive.
Unbrewed uses Next.js static export, so your fork can run on GitHub Pages. Since Pages serves from https://username.github.io/repo/, update the repo name in the build steps:
lib/buildTools/prefixFonts.js — replace unbrewed-p2p with your fork's repo namenext.config.js — use NODE_ENV to set the production basePath to your repo namePRs, forks, and feature requests through the issue tracker are all welcome! Come say hi on Discord.
yarn testpublic/fontsstyles/fonts.cssstyles/styles.tslib/buildTools/prefixFonts.js to add another HTML match for fixing production links (GitHub Pages puts the repo name in the URL)