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 synchronise notes seamlessly across peer devices in real-time.
- 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 / Typecheck Sync Server & Cloudflare Worker
.\scripts\build.ps1 server
# Build both Android APK and Server
.\scripts\build.ps1 all
# Build other Flutter targets
.\scripts\build.ps1 appbundle
.\scripts\build.ps1 web
.\scripts\build.ps1 windows# Build Android APK (default target: apk)
./scripts/build.sh apk
# Build / Typecheck Sync Server & Cloudflare Worker
./scripts/build.sh server
# Build both Android APK and Server
./scripts/build.sh all
# Build other Flutter targets
./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 Server & Web, then deploy to Test environment (test D1 database)
.\scripts\deploy.ps1 test
# Build Server & Web, then deploy to Live environment (roboref.app + live D1 database)
.\scripts\deploy.ps1 live
# Deploy existing build without rebuilding
.\scripts\deploy.ps1 test -SkipBuild
# Deploy without rebuilding Flutter Web (e.g. server-only updates)
.\scripts\deploy.ps1 test -SkipWebBuild
# Deploy without rebuilding Server (e.g. web-only updates)
.\scripts\deploy.ps1 test -SkipServerBuild# Build Server & Web, then deploy to Test
./scripts/deploy.sh test
# Build Server & Web, then deploy to Live
./scripts/deploy.sh live
# Deploy with skip options
./scripts/deploy.sh test --skip-build
./scripts/deploy.sh test --skip-web
./scripts/deploy.sh test --skip-server# 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 (eg
https://roboref.app, orhttp://roboref.local:8080). 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.