BeamNG.Earth
A 1:1 scale streamed Earth for BeamNG.drive: real elevation and satellite imagery, floating origin, LOD streaming from a companion server
Captains-draft tournaments for League of Legends and Counter-Strike 2.
GamesTypeScript · JavaScriptGitHub @calebaracousOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗The web app that runs the Spicy League — a recurring captains-draft 5v5 tournament series for League of Legends and Counter-Strike 2.
Live site: spicyleague.dev
Each season follows the same lifecycle:
floor(signups / 5) recommended; two can pair up as duo captains)The app handles all of it: signups, a live realtime draft, match reporting, standings with tiebreakers, and player profiles backed by Riot API stats. A Discord bot keeps league roles, private team channels and match threads in step with the site, answers slash commands like /standings, and feeds the home page's announcements ticker (see docs/DISCORD.md).
It also runs 10-mans — one-off 5v5 pickup games: the first 10 signups vote for two captains, who snake-draft the other eight live. See docs/TEN-MAN.md.
| Concern | Choice |
|---|---|
| Framework | Next.js 16 (App Router) + React 19 |
| Language | TypeScript (strict) |
| Styling | Tailwind CSS v4 + shadcn/ui |
| Auth | Better Auth — username + password, email verification |
| Database | Neon Postgres |
| ORM | Drizzle ORM |
| Resend | |
| Realtime (drafts, 10-mans) | Server-Sent Events (DB polling, no external pub/sub) |
| Rate limiting | Upstash Redis (optional — falls open if not configured) |
| Cron | Vercel Cron — daily Riot stat refresh + Discord reminders |
| Discord | REST bot + slash commands over the HTTP interactions endpoint (no separate process) |
| Validation | Zod |
| Deployment | Vercel |
Prerequisites: Node.js 22+ (the DB driver needs Node's built-in WebSocket; CI uses 22), a Neon Postgres database, a Resend account.
git clone https://github.com/calebaracous/spicy-league.git
cd spicy-league
npm install
Copy .env.example to .env.development.local and fill in the required values (see Environment variables below). Point it at a Neon branch, not production — see docs/STAGING.md.
npm run db:migrate # build/upgrade the schema on your Neon branch (reads .env.development.local)
npm run dev # start dev server at http://localhost:3000
The app validates env vars via @t3-oss/env-nextjs (when src/lib/env.ts is first imported). Set SKIP_ENV_VALIDATION=1 to skip this (useful in CI).
Minimum for local dev:
| Variable | Description |
|---|---|
DATABASE_URL | Neon pooled connection string |
BETTER_AUTH_SECRET | Random string, 32+ chars |
AUTH_RESEND_KEY | Resend API key — needed for signup emails |
NEXT_PUBLIC_APP_URL | http://localhost:3000 for local dev |
Additional for full functionality:
| Variable | Description |
|---|---|
RIOT_PERSONAL_API_KEY | Riot Games Personal API Key for LoL stats |
UPSTASH_REDIS_REST_URL | Upstash Redis URL for rate limiting |
UPSTASH_REDIS_REST_TOKEN | Paired with the URL |
CRON_SECRET | Bearer token for the Vercel Cron endpoints |
DISCORD_* | Discord bot — token, server, channels, slash commands (setup in docs/DISCORD.md) |
See docs/ENV.md for the full list and notes on what breaks without each one.
Migrations are sequential SQL files under drizzle/, starting from a squashed baseline (see docs/DATA-MODEL.md → Migrations). Never edit an existing migration — always generate a new one:
npm run db:generate # generate a new migration after schema changes
npm run db:migrate # apply pending migrations
npm run db:studio # open Drizzle Studio to browse the DB
Schemas live in src/db/schema/ — one file per domain (auth, seasons, drafts, matches, stats, ten-mans, events).
To get a populated season locally, seed one (4 captain + 16 bot accounts; credentials are in the script header). It writes to whatever DATABASE_URL points at, so prefer npm run test:e2e for automated testing:
ALLOW_TEST_SEED=1 npx tsx --env-file=.env.development.local scripts/seed-test-season.ts
npm run dev # dev server with Turbopack
npm run build # production build
npm run lint # ESLint
npm run typecheck # tsc --noEmit
npm run format # Prettier (format:check is what CI runs)
npm run test:unit # Vitest — pure logic: draft order, standings, schedule, subs, Discord helpers, events (runs in CI)
npm run test:e2e # Playwright — full season draft through the UI (see docs/TESTING.md)
CI runs format check, lint, typecheck, unit tests, and build on every push. A Husky pre-commit hook runs ESLint + Prettier on staged files.
src/
app/ # Next.js App Router — pages, server actions, API routes
admin/ # Admin-only pages (season management, draft controls)
seasons/ # Public season pages (signup, draft viewer, matches)
10-man/ # 10-man pickup flow (signup, vote, draft, result)
api/ # Route handlers (auth, draft + 10-man SSE streams, crons, Discord interactions)
components/ # Shared UI components and shadcn primitives
db/ # Drizzle client and schema
lib/ # Server-side logic (auth, draft, schedule, Riot API, etc.)
drizzle/ # Generated migration files
scripts/ # Dev + one-off scripts (test-season seeder, e2e cleanup, Season 12 setup, Discord command registration)
docs/ # Architecture and domain docs (good starting point)
Before touching an unfamiliar area, skim the relevant doc in docs/. They're written to be dense and useful, not ceremonial:
Fork the repo, make your changes, and open a pull request. Keep commits small. CI (format, lint, typecheck, unit tests, build) must pass. If you're adding non-trivial functionality or changing a flow, update the relevant doc in the same commit.
If you spot a bug or have an idea, open an issue first so we can discuss before you build it out.