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.
When using the default scraper, 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