- Python 52%
- TypeScript 47.2%
- JavaScript 0.2%
- CSS 0.2%
- Shell 0.2%
- Add dark mode styling to bet resolution section (backgrounds, text, borders) - Add dark mode styling to winner display section - Add participant win/loss summary showing net gains/losses for each user - Color-code participant results (green for wins, red for losses) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> |
||
|---|---|---|
| .claude | ||
| .forgejo/workflows | ||
| .serena | ||
| backend | ||
| docs | ||
| frontend | ||
| presentations | ||
| scripts | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| docker-compose.prod.yml | ||
| docker-compose.yml | ||
| README.md | ||
| SPECIFICATION.md | ||
Office Betting Platform v2.0
A multi-organization play-money pari-mutuel betting platform using OfficeCoins virtual currency.
DISCLAIMER: This application uses virtual play money only. No real money is wagered or paid out. For entertainment purposes only.
Screenshot
TODO: Add screenshot of the current UI to docs/screenshot.png
Quick Start
docker-compose up --build
Then open http://localhost:3000 in your browser.
What's New in v2.0
- Multi-Organization System: Create and manage multiple betting organizations
- Organization Roles: Owner, Admin, and Member roles with different permissions
- Invitations System: Invite users via email or shareable invite links
- Real-Time Notifications: Server-Sent Events (SSE) for live updates
- Comments & Discussions: Comment on bets with real-time updates
- Achievements System: Gamification badges for user milestones
- Seasons & Categories: Organize bets by season and category
- Image Uploads: Custom avatars and organization logos
- Dark Mode: Full dark mode support
- Activity Feed: Track recent activity across your organization
- Audit Logging: Complete admin action history
- Transaction History: Full audit trail for all coin movements
- Reports & Export: Moderation tools and data export
- House Fees: Configurable house fee per organization
Features
Organizations
- Create unlimited organizations with unique slugs
- Customize settings per organization:
- Initial balance for new members
- Minimum wager amount
- House fee percentage
- Early bet bonus multiplier
- Custom logo and branding
- Three-tier permission system (Owner, Admin, Member)
- Invite-only or open membership
- Per-organization balances (not global)
Betting
- Create bets with any number of outcomes (minimum 2)
- Pari-mutuel odds that update in real-time after each wager
- Early bet bonus: Wagers in the first 50% of the betting window get weight multiplier
- Live countdown timers until betting closes
- House fees: Configurable percentage taken from the pool
- Categories: Organize bets by category (Sports, Politics, Office, etc.)
- Seasons: Group bets into seasons for seasonal leaderboards
- Comments: Discuss bets with other members
- Zero-sum accounting: All payouts verified via transaction ledger
Users & Social
- Register with email/password (email verification optional)
- Custom avatars and user profiles
- Personal wager history and statistics
- Achievements and badges
- Activity feed showing recent bets, wagers, and comments
- Real-time notifications for:
- New bets in your organization
- Bet results and payouts
- Comments on bets you've wagered on
- New achievements
Administration
- Admin dashboard for organization management
- Invite members via email or shareable links
- Approve/reject membership requests
- Adjust member balances
- View audit log of all admin actions
- Moderation queue for reported content
- Export data for analysis
- View transaction history for zero-sum verification
Tech Stack
| Component | Technology |
|---|---|
| Backend | FastAPI + Python 3.14 |
| Database | SQLite (file-based) |
| ORM | SQLAlchemy 2.0 |
| Frontend | React 18 + TypeScript + Vite |
| Styling | Tailwind CSS |
| Icons | Lucide React |
| Auth | JWT tokens |
| Real-time | Server-Sent Events (SSE) |
| Testing | Vitest + pytest |
| Container | Docker Compose |
| Dependency Mgmt | uv (backend), npm (frontend) |
Project Structure
office-betting/
├── docker-compose.yml # One-command startup
├── README.md
├── SPECIFICATION.md # Full technical specification
│
├── backend/
│ ├── Dockerfile
│ ├── pyproject.toml
│ ├── data/ # SQLite database (created on startup)
│ ├── migrations/ # Alembic database migrations
│ └── src/mirustech/betting/
│ ├── main.py # FastAPI app
│ ├── config.py # Settings
│ ├── database.py # SQLAlchemy setup
│ ├── models/ # Database models
│ ├── schemas/ # Pydantic schemas
│ ├── routers/ # API routes
│ │ ├── auth.py
│ │ ├── bets.py
│ │ ├── organizations.py
│ │ ├── members.py
│ │ ├── invitations.py
│ │ ├── notifications.py
│ │ ├── comments.py
│ │ ├── achievements.py
│ │ ├── activity.py
│ │ ├── categories.py
│ │ ├── seasons.py
│ │ ├── transactions.py
│ │ ├── uploads.py
│ │ ├── audit.py
│ │ ├── reports.py
│ │ ├── export.py
│ │ └── ...
│ ├── services/ # Business logic
│ └── seed.py # Seed data
│
└── frontend/
├── Dockerfile
├── package.json
└── src/
├── api/ # API client
├── components/ # React components
├── pages/ # Page components
├── hooks/ # Custom hooks
├── contexts/ # React contexts
└── types/ # TypeScript types
API Endpoints
Authentication
POST /api/auth/register- Create accountPOST /api/auth/login- Get JWT tokenGET /api/auth/me- Current user infoPUT /api/auth/me- Update profilePOST /api/auth/forgot-password- Password reset requestPOST /api/auth/reset-password- Reset password with token
Organizations
GET /api/organizations- List user's organizationsPOST /api/organizations- Create organizationGET /api/organizations/{slug}- Get organization detailsPUT /api/organizations/{slug}- Update organization (admin)DELETE /api/organizations/{slug}- Delete organization (owner)GET /api/organizations/{slug}/members- List membersPOST /api/organizations/{slug}/invitations- Create invitation (admin)POST /api/organizations/{slug}/join- Join via invite code
Bets
GET /api/bets- List all bets (filterable by status, category, season)POST /api/bets- Create new betGET /api/bets/{id}- Get bet details with oddsPOST /api/bets/{id}/wager- Place a wagerPOST /api/bets/{id}/resolve- Resolve bet (creator only)POST /api/bets/{id}/report- Report bet for moderation
Comments
GET /api/bets/{id}/comments- Get bet commentsPOST /api/bets/{id}/comments- Post commentPUT /api/comments/{id}- Edit commentDELETE /api/comments/{id}- Delete comment
Notifications
GET /api/notifications/stream- SSE stream for real-time notificationsGET /api/notifications- List notificationsPUT /api/notifications/{id}/read- Mark as readPOST /api/notifications/read-all- Mark all as read
Other
GET /api/leaderboard- Organization leaderboardGET /api/users/me/wagers- User's wager historyGET /api/activity- Recent activity feedGET /api/achievements- List achievementsGET /api/transactions- Transaction history (admin)GET /api/audit- Audit log (admin)POST /api/uploads/avatar- Upload avatarPOST /api/uploads/org-logo- Upload org logo
Development Setup
Backend (without Docker)
cd backend
uv sync
source .venv/bin/activate # or `.venv\Scripts\activate` on Windows
# Run migrations
alembic upgrade head
# Seed data
python -m mirustech.betting.seed
# Run development server
uvicorn mirustech.betting.main:app --reload --port 8000
# Run tests
pytest
# Type checking
mypy src/
# Linting
ruff check .
Frontend (without Docker)
cd frontend
npm install
npm run dev # Starts on http://localhost:5173
# Run tests
npm test
# Build for production
npm run build
# Type checking
npx tsc --noEmit
# Linting
npm run lint
Configuration
Environment variables (can be set in docker-compose.yml or .env):
| Variable | Default | Description |
|---|---|---|
BETTING_DATABASE_URL |
sqlite+aiosqlite:///./data/betting.db |
Database connection |
BETTING_JWT_SECRET_KEY |
dev-secret-key... |
JWT signing key (change in production!) |
BETTING_DEBUG |
false |
Debug mode |
Organization-level settings (configurable per org):
initial_balance- Starting coins for new members (default: 1000)minimum_wager- Minimum wager amount (default: 50)early_bet_bonus- Weight multiplier for early bets (default: 1.2)house_fee_pct- House fee percentage (default: 0.05 = 5%)allow_public_join- Allow anyone to join (default: false)
Zero-Sum Accounting
All coin movements are tracked via the Transaction model:
sum(payouts) + house_fee = sum(wagers)
house_fee = total_pool * house_fee_pct
distributable = total_pool - house_fee
payout_i = (weighted_wager_i / total_winning_weight) * distributable
Every bet resolution creates transactions that maintain zero-sum balance across the organization.
Testing
Backend Tests
cd backend
pytest # Run all tests
pytest -v # Verbose output
pytest --cov # With coverage report
pytest tests/integration/ # Integration tests only
Frontend Tests
cd frontend
npm test # Run in watch mode
npm run test:run # Run once
npm run test:coverage # With coverage report
Migration from v1.0
v2.0 is a complete rewrite with a different database schema. There is no automated migration path from v1.0. Key changes:
- Balances: v1.0 had global balances, v2.0 has per-organization balances
- Organizations: v2.0 introduces multi-tenancy
- Transactions: v2.0 has complete audit trail
- Notifications: v2.0 has real-time SSE notifications
Deployment Notes
For production deployment:
- Change the JWT secret: Set a strong random
BETTING_JWT_SECRET_KEY - Use a proper database: Consider PostgreSQL for production instead of SQLite
- Enable email verification: Configure email settings for user verification
- Set up reverse proxy: Use nginx or similar for SSL termination
- Configure file uploads: Set up proper file storage (S3, etc.)
- Monitor transactions: Regularly verify zero-sum accounting via
/api/transactions - Backup database: Regular backups of the SQLite file or database
License
MIT
Contributing
This is a personal/office project. Feel free to fork and adapt for your own use!
