EVA Balancer pulls real player statistics from EVA's API and uses a brute-force algorithm to split players into two teams with the minimum possible KDA difference — creating the fairest matches possible.
Built for the Bahrain EVA community by the community.
- Booking Import — Paste an EVA booking link, automatically imports all players with live stats and balances them instantly
- Live Stats — Fetches KDA, level, games played, and win rate directly from EVA's GraphQL API
- Smart Balancing — Brute-force combinatorial optimization finds the mathematically optimal team split
- Weighted Mode — Balance by KDA alone, or use a composite score (60% KDA + 25% Win Rate + 15% Level)
- Season Selector — Switch between Season 6, 7, and 8 stats on the fly
- Private Profile Detection — Flags players with private stats and prompts for manual entry
- Balance History — Past results saved locally, browse and reload previous matchups
- Share Links — Generate a URL to share balanced team results with your squad
- Refresh All — One-click refresh of every player's stats from the API
- Manual Editing — Override any player's KDA, level, or game count
- Mobile Friendly — Responsive design with sticky action bar for mobile use
- Node.js 18+
- PostgreSQL database (or use SQLite locally — see below)
# Clone
git clone https://github.com/Meowkai123/EVA-BALANCER.git
cd EVA-BALANCER
# Install
npm install
# Configure
cp .env.example .env
# Edit .env with your DATABASE_URL
# Database
npx prisma migrate dev --name init
# Run
npm run devOpen http://localhost:3000.
| Variable | Description | Example |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | postgresql://user:pass@host:5432/db |
If you don't have PostgreSQL, change prisma/schema.prisma:
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}Then run npx prisma migrate dev --name init.
- Add players individually by username (e.g.
PLAYER#1234), or - Import a booking — paste an EVA booking URL to pull in everyone at once
- Select players (up to 10) and hit Balance Squad
- Share the result with your squad via the Copy or Share button
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| Language | TypeScript 5 |
| Database | PostgreSQL via Prisma ORM |
| Styling | Tailwind CSS 4 |
| Data Source | EVA GraphQL API |
| Hosting | Render (Docker) |
app/
page.tsx # Main UI (single-page client component)
api/
players/ # CRUD for players (GET, POST, DELETE)
players/[id]/ # Update/delete individual player (PATCH, DELETE)
balance/ # Team balancing endpoint (POST)
import-booking/ # Extract players from EVA booking URL (POST)
fetch-stats/ # Re-fetch stats for a player (POST)
lib/
evaClient.ts # EVA GraphQL API client with caching & retry
balancer.ts # Brute-force team balancing algorithm
prisma.ts # Database client singleton
scheduler.ts # Weekly stat refresh cron job
prisma/
schema.prisma # Database schema (Player, PlayerStats, StatsSnapshot)
The app ships with a Dockerfile for easy deployment on Render, Railway, Fly.io, or any Docker host.
On Render:
- Create a free PostgreSQL database
- Create a Web Service pointing to this repo (Runtime: Docker)
- Set
DATABASE_URLto the internal database URL - Deploy — migrations run automatically on startup
- Region: Hardcoded for Bahrain region (
en-BH) - Rate Limiting: EVA's API throttles requests — the app uses 1.5s delays and retries to handle this
- Max 10 Players: The brute-force algorithm enumerates all combinations, so 10 is the practical limit
- No Map Data: EVA's public API only exposes aggregate season stats, not per-map breakdowns
MIT
Built for the EVA Bahrain community
Made for the community
