A full-stack virtual sports betting platform where users wager play money on football matches with real-time odds and automatic market settlement.
- Virtual Currency - Start with 1000 coins, bet on matches risk-free
- Real Football Data - Live matches from football-data.org API
- Multiple Market Types - Match winner, player props, tournament specials
- Live Odds - Dynamic odds based on selections
- Leaderboard - Compete with friends for top rankings
- Activity Feed - See what others are betting on
- Secure Auth - JWT-based authentication with role-based access
- Tournament Management - Create tournaments linked to real competitions
- Event Creation - Add matches manually or fetch from API (by matchday or stage)
- Market Creation - Set up betting markets with custom odds
- Market Settlement - Settle markets and auto-distribute winnings
- Market Voiding - Cancel markets with full refunds
- User Management - Adjust balances, activate/deactivate users
- Data Sync - Sync teams, players, and fixtures from football-data.org
+------------------+
| CloudFront CDN |
| (Static Assets) |
+--------+---------+
|
v
+------------+ HTTPS +------------------+ +------------------+
| Client |-------------------->| AWS App Runner |------->| RDS PostgreSQL |
| Browser | | (FastAPI API) | | (Primary DB) |
+------------+ +--------+---------+ +------------------+
|
v
+------------------+
| SSM Parameter |
| Store (ENV) |
+------------------+
|
v
+------------------+
| football-data.org|
| API |
+------------------+
User Request
|
v
+----------------------------+
| AWS Route 53 (DNS) |
+----------------------------+
|
+------------+------------+
| |
v v
+------------+ +--------------+
| CloudFront | | App Runner |
| (Static | | (API) |
| Assets) | +--------------+
+------------+ |
| v
| +--------------+
| | SSM Params |
| | (Secrets) |
| +--------------+
| |
v v
+------------+ +--------------+
| S3 Bucket | | RDS |
| (React | | PostgreSQL |
| Build) | +--------------+
+------------+
+-------------+ +-------------+ +-------------+
| User | | Tournament | | Event |
+-------------+ +-------------+ +-------------+
| id (PK) |<-----+| id (PK) |<-----+| id (PK) |
| username | | name | | tournament_id|
| email | | competition_id| | title |
| balance | | status | | match_id |
| is_admin | +-------------+ | starts_at |
+-------------+ +-------------+
| |
| +-------------+ |
| | Bet | |
| +-------------+ |
+------>| id (PK) | |
| user_id (FK)| |
| selection_id| |
+------>| stake | |
| | status | |
| +-------------+ |
| |
| +-------------+ +-------------+
| | Selection | | Market |
| +-------------+ +-------------+
+------>| id (PK) |<-----+| id (PK) |
| market_id | | event_id |
| label | | question |
| odds | | status |
| is_winner | +-------------+
+-------------+
- Python 3.11+
- Node.js 18+
- Docker Desktop (for local PostgreSQL)
cd backend
# Start PostgreSQL
docker-compose up -d
# Create virtual environment
python -m venv venv
venv\Scripts\activate # Windows
source venv/bin/activate # macOS/Linux
# Install dependencies
pip install -r requirements.txt
# Configure environment
copy .env.example .env
# Edit .env with your JWT_SECRET_KEY and FOOTBALL_API_KEY
# Seed database with test accounts
python -m app.seed
# Start server
uvicorn app.main:app --reloadBackend runs at: http://localhost:8000 API Docs: http://localhost:8000/docs
cd frontend
# Install dependencies
npm install
# Configure environment
copy .env.example .env
# Set VITE_API_URL=http://localhost:8000
# Start development server
npm run devFrontend runs at: http://localhost:5173
After running python -m app.seed, use these accounts:
| Role | Password | |
|---|---|---|
| Admin | admin@mailinator.com | admin@123 |
| User | fenil@mailinator.com | fenil@123 |
Note: All test accounts use
@mailinator.comemails with matching passwords.
POST /auth/login
GET /auth/me
POST /auth/change-passwordPOST /bets # Place a bet
GET /bets/me # My bet historyGET /events/{id}/markets # Get markets for event
POST /bets # Place bet on selectionPOST /admin/events # Create event
POST /admin/markets # Create market
POST /admin/markets/{id}/settle # Settle with winner
POST /admin/markets/{id}/void # Void market
POST /admin/sync/competitions # Sync from API
GET /admin/tournaments/{id}/matches?matchday=8 # Fetch by matchday
GET /admin/tournaments/{id}/matches?stage=LAST_16 # Fetch by stageFull API documentation: http://localhost:8000/docs
| Technology | Purpose |
|---|---|
| FastAPI | High-performance Python web framework |
| SQLAlchemy 2.0 | Modern ORM with type hints |
| PostgreSQL | Production-grade database |
| PyJWT | JWT authentication |
| Pydantic | Data validation |
| httpx | Async HTTP client for football API |
| Technology | Purpose |
|---|---|
| React 19 | Latest React with concurrent features |
| Vite | Ultra-fast build tool |
| Tailwind CSS | Utility-first styling |
| React Query | Server state management |
| React Router v7 | Client-side routing |
| React Hot Toast | Toast notifications |
| Lucide React | Beautiful icons |
Internet
|
v
+----------------------------------+
| AWS CloudFront |
| (CDN for static assets + |
| API Gateway for /api/*) |
+----------------------------------+
| |
v v
+--------------+ +------------------+
| S3 Bucket | | AWS App Runner |
| (Frontend) | | (FastAPI API) |
+--------------+ +------------------+
|
v
+------------------+
| RDS PostgreSQL |
| (Database) |
+------------------+
^
|
+------------------+
| SSM Parameter |
| Store (ENV) |
+------------------+
- AWS CLI configured with appropriate credentials
- Docker installed locally
- AWS account with access to: ECR, App Runner, RDS, S3, CloudFront
aws ecr create-repository --repository-name betarena-backend --region ap-south-1cd backend
# Login to ECR
aws ecr get-login-password --region ap-south-1 | docker login --username AWS --password-stdin YOUR_ACCOUNT_ID.dkr.ecr.ap-south-1.amazonaws.com
# Build image
docker build -t betarena-backend .
# Tag image
docker tag betarena-backend:latest YOUR_ACCOUNT_ID.dkr.ecr.ap-south-1.amazonaws.com/betarena-backend:latest
# Push image
docker push YOUR_ACCOUNT_ID.dkr.ecr.ap-south-1.amazonaws.com/betarena-backend:latest# Create DB subnet group
aws rds create-db-subnet-group \
--db-subnet-group-name betarena-db-subnet \
--db-subnet-group-description "Subnet group for BetArena DB" \
--subnet-ids '["subnet-xxxx", "subnet-yyyy"]'
# Create PostgreSQL instance
aws rds create-db-instance \
--db-instance-identifier betarena-db \
--db-instance-class db.t3.micro \
--engine postgres \
--engine-version 16 \
--allocated-storage 20 \
--storage-type gp2 \
--master-username postgres \
--master-user-password YOUR_SECURE_PASSWORD \
--db-subnet-group-name betarena-db-subnet \
--vpc-security-group-ids sg-xxxxx \
--backup-retention-period 7 \
--no-publicly-accessibleaws ssm put-parameter \
--name /betarena/prod/database_url \
--value "postgresql://postgres:PASSWORD@betarena-db.xxxx.ap-south-1.rds.amazonaws.com:5432/betarena" \
--type SecureString
aws ssm put-parameter \
--name /betarena/prod/jwt_secret \
--value "your-secret-jwt-key-any-random" \
--type SecureString
aws ssm put-parameter \
--name /betarena/prod/football_api_key \
--value "your-football-data-org-api-key" \
--type SecureStringaws apprunner create-service \
--service-name betarena-backend \
--source-configuration '{
"ImageRepository": {
"ImageIdentifier": "YOUR_ACCOUNT_ID.dkr.ecr.ap-south-1.amazonaws.com/betarena-backend:latest",
"ImageRepositoryType": "ECR",
"ImageConfiguration": {
"Port": "8000",
"RuntimeEnvironmentVariables": {
"ENVIRONMENT": "production"
},
"RuntimeEnvironmentSecrets": {
"DATABASE_URL": "/betarena/prod/database_url",
"JWT_SECRET_KEY": "/betarena/prod/jwt_secret",
"FOOTBALL_API_KEY": "/betarena/prod/football_api_key"
}
}
}
}' \
--instance-configuration '{
"Cpu": "1 vCPU",
"Memory": "2 GB"
}'cd frontend
# Set production API URL
$env:VITE_API_URL = "https://your-app-runner-url.ap-south-1.awsapprunner.com" # PowerShell
export VITE_API_URL=https://your-app-runner-url.ap-south-1.awsapprunner.com # Bash
# Install dependencies
npm install
# Build
npm run buildaws s3api create-bucket \
--bucket betarena-frontend \
--region ap-south-1 \
--create-bucket-configuration LocationConstraint=ap-south-1
# Enable static website hosting
aws s3 website s3://betarena-frontend/ --index-document index.html --error-document index.html
# Set bucket policy for public read
aws s3api put-bucket-policy --bucket betarena-frontend --policy '{
"Version": "2012-10-17",
"Statement": [{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::betarena-frontend/*"
}]
}'aws s3 sync dist/ s3://betarena-frontend/ --deleteaws cloudfront create-distribution \
--origin-domain-name betarena-frontend.s3.ap-south-1.amazonaws.com \
--default-root-object index.html \
--no-query-string-forwardaws cloudfront create-invalidation \
--distribution-id YOUR_DISTRIBUTION_ID \
--paths "/*"-
Seed Production Database:
# Connect to App Runner service aws apprunner create-deployment --service-arn arn:aws:apprunner:ap-south-1:xxxx:service/betarena-backend/xxxx # Seed data (run once) # Use AWS Systems Manager Session Manager or create a one-off task
-
Configure CORS:
- Update backend
CORS_ORIGINSenvironment variable with CloudFront domain
- Update backend
-
Verify Deployment:
# Run health check
curl http://localhost:8000/health
# View API docs
open http://localhost:8000/docs# Run linter
npm run lint
# Build for production
npm run build
# Preview production build
npm run preview- football-data.org - Football data and match information
- FastAPI - High-performance Python web framework
- React - JavaScript library for building user interfaces
This project is for educational purposes.