# Vash Esports
[](https://github.com/VashSoftware/esports/actions/workflows/ci.yml)
[](https://github.com/VashSoftware/esports/actions/workflows/deploy.yml)
[](https://discord.gg/n3mZgWk)
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
- **Runtime:** [Bun](https://bun.sh)
- **Framework:** [SvelteKit](https://svelte.dev) + [Svelte 5](https://svelte.dev/docs/svelte/overview)
- **Database:** PostgreSQL + [Drizzle ORM](https://orm.drizzle.team)
- **Auth:** [Better Auth](https://better-auth.com) with osu! OAuth
- **Styling:** [Tailwind CSS 4](https://tailwindcss.com)
- **osu! Integration:** [bancho.js](https://bancho.js.org) (IRC) + osu! API v2
- **Discord:** [discord.js](https://discord.js.org)
- **Testing:** [Vitest](https://vitest.dev) (unit) + [Playwright](https://playwright.dev) (e2e)
- **Deploy:** Docker Compose on a single VM, CI/CD via GitHub Actions
## Getting Started
### Prerequisites
- [Bun](https://bun.sh) (v1.3+)
- PostgreSQL 16+ (or Docker)
- An [osu! OAuth application](https://osu.ppy.sh/home/account/edit#new-oauth-application) with callback URL `http://localhost:5173/api/auth/oauth2/callback/osu`
- [osu! IRC credentials](https://osu.ppy.sh/p/irc)
- A [Discord bot](https://discord.com/developers/applications) with a token and channel ID
- [Cloudflare R2](https://developers.cloudflare.com/r2/) bucket for image storage
### Setup
```sh
git clone https://github.com/VashSoftware/esports.git
cd esports
cp .env.example .env
```
Edit `.env` with your credentials:
```sh
# Database — use Docker or your own Postgres instance
DATABASE_URL="postgresql://vash:password@localhost:5432/vash"
# App
ORIGIN="http://localhost:5173"
BETTER_AUTH_SECRET=""
ROOT_ADMIN_EMAIL="@osu.local"
# osu!
OSU_CLIENT_ID=""
OSU_CLIENT_SECRET=""
OSU_IRC_USERNAME=""
OSU_IRC_PASSWORD=""
# Discord
DISCORD_BOT_TOKEN=""
DISCORD_MATCH_CHANNEL_ID=""
# Cloudflare R2
R2_ACCOUNT_ID=""
R2_ACCESS_KEY_ID=""
R2_SECRET_ACCESS_KEY=""
R2_BUCKET="vash-esports-images"
R2_PUBLIC_URL="https://cdn.esports.vash.software"
```
If you don't have Postgres installed, start one with Docker:
```sh
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:
```sh
bun install
bunx drizzle-kit push
```
Start the dev server:
```sh
bun run dev
```
The app will be running at [http://localhost:5173](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.
```sh
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](https://www.conventionalcommits.org/) 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.