Skip to content

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.yaml

Tech Stack

LayerTechnologyNotes
Package managerpnpm 8.15+Workspaces enabled
Build orchestrationTurborepoShared dev, build, lint, test tasks
BackendNestJS 11 (TypeScript)Node.js 18+, WebSocket gateway via Socket.IO
Mobile/web clientReact Native + Expo 55Expo Router for file-based routing
Admin dashboardNext.js 15 + React 19Tailwind CSS
DatabasePostgreSQL (via Neon)Drizzle ORM, schema-first
AuthClerkJWT validation on server, native SDK on client
Real-timeSocket.IOGame state, matchmaking, presence events
External APIsSpotify Web APIBand name validation and search
Push notificationsExpo PushToken stored in pushTokens table
File storageAWS S3Used 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 S3

Application 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.