Data-Driven Lineup Optimization for Competitive Rowing
Modern SaaS platform for coaches who demand precision
Features • Quick Start • Tech Stack • Documentation • Contributing
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.
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
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
- 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
- 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 | 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 |
- 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
- 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
- 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 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
- 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
Ensure you have the following installed:
- Node.js 18.x or higher (Download)
- PostgreSQL 14+ (Download or use Docker)
- Git (Download)
- Ollama (optional, for AI features) (Download)
- Clone the repository
git clone https://github.com/samwduncan/RowLab.git
cd RowLab- Install dependencies
npm install- Set up environment variables
cp .env.example .envEdit .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- 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- Start the development servers
# Start both frontend and backend
npm run dev:full
# Or use tmux for persistent sessions
npm run dev:tmux- Open the application
Visit http://localhost:3001 in your browser.
For production or testing with Docker:
# Build and start containers
docker-compose up -d
# View logs
docker-compose logs -f
# Stop containers
docker-compose downAccess the application at http://localhost:3001.
See docs/self-hosted-setup.md for detailed deployment instructions.
| 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 |
| 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 |
| 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 |
- 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)
# 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# 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# Generate secure random secrets for JWT
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"# 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 buildRowLab/
├── 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
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.
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.
- 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
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:
- Fork and create a feature branch:
git checkout -b feature/your-feature-name - Make your changes and validate:
npm run validate - Commit with clear messages:
git commit -m "type(scope): description" - Push and open a pull request
Good places to start: Look for issues labeled good first issue or help wanted.
oarbit is actively developed across milestone releases. Here's where we are and where we're headed.
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
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)
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
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).
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)
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
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 | 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 | ✅ | ❌ | ❌ | ❌ |
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) |
- Documentation - Check docs/ for guides and references
- GitHub Issues - Search existing issues or open a new one
- GitHub Discussions - Ask questions and share ideas
- Star this repository to get updates
- Watch releases for new versions
- Follow the roadmap in the Roadmap section above
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.
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.
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
| 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