Skip to content

vgebrev/leagr

Repository files navigation

Leagr

A little SvelteKit 5 web app to help organise social 5-a-side [football] leagues.

Features include:

  • League Management
    • Subdomain-based league registration.
    • Access-controlled league isolation.
    • Mailgun integration for sending email (Access code recovery).
  • Player Management
    • View and manage player availability.
    • Waiting list after a limit is reached.
    • Moving players between lists.
    • Player renaming capability.
    • Quick-access player information modals.
  • Team Management
    • Generate random teams, either completely random or using player ELO as seeds.
    • AI-generated team logos using OpenAI's Images API (Requires an OpenAI API Key, disabled by default).
    • Provisional rating system ensures balanced teams even with new players.
    • Multi-iteration team generation algorithm that maximises team variance and balance using attack/defense ratings.
    • Visual indicators for provisional vs. established players.
    • Team attack/defense rating displays.
    • Replay team draws for dramatic effect.
    • Players can be moved from a team to the waiting list (and vice versa), removed, renamed, or marked as a no-show.
    • Quick-access team information modals.
  • Discipline
    • Automatic suspension of players after no-shows.
  • Game Scheduling and Score Tracking
    • Generate a round-robin home-away match schedule and track results.
    • Match Centre page for live stats tracking (goals, attack/defence contributions, and saves).
    • Individual goal-scorer tracking with interactive popover UI (league + knockout matches).
    • Standings table based on match results.
    • Knockout tournament generation with teams seeded by standings.
    • Stars of the Day awards players with the most contributions across a session's league and knockout cup phases.
  • Player Rankings
    • Cumulative player rankings based on team performances and consistency.
    • Player ELO with provisional ratings system for new players (<5 sessions).
    • Attack/defense ratings displayed on player profiles and teams.
    • Individual attack/defence ratings derived from team goals for/against across sessions.
    • Performance tracking: league positions, cup progress, win streaks, and achievements.
    • Player profile modals - ranking details, history, profile photos (Admin-approved), and performance stats accessible throughout the app.
    • Champions hall: tracks league and cup winners (yearly and all-time views).
    • Golden boot: tracks league and cup goal scorers (yearly and all-time views).
    • Annually reset rankings to keep competition fresh and motivating.
  • Year Recap
    • An annual highlight reel of the league
    • Individual Categories
    • Team Categories
    • Fun/Stats Categories
    • Background Music

Environment Setup

Data is stored as JSON files in the data directory. For dev, make sure it exists in the root of the project.

For development (needs Node.js):

  • npm ci - Ensures dependencies are installed.
  • npm run dev - Starts the dev server. The app is available at http://localhost:5173.
  • npm run dev -- --host - Starts the dev server and allows access from other devices on your network (useful for mobile testing, or if you're using WSL).
  • npm test - Runs all tests (backend + frontend).
  • npm run test:backend - Runs backend tests only.
  • npm run test:frontend - Runs frontend tests only.
  • npm run check - Type checking.
  • npm run lint - Code linting.
  • npm run format - Code formatting.

Subdomain Setup

Since leagues are registered/accessed on subdomains, it's useful to set up your hosts file to test locally:

# Add to /etc/hosts (Linux/Mac) or C:\Windows\System32\drivers\etc\hosts (Windows)
127.0.0.1 leagr.local
127.0.0.1 league1.leagr.local
127.0.0.1 league2.leagr.local

# If you're using WSL, you need the WSL Network IP
172.21.184.1 leagr.local
172.21.184.1 league1.leagr.local

Then you can access the app at http://leagr.local:5173, http://league1.leagr.local:5173, etc.

Security Configuration

The application includes rudimentary security features to prevent abuse:

CORS Protection

  • ALLOWED_ORIGIN: Comma-separated list of allowed origins for cross-origin requests
  • Only specified origins can access the API endpoints
  • Example: https://your-production-url.com,http://localhost:3000

Semi-public API Key Authentication

  • API_KEY: Required for all API endpoint access
  • Must be provided via X-API-KEY header
  • Example: a1b2c3d4-e5f6-7890-abcd-ef1234567890

Access Code Authorisation

  • Each league has a unique access code
  • To access the league, the access code must be provided in a "code" query parameter, or the user is redirected to a login page
  • Access code must be included in an Authorization header of API requests
  • Access codes can be reset if an organiser/owner email is set up for the league

Rate Limiting

  • Built-in rate limiting: 60 requests per minute per IP address
  • Automatically blocks excessive requests with HTTP 429 status

Testing

The application includes comprehensive automated testing:

  • 1000+ tests covering backend logic and frontend components
  • Backend tests use Node environment (unit and integration tests)
  • Frontend tests use jsdom environment (component and store tests)
  • Automated test execution runs before every deployment
  • Tests must pass before deployment succeeds

Production Deployment

For production (needs Docker):

  • Build a docker image with a production build of the app
  • Note: Automated tests run during the build process and must pass
docker build -t leagr:latest
docker run -d \
  --name leagr \
  --restart unless-stopped \
  -p 3000:3000 \
  -v /path/to/data/on/host:/app/data \
  -v /path/to/logs/on/host:/app/logs \
  -e ALLOWED_ORIGIN="https://your-production-url.com,http://localhost:3000" \
  -e API_KEY="a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -e APP_URL="https://your-production-url.com" \
  -e MAILGUN_SENDING_KEY="your-mailgun-sending-key" \
  -e MAILGUN_DOMAIN="your-mailgun-domain.com" \
  -e BODY_SIZE_LIMIT=6291456 \
  -e LOG_LEVEL="info" \
  -e OPENAI_API_KEY="sk-..." \
  leagr:latest

Expose the app to the internet by configuring your web server or reverse proxy (e.g. Nginx, Apache) to forward requests to port 3000.

Environment Variables:

  • ALLOWED_ORIGIN: Comma-separated allowed origins (required for CORS protection)
  • API_KEY: Secure API key for endpoint access (required for API authentication)
  • APP_URL: The base URL of your application (used for generating links in emails)
  • MAILGUN_SENDING_KEY: Mailgun API key for sending emails
  • MAILGUN_DOMAIN: Mailgun domain for sending emails
  • BODY_SIZE_LIMIT: Maximum request body size in bytes (default: 524288 / 512KB). Set to 6291456 (6MB) for avatar uploads
  • LOGS_DIR: Directory path for application logs (default: /app/logs). Mount as volume for persistent logs
  • LOG_LEVEL: The level of logging messages to keep in the application log. Possible values: debug, info, warn, or error (default: info)
  • OPENAI_API_KEY: An active OpenAI API Key for team logo generation

Notes:

  • Replace /path/to/data/on/host with the actual path to the data directory on your host machine
  • Replace /path/to/logs/on/host with the actual path to the logs directory on your host machine
  • Replace a1b2c3d4-e5f6-7890-abcd-ef1234567890 with a secure, randomly generated API key
  • Replace the allowed origins, app URL with your actual domain(s)
  • Replace Mailgun credentials with your actual Mailgun account details
  • The BODY_SIZE_LIMIT is set to 6MB (6291456 bytes) to support avatar uploads up to 5MB

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Organise your social sports leagues with Leagr.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors