2026-02-27 16:23:27 +01:00
2026-03-13 14:30:06 -04:00
2026-03-13 18:09:10 +01:00
2026-03-13 17:15:04 +01:00
2026-03-01 03:06:37 +01:00
2026-03-07 17:31:08 +01:00
2026-03-15 17:49:14 +01:00
2026-03-13 16:52:12 +01:00
2026-03-15 17:49:14 +01:00
2026-02-27 16:23:27 +01:00
2026-02-27 16:23:27 +01:00
2026-03-13 17:07:06 +01:00
2026-02-27 16:23:27 +01:00
2026-03-13 17:15:04 +01:00
2026-03-13 16:52:12 +01:00
2026-03-13 16:47:47 -04:00
2026-02-27 16:23:27 +01:00

Vash Esports

CI Deploy Discord

An automated osu! matchmaking platform. Players queue up, get matched by ELO, and play fully automated multiplayer matches — lobby creation, map picking, score tracking, and rating updates all happen without referees.

Features

  • Ranked queue — ELO-based matchmaking with automatic mappool selection by skill level
  • Automated matches — lobbies are created in osu! via IRC, maps are picked/banned through chat commands, scores are collected automatically
  • Match engine — full state machine (lobby → rolling → picking → playing → results) with configurable best-of formats and team sizes
  • Beatmap pools — create and manage mappools with standard categories (NM, HD, HR, DT, FM, TB)
  • Teams — create teams, manage rosters, track team stats
  • Leaderboard — player and team rankings with high score tracking
  • Admin panel — user management, role assignment, match oversight
  • Discord notifications — match results posted to your Discord server

Tech Stack

Getting Started

Prerequisites

Setup

git clone https://github.com/VashSoftware/esports.git
cd esports
cp .env.example .env

Edit .env with your credentials:

# Database — use Docker or your own Postgres instance
DATABASE_URL="postgresql://vash:password@localhost:5432/vash"

# App
ORIGIN="http://localhost:5173"
BETTER_AUTH_SECRET="<run: openssl rand -hex 32>"
ROOT_ADMIN_EMAIL="<your-osu-user-id>@osu.local"

# osu!
OSU_CLIENT_ID="<from osu settings>"
OSU_CLIENT_SECRET="<from osu settings>"
OSU_IRC_USERNAME="<your osu username>"
OSU_IRC_PASSWORD="<from osu IRC settings>"

# Discord
DISCORD_BOT_TOKEN="<your bot token>"
DISCORD_MATCH_CHANNEL_ID="<channel id for match notifications>"

# Cloudflare R2
R2_ACCOUNT_ID="<cloudflare account id>"
R2_ACCESS_KEY_ID="<r2 api token access key>"
R2_SECRET_ACCESS_KEY="<r2 api token secret>"
R2_BUCKET="vash-esports-images"
R2_PUBLIC_URL="https://cdn.esports.vash.software"

If you don't have Postgres installed, start one with Docker:

docker run -d --name esports-db \
  -e POSTGRES_DB=vash \
  -e POSTGRES_USER=vash \
  -e POSTGRES_PASSWORD=password \
  -p 5432:5432 \
  postgres:17

Install dependencies and push the database schema:

bun install
bunx drizzle-kit push

Start the dev server:

bun run dev

The app will be running at http://localhost:5173.

Scripts

Command Description
bun run dev Start dev server
bun run build Production build
bun run check Type-check with svelte-check
bun run lint Lint with Prettier + ESLint
bun run test:unit Run unit tests (Vitest)
bun run test:e2e Run e2e tests (Playwright)
bun run test Run all tests
bun run db:push Push schema changes to database
bun run db:studio Open Drizzle Studio (database GUI)

Project Structure

src/
  lib/
    server/
      match/
        engine.ts       # Match state machine and ELO calculations
        orchestrator.ts  # IRC lobby lifecycle (create, pick, play, results)
        queue.ts         # Ranked queue and matchmaking logic
        rating.ts        # ELO rating system
      db/
        schema.ts        # Drizzle database schema
      osu.ts             # osu! API v2 client
      auth.ts            # Better Auth configuration
  routes/
    (app)/
      matches/           # Match browser and live match view
      mappools/          # Mappool creation and management
      teams/             # Team browser and management
      leaderboard/       # Player and team rankings
      admin/             # Admin panel

Deployment

The app deploys via Docker Compose to a single VM. Merges to staging and prod branches trigger automatic deployments through GitHub Actions.

docker compose build
docker compose up -d
docker compose exec app bunx drizzle-kit push --force

See docker-compose.yml for the full production setup and docker-compose.staging.yml for the staging environment.

Contributing

This project uses conventional commits enforced by git hooks:

feat: add new feature
fix: fix a bug
chore: maintenance task
refactor: code restructuring
docs: documentation changes

Pre-commit hooks run Prettier and ESLint on staged files. Pre-push hooks run type-checking and unit tests.

License

All rights reserved. This source code is publicly available for reference and educational purposes. See the project maintainers for contribution or usage inquiries.

Description
The best way to play competitively
Readme 4.5 MiB
Languages
TypeScript 69.6%
Svelte 27.9%
PowerShell 1.3%
Shell 0.4%
CSS 0.4%
Other 0.3%