RoboRef (roboref.app) is an offline-first match anomaly log and referee assistant built specifically for Head Referees and field referees at VEX Robotics competitions (V5RC, VIQRC, VEX U, and VEX AI).
RoboRef enables field referees to quickly log rule infractions, inspect a team's prior incident history before match queuing, and synchronize notes seamlessly across peer devices in real-time—even in tournament venues with severe RF interference and zero internet connectivity.
- Key Features
- Architecture & Tech Stack
- Repository Structure
- Prerequisites
- Getting Started & Running Locally
- Building for Production
- Configuration & Environment Variables
- Testing & Code Quality
- Versioning & Changelog
- Contributing & AI Agent Guidelines
- ⚡ Offline-First Resilience: Full local persistence using Drift (SQLite). Referees can log notes, search matches, and inspect team histories without any network connection.
- 📝 Fast Incident Logging: Rapidly record rule infractions with rule codes (e.g.
G1,G12,S1,SG6,R4), severity classifications (Minor, Major, Warning, DQ), match linkage, and referee notes. - 🔍 Prior Infraction History: View cumulative incident histories for every team on the field prior to match start to spot repeat warnings or escalating patterns.
- 🏆 Tournament & Division Schedules: Ingest complete tournament schedules, division assignments, alliance pairings, and match field allocations.
- 🌐 VEX Events API & CSV Ingestion:
- Direct live search and schedule ingestion via the official VEX Events API v2 (
events.vex.com). - Offline Tournament Manager (TM) team and match schedule CSV import for venues without internet access.
- Direct live search and schedule ingestion via the official VEX Events API v2 (
- 🔄 Dual Sync Protocol:
- Venue LAN Sync: Connect to a local venue Raspberry Pi or laptop (
http://roboref.local:8080) over local Wi-Fi / Ethernet without WAN access. - Cloud Sync: Global replication powered by Cloudflare Workers and D1 database.
- Venue LAN Sync: Connect to a local venue Raspberry Pi or laptop (
- 📱 Mobile-First Material Design 3: High-contrast, touch-friendly UI designed for rapid handheld operation on the competition field with full dark/light theme support.
| Component | Technology | Purpose |
|---|---|---|
| Frontend Client | Flutter (Dart ^3.5.0) | Cross-platform mobile (Android, iOS) & Web/PWA client |
| State Management | Riverpod 2.x | Reactive state and dependency injection |
| Client Storage | Drift (SQLite) | Embedded, high-performance offline database |
| Sync Server | Hono + TypeScript | Universal backend running on Node.js (LAN) and Cloudflare Workers (Cloud) |
| Server Storage | better-sqlite3 / Cloudflare D1 | High-speed server persistence and delta sync logging |
RoboRef/
├── app/ # Flutter client application
│ ├── android/ # Android platform files & gradle configuration
│ ├── ios/ # iOS platform files & Xcode workspace
│ ├── web/ # Web platform assets, manifest, and service worker
│ ├── assets/ # Application icons, fonts, and changeLog.md
│ └── lib/
│ ├── core/ # Network clients, themes, constants, and utilities
│ ├── database/ # Drift SQLite schemas, DAOs, and connection logic
│ └── features/ # Feature-first modules (incidents, matches, teams, settings, home)
├── server/ # Universal sync backend (TypeScript & Hono)
│ └── src/
│ ├── adapters/ # Storage implementations (better-sqlite3 for Node, D1 for Cloudflare)
│ ├── core/ # REST API routes, VEX Events proxy, and sync logic
│ ├── index.node.ts # Local Node.js / Raspberry Pi server entry point
│ └── index.cf.ts # Cloudflare Workers server entry point
├── scripts/ # Build and utility scripts
│ ├── build.ps1 # Automated Windows / PowerShell build script (CalVer + commit count)
│ ├── build.sh # Automated Bash / Linux build script
│ ├── deploy.ps1 # Automated build + deploy script for Cloudflare (test/live)
│ ├── deploy.sh # Automated Linux / Bash deploy script for Cloudflare
│ └── generate-icons.mjs# Icon generation pipeline for Android, iOS, and Web assets
└── wrangler.toml # Root Cloudflare configuration (Workers + Static Web Assets, test/live)
Before getting started, make sure you have installed:
- Flutter SDK (
^3.5.0or higher) with Dart^3.5.0 - Node.js (
v18.xorv20.xLTS) andnpm - Platform Toolchains (depending on your target build):
- Android: Android Studio & Android SDK (API 34+)
- iOS/macOS: Xcode (macOS only)
- Web: Google Chrome / Chromium
Navigate to the app/ directory and install Flutter dependencies:
cd app
flutter pub getflutter run -d chromeflutter run -d androidflutter run -d iosIf you update database tables, DAOs, or queries, re-generate the Drift code:
cd app
dart run build_runner build --delete-conflicting-outputsThe sync server can run locally as a Node.js process (ideal for Raspberry Pi venue servers or local debugging) or inside the Cloudflare Workers local environment.
Navigate to the server/ directory and install dependencies:
cd server
npm installStarts the local server on http://0.0.0.0:8080 backed by a local SQLite database file (roboref.sqlite):
npm run dev:nodenpm run dev:cfnpm run typecheckRoboRef uses Calendar Versioning (CalVer, formatted as YYYY.M.D) paired with the Git commit count as the build number. Helper scripts in scripts/ automatically format these flags:
# Build Android APK (default target: apk)
.\scripts\build.ps1 apk
# Build Android App Bundle (.aab)
.\scripts\build.ps1 appbundle
# Build Web PWA bundle
.\scripts\build.ps1 web
# Build Windows Desktop executable
.\scripts\build.ps1 windows# Build Android APK
./scripts/build.sh apk
# Build Web PWA bundle
./scripts/build.sh webYou can also run Flutter build commands directly from the app/ folder:
cd app
# Android APK
flutter build apk --release
# Android App Bundle
flutter build appbundle --release
# Web PWA (outputs to app/build/web)
flutter build web --release
# iOS (requires macOS and Xcode)
flutter build ipa --releaseRoboRef uses a unified Cloudflare Workers configuration with Static Assets (wrangler.toml at the repository root). This hosts the Flutter Web PWA on Cloudflare's global edge network while routing backend API requests (/api/*) directly to the Hono sync worker.
Ensure you are logged into Wrangler (npx wrangler login) before deploying.
# Build Web and deploy to Test environment (test D1 database)
.\scripts\deploy.ps1 test
# Build Web and deploy to Live environment (roboref.app + live D1 database)
.\scripts\deploy.ps1 live
# Deploy existing build without rebuilding Flutter
.\scripts\deploy.ps1 test -SkipBuild# Build Web and deploy to Test
./scripts/deploy.sh test
# Build Web and deploy to Live
./scripts/deploy.sh live# Test environment
npx wrangler deploy --env test
# Live / Production environment
npx wrangler deploy --env livecd server
npm run build:node
npm run start:node(Optionally configure systemd or PM2 to keep the Node.js server active on boot at http://roboref.local:8080.)
Build and run the lightweight Alpine-based container with persistent SQLite storage:
cd server
docker build -f Dockerfile.rpi -t roboref-sync-server .
docker run -d -p 8080:8080 -v roboref-data:/data --restart unless-stopped --name roboref-sync roboref-sync-serverCreate a .env file inside the server/ folder or set environment variables on your deployment host:
| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
Port for the local Node.js sync server |
DB_PATH |
roboref.sqlite |
Filepath for the local SQLite database |
VEX_EVENTS_TOKEN |
(Optional) | VEX Events API v2 Bearer token for server-side proxy caching |
VEX_API_KEY |
(Optional) | Alternative environment variable name for VEX Events API key |
Inside the RoboRef app under Settings:
- Referee Display Name: Configure referee display name. Active tournaments are selected from the Event List on the Home screen.
- Sync Server Address: Configure the sync server host (defaults to
http://roboref.local:8080for venue LAN). All VEX Events queries proxy securely through the sync server.
cd app
flutter test
flutter analyzecd server
npm run typecheck- CalVer Scheme: Releases follow
YYYY.M.D+<commit_count>(e.g.2026.8.27+1). - In-App Changelog: RoboRef dynamically renders release notes directly from app/assets/changeLog.md inside the application.
When modifying or extending RoboRef:
- Clean-Slate Architecture: All code is built fresh with Flutter/Dart and TypeScript/Hono. Do not use legacy referee.fyi code.
- Offline-First Constraint: All user interactions must function completely offline and sync gracefully when connectivity is re-established.
- Changelog Requirement: Any user-facing change (UI adjustments, features, bug fixes) must be documented in app/assets/changeLog.md under the current release/date.
- AI Guidelines: Review AGENTS.md for full context and instructions when using AI coding assistants.