A real-time, serverless web application for programming contest spectators.
LiveSite provides an animated, responsive standings viewer for programming contests. Originally created for ICPC contests in Japan and Asia Pacific.
🌐 Live Examples:
- ✨ Animated Standings: Real-time updates with smooth rank changes and problem status animations
- 🏆 Award Ceremony Mode: Progressive reveal animation for result announcements
- 📱 Responsive Design: Works on desktop, tablet, and mobile
- 🔥 Serverless Architecture: Runs entirely on Firebase (Hosting + Realtime Database + GCS)
- 🎨 Customizable: Dark mode, team photos, country flags, and more
- 📊 Scoreboard Freeze: Shows pending submissions during frozen period
- 🚀 Easy Setup: Automated scraping from DOMjudge scoreboards
LiveSite uses a unique architecture that eliminates the need for dedicated servers:
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
│ DOMjudge │──────▶│ Scraper │──────▶│ Firebase │
│ Contest │ │ (Python) │ │ + GCS │
└─────────────┘ └──────────────┘ └──────┬───────┘
│
▼
┌──────────────┐
│ Viewers │
│ (React SPA) │
└──────────────┘
- Python scraper polls DOMjudge scoreboard every 10 seconds
- Firebase Realtime Database stores URLs to contest data (pub/sub)
- Google Cloud Storage hosts the actual JSON files (standings, teams, contest info)
- React frontend subscribes to Firebase and displays animated standings
# Frontend
cd frontend
npm install
# Python client (for scraping)
cd ../client
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtcd frontend
npm run serveThis starts Firebase emulators and opens http://localhost:5000 with demo data.
See the Setup Guide for detailed instructions on preparing your contest data and connecting to DOMjudge.
Comprehensive guides are available in the doc/ directory:
- SETUP.md - Local setup and testing (no cloud required)
- DEPLOYMENT.md - Production deployment to Firebase
- REVEAL.md - Award ceremony reveal animation setup
- examples/ - Sample configuration files
- Node.js and npm
- Python 3 (for client scraper)
- Google Account with Firebase/GCP project (for production)
- DOMjudge or compatible contest system
frontend/src/siteconfig.ts with your Firebase project configuration. See DEPLOYMENT.md for details.
Team names in DOMjudge must follow this format: {id}: {name}
Examples:
- ✅
01: TeamA - ✅
02: Awesome Coders - ✅
10: Team Ten - ❌
TeamA(missing ID) - ❌
Team 01(ID not before colon)
This allows the scraper to link teams between DOMjudge and your team data. See SETUP.md for more details.
- React with TypeScript
- Redux for state management
- Firebase Realtime Database for live data sync
- Material Design Bootstrap for UI
- Beautiful Soup for HTML parsing
- Google Cloud SDK for Firebase/GCS integration
- Scrapers for DOMjudge
- Scraper fetches HTML from DOMjudge
- Parses and converts to JSON
- Uploads to Google Cloud Storage
- Updates Firebase Database with GCS URL
- Frontend receives update via Firebase listener
- Diffs standings to compute events (AC/WA/pending)
- Animates UI changes
# Frontend development
cd frontend
npm run serve # Start dev server with emulators
npm run build # Build for production
npm run lint # Lint TypeScript/React code
npm test # Run smoke tests
# Python client
cd client
python livecli.py setup # Authenticate with Google
python livecli.py upload contest.yaml teams.yaml # Upload contest data
python livecli.py scrape domjudge --scoreboard-url=... # Scrape DOMjudge
# Firebase deployment
cd frontend
firebase deploy --only hosting # Deploy frontend
firebase deploy --only database # Deploy database rulesExample configuration files are provided in doc/examples/:
contest.yaml- Contest metadata and front page HTMLteams.yaml- Team information with members and photos
Contributions are welcome! You can help by:
- Reporting issues: Found a bug or have a feature request? Open an issue
- Contributing code:
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly (local dev + production if possible)
- Submit a pull request