A web application for managing referee scheduling for club soccer associations.
- Google OAuth2 authentication
- Role-based access (Assignor, Referee, Pending Referee)
- Match schedule management (CSV import from Stack Team App)
- Referee profile management with certification tracking
- Referee availability marking (per-match and full-day)
- Day-level unavailability tracking
- Assignment workflow with conflict detection
- Assignment acknowledgment by referees
- Overdue acknowledgment tracking (>24 hours)
- Mobile-responsive design
All dates and times are stored and displayed in US Eastern Time (America/New_York).
- Stack Team App CSV exports are in Eastern Time
- All match dates and times are treated as Eastern Time
- No timezone conversion is applied - this is appropriate for a local sports club where all matches occur in the Eastern timezone
- Backend: Go 1.22 with Vertical Slice Architecture
- Frontend: SvelteKit
- Database: PostgreSQL 16
- Auth: Google OAuth2
- Deployment: Docker
- Testing: Go testing framework (258 tests, 100% handler/service coverage)
This project uses Vertical Slice Architecture where each feature is organized as a self-contained slice with all its layers (models, repository, service, handler, routes, tests).
Benefits:
- High cohesion within features
- Low coupling between features
- Easy to locate and modify feature code
- Testable with clear boundaries
- Enables parallel development
Key Patterns:
- Dependency injection via interfaces
- Repository pattern for data access
- Service layer for business logic
- Handler layer for HTTP request/response
- Shared infrastructure (config, database, middleware, errors)
📘 See ARCHITECTURE.md for complete architecture documentation
- Docker and Docker Compose
- Google Cloud Project with OAuth2 credentials
- Go to Google Cloud Console
- Create a new project or select an existing one
- Enable the Google+ API:
- Navigate to "APIs & Services" > "Library"
- Search for "Google+ API"
- Click "Enable"
- Create OAuth2 credentials:
- Navigate to "APIs & Services" > "Credentials"
- Click "Create Credentials" > "OAuth client ID"
- Choose "Web application"
- Add authorized redirect URIs:
http://localhost:8080/api/auth/google/callback(for local development)
- Click "Create"
- Copy the Client ID and Client Secret
-
Clone the repository:
git clone <repository-url> cd referee-scheduler
-
Create a
.envfile from the example:cp .env.example .env
-
Edit
.envand add your Google OAuth2 credentials:GOOGLE_CLIENT_ID=your-client-id-here.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=your-client-secret-here -
Start the application with Docker Compose:
docker-compose up --build
-
Access the application:
- Frontend: http://localhost:3000
- Backend API: http://localhost:8080
- Health check: http://localhost:8080/health
Migrations run automatically when the backend starts. Migration files are located in backend/migrations/.
To create a new migration:
- Create two files in
backend/migrations/:XXX_description.up.sql(for applying the migration)XXX_description.down.sql(for rolling back)
- Restart the backend container
By default, new users are created with the pending_referee role. To create an assignor account:
- Sign in with Google to create your user account
- Connect to the database:
docker exec -it referee-scheduler-db psql -U referee_scheduler - Update your user role:
UPDATE users SET role = 'assignor', status = 'active' WHERE email = 'your-email@example.com';
- Exit the database:
\q - Sign out and sign back in to see the assignor dashboard
referee-scheduler/
├── backend/ # Go backend
│ ├── main.go # Application entry point (307 lines)
│ ├── shared/ # Shared infrastructure
│ │ ├── config/ # Configuration management
│ │ ├── database/ # Database connection & migrations
│ │ ├── errors/ # Standard error handling
│ │ ├── middleware/ # HTTP middleware (auth, RBAC, CORS)
│ │ └── utils/ # Shared utilities
│ ├── features/ # Feature slices (vertical architecture)
│ │ ├── users/ # User management & profiles
│ │ ├── matches/ # Match management & CSV import
│ │ ├── assignments/ # Referee assignments
│ │ ├── acknowledgment/ # Assignment acknowledgment
│ │ ├── referees/ # Referee management
│ │ ├── availability/ # Match & day availability
│ │ └── eligibility/ # Eligibility checking
│ ├── migrations/ # Database migrations
│ ├── Dockerfile # Backend container config
│ └── go.mod # Go dependencies
├── frontend/ # SvelteKit frontend
│ ├── src/
│ │ ├── routes/ # SvelteKit routes
│ │ ├── app.html # HTML template
│ │ └── app.css # Global styles
│ ├── Dockerfile # Frontend container config
│ └── package.json # Node dependencies
├── docker-compose.yml # Docker orchestration
├── .env.example # Environment variables template
├── docs/ # All documentation
│ ├── planning/ # PRDs, stories, decompositions
│ ├── guides/ # Setup, developer, deployment guides
│ ├── architecture/ # Architecture & ADRs
│ ├── implementation-reports/ # Epic & story reports
│ └── session-reports/ # Development history
└── README.md # This file
Architecture: This project uses Vertical Slice Architecture where each feature is self-contained with its own models, repository, service, handler, and tests. See ARCHITECTURE.md for details.
-
Backend Development: Go automatically recompiles on changes
docker-compose logs -f backend
-
Frontend Development: Hot module replacement enabled
docker-compose logs -f frontend
-
Run Tests:
cd backend go test ./features/... # Feature tests (258 tests) go test ./shared/... # Shared package tests (31 tests)
-
Database Access:
docker exec -it referee-scheduler-db psql -U referee_scheduler
Follow the vertical slice pattern:
- Create feature directory:
backend/features/myfeature/ - Add models, repository, service, handler, routes
- Write tests (aim for 100% handler/service coverage)
- Register routes in
main.go - Update documentation
📘 See DEVELOPER_GUIDE.md for complete developer onboarding
Database:
\dt- List all tables\d users- Describe users tableSELECT * FROM users;- View all users
Testing:
go test ./features/users -v- Test specific featurego test ./... -cover- Test with coverage reportgo build- Verify compilation
All endpoints organized by feature slice. See ARCHITECTURE.md for implementation details.
GET /health- Health checkGET /api/auth/google- Initiate Google OAuth2 flowGET /api/auth/google/callback- OAuth2 callback handlerPOST /api/auth/logout- Sign out and clear sessionGET /api/auth/me- Get current authenticated user
GET /api/profile- Get current user's full profilePUT /api/profile- Update profile (name, DOB, certification)
POST /api/matches/import/parse- Parse CSV file for previewPOST /api/matches/import/confirm- Confirm and import matchesGET /api/matches- List all matches with filtersPUT /api/matches/{id}- Update match details (date, time, location)POST /api/matches/{match_id}/roles/{role_type}/add- Add role slot to match
GET /api/referees- List all referees with status filteringPUT /api/referees/{id}- Update referee (status, grade, role)
GET /api/matches/{id}/eligible-referees?role={role_type}- Get eligible referees for match/role
POST /api/matches/{match_id}/roles/{role_type}/assign- Assign/reassign/remove refereeGET /api/matches/{match_id}/conflicts?referee_id={id}&role_type={type}- Check assignment conflicts
GET /api/referee/matches- Get eligible matches for current refereePOST /api/referee/matches/{id}/availability- Toggle match availability (available/unavailable/clear)GET /api/referee/day-unavailability- Get all unavailable datesPOST /api/referee/day-unavailability/{date}- Toggle full-day unavailability
POST /api/referee/matches/{match_id}/acknowledge- Acknowledge assignment
GET /api/admin/roles- List all rolesGET /api/admin/permissions- List all permissionsGET /api/admin/users/{id}/roles- Get user's assigned rolesPOST /api/admin/users/{id}/roles- Assign role to userDELETE /api/admin/users/{id}/roles/{roleId}- Revoke role from user
GET /api/admin/audit-logs- Query audit logs with filtersGET /api/admin/audit-logs/export- Export audit logs as CSVPOST /api/admin/audit-logs/purge- Purge old audit logs
- pending_referee: New user awaiting assignor approval (read-only access)
- referee: Active referee who can view matches and mark availability
- assignor: Admin who can manage referees and assign matches
The system uses Role-Based Access Control (RBAC) with granular permissions:
Key Permissions:
can_assign_referees- Manage matches, assignments, and referee detailscan_assign_roles- Manage user roles and permissionscan_view_audit_logs- Access audit log system
Role Assignment:
- Assignors can grant roles to users via the admin interface
- Multiple roles can be assigned to a single user
- Permissions are checked on every API request
See EPIC_1_SUMMARY.md for RBAC implementation details.
- Ensure PostgreSQL container is running:
docker-compose ps - Check database logs:
docker-compose logs db
- Verify your Google OAuth2 credentials in
.env - Ensure the redirect URI matches exactly in Google Cloud Console
- Ensure both containers are running:
docker-compose ps - Check CORS configuration in
backend/main.go - Verify
VITE_API_URLin docker-compose.yml
See DOCS_INDEX.md for a complete guide to all documentation.
Key documents:
- GETTING_STARTED.md - Setup and usage guide
- DEPLOYMENT.md - Production deployment guide
- PROJECT_STATUS.md - Current status (91% complete)
- STORIES.md - All epics and user stories
✅ Epics 1-7 Complete - All core features implemented
✅ V2 Epics 7-8 Complete - Scheduling UI improvements and backend refactoring
Recent Milestones:
- ✅ Epic 1: Role-Based Access Control (RBAC)
- ✅ Epic 2: Audit Logging & Retention
- ✅ Epic 3-6: Core feature set (matches, assignments, availability)
- ✅ Epic 7: Self-hosted deployment infrastructure
- ✅ V2 Epic 7: Scheduling interface improvements (weekend filters, pagination, scroll retention)
- ✅ V2 Epic 8: Vertical slice architecture migration (9/9 stories complete)
Current Architecture: Vertical Slice Architecture with 7 feature slices and shared infrastructure.
See PROJECT_STATUS.md for detailed status.
Private - Club use only