Run with the pack. Dash to the top.
Multiplayer endless runner built for Twitch streamers and their communities.
You're a wolf. The obstacles don't care. Your chat is watching.
FangDash drops up to four players into the same procedurally generated gauntlet — same seed, same layout, zero excuses. Race your mods, race your viewers, or race solo to chase a personal best. Earn skins, rack up achievements, and watch your name climb the leaderboard while you're live.
- Endless Runner — Jump, slide, and dash through procedurally generated obstacle courses. The further you run, the faster it gets.
- Real-Time Multiplayer — Up to 4 players race the same seeded layout simultaneously over WebSockets. Everyone sees the same course — fairness is non-negotiable.
- Twitch-Native — Sign in with Twitch, invite your chat, and let your community race you live on stream.
- 6 Wolf Skins — Start as a Gray Wolf and unlock your way up to the MrDemonWolf skin through milestones.
- 16 Achievements — Spanning score, distance, games played, skill plays, and social categories.
- Leaderboards with Anti-Cheat — Server-validated scores with per-difficulty and time-period filters (daily / weekly / all-time).
- Difficulty Ramping — Speed scales from 300 to 800 px/s as obstacle gaps tighten around you.
- Deterministic Seeds — Seeded PRNG means every racer faces the exact same obstacle layout. No luck, only skill.
- Audio System — BGM crossfade, SFX, and per-category volume controls.
- PWA — Install it, play it offline, put it on your stream layout.
- Admin Dashboard — Player management, score moderation, and full race history.
- Clone the repository:
git clone https://github.com/MrDemonWolf/fangdash.git
cd fangdash- Install dependencies:
bun install- Set up environment variables:
cp apps/api/.dev.vars.example apps/api/.dev.vars
cp apps/web/.env.local.example apps/web/.env.local- Start all services in development:
bun devThe web app runs at http://localhost:3000 and the API at
http://localhost:8787. The docs site runs at http://localhost:3001.
| Layer | Technology |
|---|---|
| Frontend | Next.js 15, React 19, Tailwind v4 |
| Game Engine | Phaser 3 |
| API | Hono on Cloudflare Workers |
| Database | Cloudflare D1 (SQLite) + Drizzle ORM |
| Auth | Better Auth with Twitch OAuth |
| API Layer | tRPC v11 |
| Multiplayer | PartyKit (WebSockets) |
| Monorepo | Turborepo + bun workspaces |
| Docs | Fumadocs + Next.js |
| Testing | Vitest |
| CI/CD | GitHub Actions + Cloudflare Workers |
| Language | TypeScript 5.7 (strict mode) |
- Node.js >= 20
- Bun >= 1.0 (see bun.sh for installation)
- Cloudflare account (for D1 database and Workers deploys)
- Twitch Developer application (for OAuth)
- Install dependencies:
bun install- Create a Cloudflare D1 database:
cd apps/api
bunx wrangler d1 create fangdash-db-
Update
apps/api/wrangler.tomlwith your D1 database ID. -
Run database migrations:
cd apps/api
bunx wrangler d1 migrations apply fangdash-db --local- Configure
apps/api/.dev.varswith your secrets:
BETTER_AUTH_SECRET=<your-secret>
BETTER_AUTH_URL=http://localhost:8787
TWITCH_CLIENT_ID=<your-twitch-client-id>
TWITCH_CLIENT_SECRET=<your-twitch-client-secret>
# Shared HMAC secret for short-lived PartyKit race connection tokens.
# Must match the value configured for the PartyKit server below.
RACE_TOKEN_SECRET=<your-race-token-secret>- Configure
apps/party/.env(loaded bypartykit dev) with the sameRACE_TOKEN_SECRETso the race server can verify tokens minted by the API:
RACE_TOKEN_SECRET=<your-race-token-secret>- Configure
apps/web/.env.local:
NEXT_PUBLIC_API_URL=http://localhost:8787- Start development:
bun devReal-time race connections are authenticated with a short-lived HMAC token, not
the Better Auth session cookie (which is httpOnly and therefore unreadable by
the client). The flow:
- The web client calls
race.getConnectionToken(tRPC) to mint a token signed over{ sub, exp }withRACE_TOKEN_SECRET. - The client forwards it to the PartyKit race server as the
?token=query param. A fresh token is minted on every (re)connect, so it can be short-lived (default 2 minutes). - The PartyKit server verifies the token with the same
RACE_TOKEN_SECRETand binds the connection to the authenticated user — no API round-trip.
RACE_TOKEN_SECRET must be identical across the API and the PartyKit server.
Generate one with openssl rand -hex 32. Provision it for production with:
# API (Cloudflare Worker secret)
cd apps/api && echo "<secret>" | bunx wrangler secret put RACE_TOKEN_SECRET --env production
# PartyKit server secret
cd apps/party && echo "<secret>" | bunx partykit secret put RACE_TOKEN_SECRETAlso add RACE_TOKEN_SECRET as a GitHub Actions repository secret — the deploy
workflow pushes it to both the Worker and PartyKit on each deploy.
bun dev— Start all apps in development mode.bun build— Build all packages and apps.bun test— Run all tests with Vitest.bun test:coverage— Run tests with coverage report.bun typecheck— Type-check all packages.bun lint— Lint all packages.bun clean— Remove all build artifacts.bun check— Run ESLint + Prettier check.bun format— Format all files with Prettier.bun format:check— Check formatting without writing.bun ship— Deploy API, web, and PartyKit to production.bun ship:api— Deploy API to Cloudflare Workers.bun ship:web— Deploy web app to Cloudflare Workers.bun ship:party— Deploy PartyKit server.bun --filter @fangdash/web generate:icons— Regenerate favicon and PWA icons from the wolf sprite (web + docs).
- Strict TypeScript with
strict: trueacross all packages. - Vitest for unit and integration testing.
- GitHub Actions CI runs typecheck, tests, lint, and format check on every PR.
- tRPC for end-to-end type safety between API and frontend.
fangdash/
├── apps/
│ ├── api/ # Hono API on Cloudflare Workers
│ ├── docs/ # Fumadocs documentation site
│ ├── party/ # PartyKit WebSocket server
│ └── web/ # Next.js frontend
├── packages/
│ ├── game/ # Phaser 3 game engine
│ └── shared/ # Types, constants, skins, achievements
├── .github/
│ └── workflows/ # CI and deploy pipelines
├── turbo.json # Turborepo task config
└── tsconfig.base.json # Shared TypeScript config
See CHANGELOG.md for the full release history, or visit fangdash.mrdemonwolf.workers.dev/changelog for the web version.
Have questions or feedback?
- Discord: Join my server
Made with love by MrDemonWolf, Inc.