A Flutter mobile application for managing golf scores and leaderboards for social golf societies. Supports regular season play, knockout competitions, offline score capture, and real-time leaderboards.
Note: This project is built with AI-assisted development tools, including Claude Code, for implementation assistance. All code changes are reviewed and committed by human developers who maintain full oversight and decision-making authority.
- Offline-First Score Capture: Record scores during rounds without internet connection
- Real-time Leaderboards: Multiple leaderboard types with live updates
- Tournament Management: Flexible tournament and season structures
- Knockout Competitions: Bracket-based matchplay competitions
- Social Features: Player profiles, chat, and scorecard photos
- Multi-Format Support: Individual and team scoring formats
- Framework: Flutter (latest stable)
- Backend: Supabase (PostgreSQL, Auth, Storage, Realtime)
- State Management: flutter_bloc (BLoC pattern)
- Local Database: Drift (SQLite)
- Architecture: Clean Architecture with Offline-First approach
Before you begin, ensure you have the following installed:
- Flutter SDK (latest stable) - Install Flutter
- Dart SDK (included with Flutter)
- Docker Desktop - Download Docker
- Supabase CLI - Install Guide
- Xcode (macOS, for iOS development) - Available on Mac App Store
- Android Studio (for Android development, optional)
- Git - Install Git
- Node.js 18+ (for documentation site) - Install Node.js
flutter doctor # Check Flutter installation
supabase --version # Should show CLI version
docker --version # Check Docker installation
node --version # Should show v18.x or highergit clone https://github.com/barry47products/mulligans-law.git
cd mulligans-lawflutter pub get# macOS
brew install supabase/tap/supabase
# Windows (via Scoop)
scoop bucket add supabase https://github.com/supabase/scoop-bucket.git
scoop install supabase
# Linux
brew install supabase/tap/supabasesupabase startThis will output important connection details:
API URL: http://localhost:54321
GraphQL URL: http://localhost:54321/graphql/v1
DB URL: postgresql://postgres:postgres@localhost:54322/postgres
Studio URL: http://localhost:54323
Inbucket URL: http://localhost:54324
JWT secret: super-secret-jwt-token-with-at-least-32-characters-long
anon key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
service_role key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Open http://localhost:54323 to access the Supabase Studio dashboard where you can:
- View database tables
- Run SQL queries
- Manage authentication
- View storage buckets
Create lib/core/config/supabase_config.dart:
class SupabaseConfig {
static const String supabaseUrl = 'http://localhost:54321';
static const String supabaseAnonKey = 'your-anon-key-from-supabase-start';
}Note: Replace your-anon-key-from-supabase-start with the actual anon key from the supabase start output.
# Apply all migrations to local database
supabase db reset
# This will:
# - Drop existing database
# - Recreate schema
# - Run all migrations in order
# - Apply seed data (if any)# iOS Simulator
flutter run -d ios
# Android Emulator
flutter run -d android
# Chrome (for web testing)
flutter run -d chromeThis project follows trunk-based development with short-lived feature branches:
# Always start from latest main
git checkout main
git pull origin main
# Create feature branch (named after task from TASKS.md)
git checkout -b feat/score-capture-uiFollow the Red-Green-Refactor cycle with frequent commits:
# Red: Write failing test
git commit -m "test: add failing test for score validation"
# Green: Make it pass
git commit -m "feat(scores): implement score validation"
# Refactor: Improve code
git commit -m "refactor(scores): extract validation logic"# Push to remote (triggers CI)
git push origin feat/score-capture-uiWhen your task is complete:
- Ensure all tests pass locally
- Update documentation if needed
- Create PR via GitHub UI
- Wait for CI to pass
- Self-review your code
- Squash and merge to main
Follow Conventional Commits:
<type>(<scope>): <subject>
[optional body]Types:
feat: New featurefix: Bug fixtest: Add/update testsrefactor: Code restructuring (no behavior change)docs: Documentation changesstyle: Formatting, whitespaceperf: Performance improvementschore: Build, dependencies, toolingci: CI/CD pipeline changes
Examples:
feat(scores): add stableford calculation
fix(sync): handle offline queue correctly
test(leaderboards): add order of merit tests
refactor(auth): simplify login flow
docs: update API documentationThis project uses Test-Driven Development (TDD). Always write tests BEFORE implementation.
# Run all tests
flutter test
# Run with coverage
flutter test --coverage
# View coverage report locally (requires lcov: brew install lcov)
genhtml coverage/lcov.info -o coverage/html && open coverage/html/index.html
# Run specific test file
flutter test test/features/scores/domain/usecases/submit_score_test.dart
# Run tests matching pattern
flutter test --name "score"
# Watch mode (re-run on changes - requires fswatch)
flutter test --watch- P0 Tasks: Report coverage, no enforcement
- P1 Tasks: 70% threshold enforced
- P2+ Tasks: 80% threshold enforced
flutter test --coverage
genhtml coverage/lcov.info -o coverage/html
open coverage/html/index.html # macOS# Analyze code (check for errors)
flutter analyze
# Format code
dart format .
# Run all checks (what CI runs)
flutter analyze && dart format --set-exit-if-changed . && flutter test# Create new migration
supabase migration new add_spot_prizes
# Edit the generated file in supabase/migrations/
# Example: supabase/migrations/20240101000000_add_spot_prizes.sql
# Apply migrations locally
supabase db reset
# View migration status
supabase migration list
# Generate TypeScript types (optional, for Supabase functions)
supabase gen types typescript --local > lib/core/types/database.types.tsAccess the local Supabase Studio at http://localhost:54323:
- Table Editor: View and edit data
- SQL Editor: Run custom SQL queries
- Authentication: Manage users and auth settings
- Storage: Upload and manage files
- API Docs: Auto-generated API documentation
mulligans-law/
├── .github/
│ └── workflows/ # CI/CD pipelines
│ ├── ci.yml # Lint, test, build
│ ├── cd.yml # App deployment (semantic-release)
│ └── deploy-docs.yml # Documentation deployment
├── docs/ # Project documentation
│ ├── functional-spec.md # Feature requirements
│ ├── technical-spec.md # Architecture details
│ ├── GITHUB_SETUP.md # GitHub configuration
│ ├── CODECOV_SETUP.md # Coverage reporting setup
│ ├── DEPLOYMENT.md # CD pipeline and deployment guide
│ └── DOCUSAURUS_SETUP.md # Docs site setup
├── docs-technical/ # Docusaurus documentation site
│ ├── docs/ # Documentation content
│ └── docusaurus.config.ts
├── lib/
│ ├── core/ # Shared utilities, themes, constants
│ │ ├── config/ # App configuration
│ │ ├── constants/ # App-wide constants
│ │ ├── theme/ # App theme
│ │ └── utils/ # Utility functions
│ ├── features/ # Feature modules
│ │ ├── auth/ # Authentication
│ │ ├── scores/ # Score capture
│ │ ├── leaderboards/ # Leaderboards
│ │ └── ...
│ └── main.dart
├── test/
│ ├── features/ # Feature tests (mirrors lib/)
│ ├── integration/ # Integration tests
│ └── helpers/ # Test utilities
├── supabase/
│ ├── migrations/ # Database migrations
│ ├── seed.sql # Seed data
│ └── config.toml # Local Supabase config
├── CLAUDE.md # Claude Code development guidelines
├── TASKS.md # Kanban board of tasks
├── WORKFLOW.md # Development workflow guide
└── README.md # This fileEach feature follows Clean Architecture:
feature/
├── data/
│ ├── models/ # Data models (JSON serialization)
│ ├── datasources/ # Remote & local data sources
│ └── repositories/ # Repository implementations
├── domain/
│ ├── entities/ # Business objects
│ ├── repositories/ # Repository interfaces
│ └── usecases/ # Business logic
└── presentation/
├── bloc/ # State management
├── screens/ # Full screen widgets
└── widgets/ # Reusable widgets- Functional Specification - Complete feature requirements and user stories
- Technical Specification - Architecture and implementation details
- CLAUDE.md - Development guidelines for AI-assisted development
- TASKS.md - Kanban board of tasks (prioritized)
- WORKFLOW.md - Detailed development workflow
- GitHub Setup - GitHub configuration guide
- Docusaurus Setup - Documentation site setup
- Technical Documentation - Docusaurus site with:
- Getting started guides
- Architecture documentation
- API reference
- Feature guides
- Testing strategies
When you add features, update the technical documentation:
cd docs-technical
npm start # Preview locally at http://localhost:3000
# Add your documentation pages
# Commit and push - auto-deploys to GitHub PagesRuns on every push to any branch:
✓ Checkout code
✓ Setup Flutter
✓ Install dependencies
✓ Format check (dart format)
✓ Analyze code (flutter analyze)
✓ Run tests (flutter test)
✓ Generate coverage report
✓ Upload to Codecov
✓ Build Android APK
✓ Build iOS (no codesign)Runs on merge to main:
✓ Run full CI pipeline
✓ Semantic versioning (conventional commits)
✓ Create GitHub Release
✓ Build production APK
✓ Upload to TestFlight (future)
✓ Deploy documentation to GitHub Pages- Tracked via Codecov
- Reports appear in Pull Requests
- Phase 1 (P0): Report only, no enforcement
- Phase 2 (P1): 70% threshold enforced
- Phase 3 (P2+): 80% threshold enforced
Main branch is protected with:
- ✓ Require PR reviews (self-review allowed for solo dev)
- ✓ Require status checks (CI must pass)
- ✓ No force pushes
- ✓ No deletions
Can't connect to Supabase:
# Check if Supabase is running
supabase status
# If not running, start it
supabase start
# Check Docker is running
docker psDatabase issues:
# Reset database (WARNING: deletes all data)
supabase db reset
# View logs
supabase db logsBuild errors:
# Clean build
flutter clean
flutter pub get
# Regenerate generated files
flutter pub run build_runner build --delete-conflicting-outputsDependency conflicts:
# Update dependencies
flutter pub upgrade
# Get exact versions from pubspec.lock
flutter pub getTests failing:
# Run tests with verbose output
flutter test --reporter expanded
# Run single test file
flutter test test/path/to/test_file.dartThis is currently a solo development project. If you'd like to contribute:
- Open an issue to discuss proposed changes
- Wait for approval before starting work
- Follow the development guidelines in CLAUDE.md
- Ensure all tests pass and coverage requirements are met
[To be determined]
[To be determined]
- Built with Flutter - Google's UI toolkit
- Backend powered by Supabase - Open source Firebase alternative
- State management with flutter_bloc
- Local database with Drift
- AI assistance from Claude by Anthropic
- Documentation with Docusaurus