Skip to content

Raffiesaurus/d2-predictor

Repository files navigation

D2 Predictor

A community prediction platform for Dota 2 Tier 1 tournaments, inspired by the prediction format from the "We Say Things" podcast hosted by SUNSfan and syndereN.

Before every major, SUNSfan and syndereN make their picks - Top 3 placements, a Dark Horse, and a White Donkey. D2 Predictor lets the entire community do the same, compete on leaderboards, and see how they stack up against the hosts.

Non-commercial fan project. Built with full credit and thanks to SUNSfan and syndereN for the inspiration.

🔗 Live site


Features

  • Predictions - Pick your Top 3 (with placements), Dark Horse, and White Donkey before each tournament
  • Automatic Scoring - Save results and all scores calculate in a single step
  • Leaderboards - Per-tournament and all-time rankings with scrollable sticky-header tables
  • Homepage Polls - Signed-in users can vote on the pinned community poll; results stay visible for 5 days after close
  • Host Predictions - SUNSfan & syndereN's picks hidden until lock, then revealed with scores
  • Final Standings - Dota 2-style tied placements (5-6th, 9-11th), seed deltas, tie-aware DH/WD logic
  • Countdown Timer - Live countdown on upcoming tournaments until predictions close
  • Prediction Lock - Picks lock automatically at tournament start, enforced server-side
  • Community Picks - Most-picked and second most-picked team per slot after lock
  • Public Profiles - Stats, rank, favorite team, and full prediction history per user
  • Status Filters - Filter tournaments by All / Upcoming / Active / Completed / Scored
  • Auto Transitions - Tournaments auto-activate when the start date passes
  • Admin Panel - Full CRUD for teams, tournaments, homepage polls, and site updates; drag-and-drop power rankings; placement format presets
  • Tournament & Team Notes - Optional info banners and per-team hover tooltips (hidden when empty)
  • Updates & Feedback - Database-backed changelog page and signed-in feedback form with email delivery via Resend

Scoring System

Pick Points Condition
Top 3 (×3) 2 pts each Exact placement match
Top 3 (×3) 1 pt each Right team, wrong placement (still top 3)
Dark Horse 1 pt Team finishes 4+ places above seed
White Donkey 1 pt Team finishes 4+ places below seed
Max per tournament 8 pts
  • Seeds are set by admin via datdota Glicko-2 ratings
  • DH/WD picks can overlap with Top 3
  • Tied placements: Dark Horse uses best position, White Donkey uses worst (favors user)
  • Threshold is centralized in src/lib/constants.ts

Tech Stack

Layer Technology
Framework Next.js 16 (App Router, TypeScript strict)
Database & Auth Supabase (PostgreSQL + Auth + Storage)
UI Tailwind CSS v4 + shadcn/ui
Drag & Drop @dnd-kit
Email Resend
Hosting Vercel
Auth Providers Google + Discord OAuth (PKCE)

Getting Started

Prerequisites

  • Node.js 18+
  • Supabase CLI
  • A Supabase project (free tier works)

Setup

  1. Clone and install

    git clone https://github.com/Raffiesaurus/d2-predictor.git
    cd d2-predictor
    npm install
  2. Configure environment

    cp .env.example .env.local
    NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
    NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your-publishable-key
    SUPABASE_SECRET_KEY=your-secret-key
    NEXT_PUBLIC_SITE_URL=http://localhost:3000
    RESEND_API_KEY=your-resend-api-key
    FEEDBACK_FROM_EMAIL="D2 Predictor Feedback <sender@yourdomain.com>"
  3. Run migrations and seed

    npx supabase db push
    npx supabase db reset --seed-only

    The site updates and the initial homepage poll are seeded by the SQL migrations.

  4. Grant admin access (after first sign-in)

    UPDATE profiles SET is_admin = true WHERE id = 'your-user-id';
  5. Start dev server

    npm run dev

    Open http://localhost:3000


Project Structure

src/
├── app/
│ ├── page.tsx                            # Homepage - tournament list, pinned poll, search + status filters
│ ├── homepage-poll.tsx                   # Client homepage poll card + post-vote results state
│ ├── auth/                               # OAuth (Google + Discord), PKCE flow
│ ├── account/                            # Profile settings (name, avatar, favorite team)
│ ├── leaderboards/                       # All-time + per-tournament leaderboards
│ ├── rules/                              # Scoring rules, FAQ, credits
│ ├── updates/                            # Public changelog page
│ ├── tournaments/[slug]/                 # Tournament detail (standings, hosts, predictions, scores)
│ ├── user/[id]/                          # Public user profiles
│ └── admin/                              # Teams, rankings, tournaments, polls, updates, results
├── components/
│ ├── countdown.tsx                       # Live countdown timer
│ ├── nav.tsx                             # Navigation bar
│ └── ui/                                 # shadcn/ui components
├── lib/
│ ├── constants.ts                        # Types, SEED_DIFF_THRESHOLD, placement presets
│ ├── site-content.ts                     # Shared site poll/update types and visibility helpers
│ ├── site-content-server.ts              # Server-side site poll/update queries
│ ├── tournament-status.ts                # Auto upcoming→active transition
│ └── supabase/                           # Client, server, admin, middleware helpers
supabase/
├── migrations/                           # SQL migration files, including site content tables
└── seed.sql                              # 16 Dota 2 teams + host setup

Roadmap

  • A better name 😭
  • Liquipedia API integration (pending access)
  • Full hero icons and team logos
  • Social sharing / SEO

License

AGPL-3.0 - © 2026 Raffiesaurus

Credits

SUNSfan and syndereN - for the "We Say Things" podcast and the prediction format that inspired this project.

About

Community prediction platform for Dota 2 Tier 1 tournaments. Pick your Top 3, Dark Horse, and White Donkey - compete on leaderboards and see how you stack up against SUNSfan & syndereN. Built with Next.js, Supabase, and Tailwind.

Topics

Resources

License

Stars

Watchers

Forks

Contributors