Skip to content
samwduncanPublic

About

Data-driven rowing platform for athletes and coaches — personal training log, AI lineup optimization, seat racing analytics, and team management | React + Express + PostgreSQL

Topics

Resources

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

1,085 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oarbit Logo

oarbit

Data-Driven Lineup Optimization for Competitive Rowing
Modern SaaS platform for coaches who demand precision

Features • Quick Start • Tech Stack • Documentation • Contributing

Version License Node React Build


Overview

oarbit transforms how rowing coaches build boat lineups and analyze team performance. Stop relying on spreadsheets, gut feelings, and institutional knowledge that walks out the door. Start making data-driven decisions with AI-powered recommendations, statistical seat racing analysis, and comprehensive performance tracking.

The Problem

Rowing coaches face constant challenges:

  • Institutional knowledge disappears when coaches leave
  • Erg scores don't predict on-water performance
  • Gut-feel decisions instead of data-driven insights
  • Spreadsheets can't capture complex athlete relationships
  • No objective way to compare athletes across boats

The Solution

oarbit is the only platform that combines:

  • Modern drag-and-drop lineup builder with real-time collaboration
  • AI-powered optimization using genetic algorithms (unique in market)
  • Statistical seat racing with Elo rankings and regression models
  • Unified integrations (Concept2, Strava, Garmin, telemetry devices)
  • Training plan management with periodization and load tracking
  • Race day tools with live timing and standings

Features

🚣 Team Management

  • Multi-tenant architecture - Manage multiple teams with role-based access
  • Athlete profiles - Track personal bests, side preferences, injury history
  • Fleet management - Organize shells by type, condition, and availability
  • User roles - Admin, coach, athlete with granular permissions

📊 Erg Data Tracking

  • Comprehensive test tracking - 2k, 6k, 500m, 30-minute tests
  • Trend visualization - Charts showing performance over time
  • Concept2 integration - OAuth sync with Concept2 Logbook for automatic import
  • Custom workouts - Record any workout type with split data
  • Export capabilities - PDF reports and CSV data exports

🔄 Integration Hub

Integration Status Features
Concept2 ✅ Live OAuth sync, automatic workout import, background sync every 6h
Strava ✅ Live Activity sync, workout upload from Concept2, background sync every 4h
Garmin ✅ Live .FIT file import, multi-file upload support
Telemetry ✅ Live Empower, Peach, NK sensor data import

🧬 AI-Powered Optimization

  • Genetic algorithm - Optimize lineups across multiple constraints
  • Side balancing - Ensure proper port/starboard distribution
  • Speed prediction - Estimate boat speed based on athlete combinations
  • Constraint handling - Respect athlete preferences and physical limitations
  • Local LLM - Privacy-preserving AI with Ollama integration
  • Combined scoring - Unified rankings from erg data, seat racing, and telemetry

📈 Seat Racing & Analytics

  • Elo rating system - Chess-inspired rankings adapted for rowing
  • Piece recording - Log multiple boats in head-to-head racing sessions
  • Margin analysis - Statistical models accounting for conditions
  • Historical tracking - View rating changes across the season
  • Regression analysis - True speed differences with confidence intervals
  • Visual comparisons - Charts showing athlete progression

📅 Training Plans

  • Plan builder calendar - Drag-and-drop workout scheduling
  • Workout library - Pre-built templates for common sessions
  • Athlete assignments - Assign workouts to individuals or groups
  • Load tracking - TSS (Training Stress Score) calculation and visualization
  • Periodization templates - Base, build, peak, taper phases
  • Compliance monitoring - Track completion rates and adherence

🏁 Race Day Tools

  • Race schedule - Timeline view with countdown timers
  • Live results - Real-time race entry and margin calculation
  • Standings calculation - Automatic point totals and rankings
  • Team highlighting - Filter to view only your team's races
  • Margin prediction - Estimate outcomes based on training data

🤝 Real-Time Collaboration

  • Multi-user editing - Multiple coaches editing lineups simultaneously
  • Presence indicators - See who's viewing/editing in real-time
  • Avatar stack - Visual representation of active collaborators
  • WebSocket sync - Instant updates across all connected clients
  • Change history - Audit log of all lineup modifications

Quick Start

Prerequisites

Ensure you have the following installed:

Installation

  1. Clone the repository
git clone https://github.com/samwduncan/RowLab.git
cd RowLab
  1. Install dependencies
npm install
  1. Set up environment variables
cp .env.example .env

Edit .env with your configuration:

# Database
DATABASE_URL=postgresql://user:password@localhost:5432/rowlab

# Authentication
JWT_SECRET=your-secret-key-here
JWT_REFRESH_SECRET=your-refresh-secret-here

# Server
PORT=8000
CLIENT_URL=http://localhost:3001

# AI (optional)
OLLAMA_URL=http://localhost:11434
OLLAMA_MODEL=llama3.2

# Integrations (optional)
CONCEPT2_CLIENT_ID=your-client-id
CONCEPT2_CLIENT_SECRET=your-client-secret
STRAVA_CLIENT_ID=your-client-id
STRAVA_CLIENT_SECRET=your-client-secret
  1. Set up the database
# Run migrations
npx prisma migrate deploy

# Generate Prisma Client
npx prisma generate

# Seed with sample data (optional)
npm run db:seed
  1. Start the development servers
# Start both frontend and backend
npm run dev:full

# Or use tmux for persistent sessions
npm run dev:tmux
  1. Open the application

Visit http://localhost:3001 in your browser.

Docker Deployment

For production or testing with Docker:

# Build and start containers
docker-compose up -d

# View logs
docker-compose logs -f

# Stop containers
docker-compose down

Access the application at http://localhost:3001.

See docs/self-hosted-setup.md for detailed deployment instructions.


Tech Stack

Frontend

Technology Purpose Version
React UI framework with hooks and concurrent rendering 18.2
Vite Fast build tool with HMR 5.0
TailwindCSS Utility-first CSS framework 3.4
Zustand Lightweight state management 4.4
@dnd-kit Accessible drag-and-drop toolkit 6.1
Framer Motion Animation library 11.18
Recharts Composable charting library 2.10
Three.js 3D graphics (boat visualization) 0.160
React Router Client-side routing 6.30
Socket.io Client Real-time WebSocket communication 4.8

Backend

Technology Purpose Version
Express.js Web framework for Node.js 4.18
PostgreSQL Relational database 14+
Prisma Next-gen ORM with type safety 7.2
JWT Token-based authentication 9.0
bcrypt Password hashing 3.0
Helmet Security headers middleware 8.1
Express Rate Limit Rate limiting 8.2
Socket.io Real-time WebSocket server 4.8
Winston Logging library 3.19
Node-cron Scheduled jobs for background sync 4.2

Testing & Quality

Technology Purpose Version
Vitest Unit testing framework 4.0
Testing Library React component testing 16.3
ESLint JavaScript/TypeScript linting 9.39
Prettier Code formatting 3.7
TypeScript Type checking 5.9

External APIs

  • Concept2 API - OAuth integration for logbook sync
  • Strava API - Activity sync and workout uploads
  • Ollama - Local LLM for AI recommendations (optional)
  • Stripe - Subscription billing (planned)

Configuration

Required Environment Variables

# Database Connection
DATABASE_URL=postgresql://user:password@host:port/database

# JWT Secrets (generate secure random strings)
JWT_SECRET=<your-secret-key>
JWT_REFRESH_SECRET=<your-refresh-secret>

# Server Configuration
PORT=8000
CLIENT_URL=http://localhost:3001
NODE_ENV=development

Optional Environment Variables

# AI Features (requires Ollama running)
OLLAMA_URL=http://localhost:11434
OLLAMA_MODEL=llama3.2

# Concept2 Integration
CONCEPT2_CLIENT_ID=<from-concept2-developers>
CONCEPT2_CLIENT_SECRET=<from-concept2-developers>
CONCEPT2_REDIRECT_URI=http://localhost:8000/api/integrations/concept2/callback

# Strava Integration
STRAVA_CLIENT_ID=<from-strava-api>
STRAVA_CLIENT_SECRET=<from-strava-api>
STRAVA_REDIRECT_URI=http://localhost:8000/api/integrations/strava/callback

# Stripe Billing (production)
STRIPE_SECRET_KEY=sk_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_PRICE_ID=price_...

# Email (for notifications)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password

Generating Secrets

# Generate secure random secrets for JWT
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"

Development

Available Scripts

# Development
npm run dev          # Start frontend only (Vite)
npm run server       # Start backend only (Express)
npm run dev:full     # Start both servers concurrently
npm run dev:tmux     # Start in tmux for persistent sessions
npm stop             # Stop all development servers

# Database
npm run db:migrate   # Run Prisma migrations
npm run db:seed      # Seed database with sample data
npm run db:reset     # Reset database and re-seed
npm run db:studio    # Open Prisma Studio (GUI)

# Testing
npm run test         # Run tests in watch mode
npm run test:run     # Run tests once
npm run test:coverage # Run tests with coverage report
npm run test:ui      # Open Vitest UI

# Code Quality
npm run lint         # Run ESLint
npm run lint:fix     # Fix auto-fixable linting issues
npm run format       # Format code with Prettier
npm run format:check # Check code formatting
npm run typecheck    # Run TypeScript type checking
npm run validate     # Run typecheck + lint + test

# Production
npm run build        # Build for production
npm start            # Run production server
npm run preview      # Preview production build

Project Structure

RowLab/
├── src/                        # React frontend source
│   ├── components/             # React components
│   │   ├── ui/                # Base design system components
│   │   │   ├── GlassButton.jsx
│   │   │   ├── GlassModal.jsx
│   │   │   └── SpotlightCard.jsx
│   │   ├── domain/            # Domain-specific components
│   │   │   ├── LineupBoard.jsx
│   │   │   ├── AthleteBank.jsx
│   │   │   └── BoatDisplay.jsx
│   │   └── compound/          # Composite components
│   │       ├── PerformanceModal.jsx
│   │       └── ErgDataModal.jsx
│   ├── pages/                 # Route pages
│   │   ├── Dashboard.jsx
│   │   ├── LineupPage.jsx
│   │   ├── AthletesPage.jsx
│   │   └── TrainingPlansPage.jsx
│   ├── store/                 # Zustand state stores
│   │   ├── useAthleteStore.js
│   │   ├── useLineupStore.js
│   │   └── useAuthStore.js
│   ├── theme/                 # Design tokens and themes
│   │   ├── colors.js
│   │   ├── glassMorphism.js
│   │   └── precisionInstrument.js
│   ├── services/              # API client services
│   │   ├── api.js
│   │   └── auth.js
│   ├── utils/                 # Utility functions
│   │   ├── calculations.js
│   │   └── validators.js
│   ├── App.jsx               # Root component
│   └── main.jsx              # Entry point
├── server/                     # Express backend
│   ├── routes/                # API route handlers
│   │   ├── auth.js
│   │   ├── athletes.js
│   │   ├── lineups.js
│   │   ├── erg-data.js
│   │   ├── seat-racing.js
│   │   ├── training-plans.js
│   │   └── integrations/
│   │       ├── concept2.js
│   │       └── strava.js
│   ├── services/              # Business logic services
│   │   ├── athleteService.js
│   │   ├── lineupService.js
│   │   ├── ergDataService.js
│   │   ├── seatRacingService.js
│   │   ├── aiService.js
│   │   ├── trainingPlanService.js
│   │   └── integrations/
│   │       ├── concept2Service.js
│   │       └── stravaService.js
│   ├── middleware/            # Express middleware
│   │   ├── auth.js
│   │   ├── rateLimiter.js
│   │   ├── validator.js
│   │   └── errorHandler.js
│   ├── socket/                # WebSocket handlers
│   │   └── collaboration.js
│   ├── jobs/                  # Background jobs
│   │   └── syncJobs.js
│   ├── utils/                 # Server utilities
│   │   ├── logger.js
│   │   └── encryption.js
│   └── index.js              # Server entry point
├── prisma/                     # Database schema and migrations
│   ├── schema.prisma          # Prisma schema definition
│   ├── migrations/            # Migration history
│   └── seed.js               # Database seeding script
├── docs/                       # Documentation
│   ├── api/                   # API documentation
│   │   ├── README.md
│   │   ├── auth.md
│   │   └── endpoints.md
│   ├── database/              # Database documentation
│   │   ├── README.md
│   │   └── schema.md
│   ├── components/            # Component documentation
│   │   └── README.md
│   ├── services/              # Service documentation
│   │   └── README.md
│   └── self-hosted-setup.md  # Deployment guide
├── public/                     # Static assets
│   └── images/
│       └── logo.svg
├── scripts/                    # Utility scripts
│   ├── dev.sh                # tmux dev environment
│   └── stop-dev.sh           # Stop dev servers
├── tests/                      # Test files (mirrors src/)
│   ├── unit/
│   ├── integration/
│   └── e2e/
├── .env.example               # Environment template
├── .gitignore                 # Git ignore rules
├── docker-compose.yml         # Docker configuration
├── package.json               # Dependencies and scripts
├── vite.config.js            # Vite configuration
├── tailwind.config.js        # Tailwind configuration
├── vitest.config.js          # Vitest configuration
├── CONTRIBUTING.md           # Contribution guidelines
├── LICENSE                   # MIT License
└── README.md                 # This file

Design System: Canvas

oarbit uses the Canvas design system — a warm, precision-focused aesthetic:

  • Warm copper & warm dark - Premium visual identity inspired by athletic instruments
  • Glass cards - Subtle backdrop blur with chamfered panel styling
  • Port/Starboard semantics - Red (port) and green (starboard) following maritime conventions
  • Gradient borders & text gradients - Refined visual hierarchy
  • High contrast text - WCAG 2.1 AA compliant
  • Mobile responsive - Layouts adapt from 375px to 1440px

Design tokens are defined in src/theme/ and evolved through v2.1-v3.0.

Writing Tests

oarbit uses Vitest and Testing Library. Place tests adjacent to source files:

src/
├── components/
│   ├── AthleteCard.jsx
│   └── AthleteCard.test.jsx  # Component test
└── services/
    ├── athleteService.js
    └── athleteService.test.js  # Service test

Example component test:

import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import AthleteCard from './AthleteCard';

describe('AthleteCard', () => {
  it('renders athlete name', () => {
    const athlete = { id: 1, name: 'John Smith' };
    render(<AthleteCard athlete={athlete} />);
    expect(screen.getByText('John Smith')).toBeInTheDocument();
  });
});

Run tests with npm run test.

Code Style

  • ESLint enforces consistent code style
  • Prettier formats code automatically
  • TypeScript (gradual migration) for type safety
  • Follow React best practices (hooks, functional components)
  • Use JSDoc comments for documentation

Contributing

We welcome contributions! See CONTRIBUTING.md for detailed guidelines on:

  • Reporting bugs and suggesting features
  • Contributing code
  • Code style, testing, and validation
  • Commit message conventions
  • Pull request process

Quick path:

  1. Fork and create a feature branch: git checkout -b feature/your-feature-name
  2. Make your changes and validate: npm run validate
  3. Commit with clear messages: git commit -m "type(scope): description"
  4. Push and open a pull request

Good places to start: Look for issues labeled good first issue or help wanted.


Roadmap

oarbit is actively developed across milestone releases. Here's where we are and where we're headed.

v1.0 — Full UX Redesign ✅

Ground-up rebuild with multi-persona Workspace/Context architecture.

  • V2 foundation with design tokens and CSS isolation
  • Application shell with context-aware navigation (Me/Coach/Admin)
  • Personal dashboard with Concept2 and Strava integration
  • Coach features migration (whiteboard, fleet, availability)
  • V2 default at /app, V1 fallback at /legacy

v2.0 — Core Migration ✅

Complete V1-to-V2 feature migration with "Precision Instrument" design philosophy.

  • Athletes and roster management with bulk CSV import
  • Erg data tracking with trend charts and Concept2 sync
  • Drag-and-drop lineup builder with undo/redo and PDF export
  • Seat racing with Elo rankings and confidence intervals
  • Training plans with periodization and NCAA 20-hour compliance
  • Racing and regattas with race day command center
  • Settings, photo uploads, and design polish (WCAG 2.1 AA)
  • Cross-feature integrations (global search, live erg, unified activity feed)
  • Advanced seat racing analytics (Bradley-Terry model, matrix planner, passive Elo)

v2.1 — Feature Expansion ✅

Feature toggles, gamification, warm color design system, and lineup improvements.

  • Feature toggles and recruit visit management
  • Gamification (achievements, PRs, team challenges, streaks)
  • Lineup and boat configuration improvements (rigging, templates, comparison)
  • Warm color design system and landing page

v3.0 — Canvas Design & Mobile ✅

Complete frontend redesign with Canvas design system, mobile responsiveness, and clean-up.

Key deliverables:

  • Canvas Design System — Warm copper aesthetic with glass cards, chamfered panels, gradient borders
  • Mobile-First Responsive — All pages responsive from 375px to 1440px
  • State Management Migration — TanStack Query v5 for server state
  • Performance Optimization — Dead code cleanup, bundle optimization, Web Vitals
  • V1 Code Removal — 208 files deleted, 5.7% bundle reduction

14 phases completed (Phase 24–36.1).

v3.1 — Integrations & Analytics ✅

Concept2 Logbook sync, Strava integration, share cards, and performance analytics.

  • Concept2 Workout Sync (Phase 37)
  • Share Card Platform (Phase 38)
  • Strava Integration & Cross-Platform Sync (Phase 39)
  • Performance Analytics Engine (Phase 40)
  • Fitness Intelligence & Training Load (Phase 41)
  • Garmin Connect & On-Water Data (Phase 42)

v4.0 — Identity & Experience Restructure ✅

Clean-slate frontend (React 19 + TanStack Router + Tailwind v4) with athlete-first architecture. 52 of 53 phases shipped; Phase 53 shelved. Superseded by v5.0 focused remediation.

  • Athlete-first personal training log (standalone, team optional)
  • React 19 + TanStack Router with file-based routing
  • Tailwind v4 with oklch color space design tokens
  • Team lifecycle — create, join, switch, and manage teams
  • Personal dashboard, workout tracking, personal records
  • Coach tools migration — lineups, seat racing, fleet, training plans
  • OAuth integrations — Concept2 and Strava sync

v5.0 — Audit Remediation & Spec Compliance 🚧 In Progress

Targeted fixes from a 24-agent audit swarm. No new features — fix, polish, and harden what exists to meet the full oarbit design spec.

  • Phase 54: Security hardening (2 CRITICAL, 4 HIGH vulnerabilities patched)
  • Phase 55: Critical bug fixes (React hooks, API shape mismatches, race conditions)
  • Phase 56: Build and code quality (62 TypeScript errors fixed, ESLint configured)
  • Phase 57: Design surfaces and colors (GlassCard migrated, banned CSS eliminated)
  • Phase 58: Typography, icons, and assets (Space Grotesk enforced, lucide-react removed)
  • Phase 59: Signature design identity (corner brackets, diamond markers, warm rules)
  • Phase 60: Animation and motion compliance (banned patterns removed, reduced-motion)
  • Phase 61: Error handling and resilience (ErrorBoundary, route error components)
  • Phase 62: Settings and auth gaps (notification/privacy prefs wired, password change, account deletion)
  • Phase 63: Navigation and search (phantom routes removed, real data Cmd+K search)
  • Phase 64: Backend API consistency
  • Phase 65: Notifications and social pipeline
  • Phase 66: Calendar unification
  • Phase 67: Concept2 data and export
  • Phase 68: Coach tools completion
  • Phase 69: Final verification sweep

Feature Comparison

Feature oarbit RegattaCentral CrewLAB iCrew
Modern UI ✅ ❌ ⚠️ ❌
AI Lineup Optimization ✅ ❌ ❌ ❌
Seat Racing Analytics ✅ ❌ ⚠️ ❌
Real-Time Collaboration ✅ ❌ ❌ ❌
Concept2 Integration ✅ ❌ ❌ ❌
Strava Integration ✅ ❌ ❌ ❌
Training Plans + NCAA ✅ ❌ ❌ ❌
Gamification ✅ ❌ ❌ ❌
Telemetry Import 🚧 Planned ❌ ✅ ❌
Mobile Responsive ✅ ❌ ❌ ❌
Self-Hosted ✅ ❌ ❌ ❌

Documentation

Comprehensive documentation is available in the /docs directory:

Document Description
API Reference Complete REST API documentation with examples
Database Schema Prisma models, relationships, and migrations
Component Guide React component documentation and usage
Services Guide Backend service layer documentation
Self-Hosted Setup Production deployment instructions
Design System Canvas design tokens and styling (see Design System section)

Community & Support

Get Help

Stay Updated

  • Star this repository to get updates
  • Watch releases for new versions
  • Follow the roadmap in the Roadmap section above

License

oarbit is open source software licensed under the MIT License.

MIT License

Copyright (c) 2026 oarbit Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Acknowledgments

oarbit is built with excellent open source tools and inspired by great products:

  • Concept2 - For providing the erg data API
  • Ollama - For local LLM inference
  • @dnd-kit - For accessible drag-and-drop
  • Prisma - For the excellent ORM
  • Linear - Design inspiration for the Precision Instrument aesthetic
  • Raycast - Command palette and UI patterns
  • Cal.com - Open source SaaS reference

Special thanks to all contributors who help make oarbit better.


Target Audience

oarbit is designed for competitive rowing programs:

  • Collegiate Programs - 250+ NCAA/ACRA programs nationally
  • Club Teams - 2,000+ competitive club programs
  • High School - Growing varsity programs
  • Masters - Competitive adult rowing clubs
  • National Teams - Elite-level training programs

Why Coaches Choose oarbit

Traditional Approach oarbit
Spreadsheets and paper Modern drag-and-drop interface
Gut-feel decisions Data-driven AI recommendations
Lost knowledge when coaches leave Persistent, searchable history
No objective athlete comparisons Elo-based seat racing rankings
Manual data entry Concept2 sync, telemetry import
Static lineups Real-time collaborative editing

oarbit — Built for coaches who demand precision

⭐ Star on GitHub • 🐛 Report Bug • 💡 Request Feature

Made with ❤️ by the oarbit community

About

Data-driven rowing platform for athletes and coaches — personal training log, AI lineup optimization, seat racing analytics, and team management | React + Express + PostgreSQL

Topics

Resources

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages