Architecture Overview
Band Game is a pnpm monorepo managed with Turborepo. It has four deployable applications and a shared packages directory.
Monorepo Structure
text
band-game/
apps/
server/ NestJS backend (REST + Socket.IO)
client/ React Native / Expo app (iOS, Android, web)
band-game-admin/ Next.js admin dashboard
wiki/ This documentation site (VitePress)
packages/ Shared packages (reserved, currently empty)
turbo.json Turborepo pipeline config
pnpm-workspace.yamlTech Stack
| Layer | Technology | Notes |
|---|---|---|
| Package manager | pnpm 8.15+ | Workspaces enabled |
| Build orchestration | Turborepo | Shared dev, build, lint, test tasks |
| Backend | NestJS 11 (TypeScript) | Node.js 18+, WebSocket gateway via Socket.IO |
| Mobile/web client | React Native + Expo 55 | Expo Router for file-based routing |
| Admin dashboard | Next.js 15 + React 19 | Tailwind CSS |
| Database | PostgreSQL (via Neon) | Drizzle ORM, schema-first |
| Auth | Clerk | JWT validation on server, native SDK on client |
| Real-time | Socket.IO | Game state, matchmaking, presence events |
| External APIs | Spotify Web API | Band name validation and search |
| Push notifications | Expo Push | Token stored in pushTokens table |
| File storage | AWS S3 | Used by admin app |
Data Flow
text
Client (Expo)
│
├── REST (HTTP) ──────► NestJS Server ──► PostgreSQL (Drizzle ORM)
│ │
└── Socket.IO ───────────────────────────► Game gateway / Matchmaking gateway
│
└──► Spotify API (band validation)
Admin (Next.js)
│
└── REST (HTTP) / Next API routes ──────► NestJS Server
└──► AWS S3Application Summaries
apps/server — NestJS Backend
The core API and real-time server. Handles all game logic, matchmaking, user data, XP, notifications, and Spotify integration. See Server Modules for a module breakdown.
apps/client — Expo Mobile/Web App
Cross-platform client for iOS, Android, and web. Uses Expo Router for navigation, Clerk for auth, and Socket.IO for real-time game state. See Client for screen structure.
apps/band-game-admin — Next.js Admin Dashboard
Internal tool for managing app configuration, reward events, and game settings. Protected by Clerk. Talks to the NestJS server via REST.
Database
PostgreSQL is hosted on Neon (serverless Postgres). Schema is managed with Drizzle ORM. Migrations live at apps/server/neon/.
Tables: matches, bands, friends, friendInvitations, challenges, appConfig, userXp, rewardEvents, items, userItems, pushTokens
See Server — Database Schema for field-level detail.
Authentication
Clerk manages user identity. The server validates Clerk JWTs in the auth module. The client uses the Clerk Expo SDK for sign-in/sign-up flows and attaches tokens to every request.
See Authentication for the full breakdown: ClerkAuthGuard per-controller, no global auth guard, WebSocket identity via identify event (no JWT on socket), admin key guard for config endpoints.
See Environment Variables for the complete per-app list.
See Deployment & Infrastructure for hosting, Railway config, EAS builds, and the full external services map.
Redis: Not used yet. The matchmaking queue, player presence, and game state cache are all in-memory (Map-based) — data is lost on server restart. See Roadmap — Redis-Backed Presence & Matchmaking Queues and Roadmap — BullMQ-Backed Turn Timers for the planned migration.