UFC Predicts is an application designed to provide predictions and statistics for UFC (Ultimate Fighting Championship) fights and fighters. Leveraging data analysis, it aims to offer insights into potential fight outcomes, fighter performance metrics, and overall UFC event tracking.
- Fighter Profiles: Detailed statistics and information for UFC fighters, refreshed hourly from SportsData.io and UFC.com.
- Live Rankings: Official UFC rankings scraped hourly and cached for instant access.
- Event Tracking: Upcoming & past UFC events automatically refreshed every hour.
- Live Fight Centre: Real-time win-probability, strike and grappling stats streamed via Server-Sent Events (SSE).
- Fight Predictions: Logistic-regression model produces probability distributions for each matchup.
- Matchup Analysis: Compare fighters head-to-head with interactive charts.
- User Accounts: Sign up with Clerk to save favourites and track your prediction accuracy.
- Modern UI: Tailwind CSS + Shadcn UI + Framer Motion for slick animations.
- Offline Fallback: Mock data kicks-in if external APIs are unavailable.
| Layer | Library |
|---|---|
| Framework | Next.js 14 (App Router) |
| Styling | Tailwind CSS • Shadcn UI • Magic UI |
| DB / ORM | MongoDB Atlas • Prisma |
| Auth | Clerk |
| Data-fetching | SWR + server Route Handlers |
| Real-time | Node SSE streams |
| Scraping | Cheerio (UFC.com), SportsData.io SDK |
| Caching | Upstash Redis (with LRU memory fallback) |
| Tooling | @next/bundle-analyzer • Vercel Analytics |
| Language | TypeScript |
To run UFC Predicts locally, follow these steps:
-
Clone the repository:
git clone https://github.com/drewsephski/UFC-Predicts.git cd UFC-Predicts -
Install dependencies:
npm install # or pnpm install or yarn install -
Set up environment variables: Copy
.env.example➡️.env.localand fill in the blanks. Minimal keys for local dev:# Clerk Authentication NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY= CLERK_SECRET_KEY= NEXT_PUBLIC_CLERK_SIGN_IN_URL=/auth/signin NEXT_PUBLIC_CLERK_SIGN_UP_URL=/auth/signup NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/app NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/app # Prisma Database (Example for PostgreSQL) DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=public" # SportsData.io SPORTSDATA_API_KEY= # RapidAPI UFC Data (live stats fallback) RAPIDAPI_KEY= # Upstash Redis (edge caching) UPSTASH_REDIS_REST_URL= UPSTASH_REDIS_REST_TOKEN= # NextAuth.js (if used - though Clerk is listed above) # NEXTAUTH_URL= # NEXTAUTH_SECRET=
-
Initialize Prisma (if new setup or schema changes):
npx prisma generate npx prisma db push # Or prisma migrate dev for development migrations -
Run the development server:
npm run dev
Open http://localhost:3000 in your browser.
This project is configured to be deployed to both GitHub Pages and Netlify.
- Import the repository in Vercel → “New Project”.
- Add environment variables from
.env.local. - Build Command
npm run build, Outputout. - Cron Jobs:
vercel.jsonalready schedules/api/cron/sync-datahourly.
- Ensure your repository is pushed to GitHub
- The GitHub Actions workflow (
.github/workflows/gh-pages.yml) will automatically deploy your site when you push to themainbranch - Your site will be available at:
https://<your-github-username>.github.io/UFC-Predicts
- Push your code to a GitHub repository
- Log in to Netlify
- Click on "New site from Git"
- Select your repository
- Configure the build settings:
- Build command:
npm run build - Publish directory:
.next
- Build command:
- Click "Deploy site"
- Install the Netlify CLI:
npm install -g netlify-cli
- Log in to Netlify:
- Bundle-analysis:
npm run analyzesurfaces heavy modules; dynamic imports applied to marketing pages. - Code-splitting: Below-the-fold components load lazily via
next/dynamic+ IntersectionObserver. - Image-optimisation:
next/imageserves AVIF/WebP with blurred placeholders. - Database Indexes: Prisma generates compound indexes for common filters (division, event date).
- Static / ISR: Marketing pages are static; data-heavy pages use ISR backed by Redis.
Upstash Redis stores JSON responses under keys like ufc:fighters, ufc:events:upcoming, etc.
TTL defaults: fighters 24 h, events 1 h, live data 1 min.
Automatic fallback to in-memory LRU cache if Redis isn’t configured.
/api/live/events exposes SSE:
const ev = new EventSource('/api/live/events?fightId=123');
ev.onmessage = e => console.log(JSON.parse(e.data));Data refresh is handled by /api/cron/sync-data (hourly via Vercel Cron) which invalidates Redis keys and re-hydrates fresh data.
| Symptom | Fix |
|---|---|
503 Too many connections from /api/live/events |
Reduce clients or raise MAX_CONNECTIONS env. |
| Empty rankings | Ensure DISABLE_WEB_SCRAPING=false and check firewall blocks. |
| Stale data | POST /api/cron/sync-data with Authorization: Bearer <CRON_SECRET> to force refresh. |
netlify login- Build your project:
npm run build
- Deploy to Netlify:
netlify deploy --prod
You can also use the provided deployment script to simplify the process:
-
Make the script executable:
chmod +x scripts/deploy.sh
-
Run the script:
./scripts/deploy.sh
This will handle building your project and guiding you through the deployment process for both GitHub Pages and Netlify.
Contributions are welcome! Please feel free to submit a Pull Request or open an Issue.
This project is licensed under the MIT License. See the LICENSE file for details.
Built by drewsephski