🏆 Tournament Manager

🏆 Access Tournament Manager

🚀 Launch Tournament Manager

Professional tournament management with real-time brackets

Overview

Tournament Manager is a comprehensive tournament management system built specifically for the Playtopia Dev Lab infrastructure. It provides complete tournament organization capabilities with support for multiple tournament formats, real-time bracket updates, and seamless integration with Authelia for authentication and user management.

🏆 Core Tournament Features

🎮 Tournament Format Support


🏗️ Technical Architecture

Technology Stack

Component Technology Purpose
Backend API Express.js + TypeScript Comprehensive REST API with validation and error handling
Database PostgreSQL 16 + Prisma ORM Robust data management with type-safe database operations
Frontend React 18 + TypeScript + Material-UI Modern responsive interface with component library
Authentication Authelia ForwardAuth Integration Header-based user authentication with role mapping
Real-time Socket.io Live tournament updates and bracket synchronization
Deployment Docker Multi-Container Production containers with nginx and PostgreSQL
SSL/Proxy Traefik v3.0 Automatic HTTPS with Let’s Encrypt certificate management

Multi-Service Architecture

Frontend Service (tournaments.playtopia.com.au)

# Tournament management interface
server {
    listen 80;
    root /usr/share/nginx/html;
    index index.html;
    
    # API proxy to backend
    location /api {
        proxy_pass http://backend:5000;
        proxy_set_header Remote-User $http_remote_user;
        proxy_set_header Remote-Email $http_remote_email;
        proxy_set_header Remote-Name $http_remote_name;
        proxy_set_header Remote-Groups $http_remote_groups;
    }
    
    # WebSocket support for real-time updates
    location /socket.io/ {
        proxy_pass http://backend:5000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Backend API Service

# Express.js API with Authelia integration
tournament-backend:
  build: ./tournament-manager/backend
  container_name: tournament-backend
  environment:
    - DATABASE_URL=postgresql://tournament_user:tournament_password@tournament-database:5432/tournament_db
    - FRONTEND_URL=https://tournaments.playtopia.com.au
  labels:
    - traefik.http.routers.tournament-api.middlewares=authelia-with-headers
    - traefik.http.routers.tournament-api.rule=Host(`tournaments.playtopia.com.au`) && PathPrefix(`/api`)

Core API Architecture

Authentication Middleware

// Authelia ForwardAuth integration
interface AutheliaUser {
  id: string;
  name: string;
  email: string;
  username: string;
  groups: string[];
  role: 'ADMIN' | 'TOURNAMENT_ORGANIZER' | 'PARTICIPANT';
}

export const authenticateUser = async (req: Request, res: Response, next: NextFunction) => {
  // Extract user from Authelia ForwardAuth headers
  const remoteUser = req.headers['remote-user'] as string;
  const remoteEmail = req.headers['remote-email'] as string;
  const remoteName = req.headers['remote-name'] as string;
  const remoteGroups = req.headers['remote-groups'] as string;

  if (remoteUser && remoteEmail) {
    // Map Authelia groups to tournament roles
    const role = mapUserRole(remoteGroups ? remoteGroups.split(',') : ['users']);
    
    const user: AutheliaUser = {
      id: remoteUser,
      name: remoteName || remoteEmail,
      email: remoteEmail,
      username: remoteUser,
      groups: remoteGroups ? remoteGroups.split(',') : ['users'],
      role
    };

    req.user = user;
    return next();
  }

  res.status(401).json({ error: 'Authentication required' });
};

Tournament Management System

// Advanced tournament bracket generation
class TournamentService {
  async generateMatches(tournament: Tournament) {
    const { participants, tournamentType, bracketSize } = tournament;
    
    switch (tournamentType) {
      case 'SINGLE_ELIMINATION':
        return this.generateSingleElimination(participants, bracketSize);
      case 'DOUBLE_ELIMINATION':
        return this.generateDoubleElimination(participants, bracketSize);
      case 'ROUND_ROBIN':
        return this.generateRoundRobin(participants);
      case 'SWISS_SYSTEM':
        return this.generateSwissSystem(participants);
    }
  }
  
  async updateMatchResult(matchId: string, result: MatchResult) {
    // Validate match result and update bracket
    const match = await this.validateMatchResult(matchId, result);
    const updatedMatch = await this.processMatchResult(match, result);
    
    // Emit real-time update via Socket.io
    this.io.to(`tournament_${match.tournamentId}`)
      .emit('match_updated', {
        matchId: updatedMatch.id,
        match: updatedMatch,
        timestamp: new Date().toISOString()
      });
      
    return updatedMatch;
  }
}

Database Schema (Prisma)

model Tournament {
  id                  String            @id @default(cuid())
  name                String
  description         String?
  tournamentType      TournamentType
  bracketSize         Int
  maxParticipants     Int
  status              TournamentStatus  @default(DRAFT)
  registrationDeadline DateTime?
  startDate           DateTime?
  endDate             DateTime?
  isPublic            Boolean           @default(true)
  ruleset             Json?
  createdAt           DateTime          @default(now())
  updatedAt           DateTime          @updatedAt

  creator             User              @relation("TournamentCreator", fields: [creatorId], references: [id])
  creatorId           String
  participants        Participant[]
  matches             Match[]
  rules               Rule[]
}

model Match {
  id              String      @id @default(cuid())
  roundNumber     Int
  matchNumber     Int
  bracketType     BracketType @default(MAIN)
  participant1Score Int?
  participant2Score Int?
  status          MatchStatus @default(PENDING)
  scheduledTime   DateTime?
  completedTime   DateTime?
  matchData       Json?

  tournament      Tournament   @relation(fields: [tournamentId], references: [id])
  tournamentId    String
  participant1    Participant? @relation("Participant1", fields: [participant1Id], references: [id])
  participant1Id  String?
  participant2    Participant? @relation("Participant2", fields: [participant2Id], references: [id])
  participant2Id  String?
  winner          Participant? @relation("MatchWinner", fields: [winnerId], references: [id])
  winnerId        String?
}

enum TournamentType {
  SINGLE_ELIMINATION
  DOUBLE_ELIMINATION
  ROUND_ROBIN
  SWISS_SYSTEM
}

File Structure

/home/thrax/unified-services/tournament-manager/
├── backend/
│   ├── Dockerfile                     # Production Express.js container
│   ├── package.json                   # Node.js dependencies and scripts
│   ├── prisma/
│   │   ├── schema.prisma             # Database schema definition
│   │   └── migrations/               # Database migration files
│   └── src/
│       ├── server.ts                 # Express server with Socket.io integration
│       ├── middleware/
│       │   └── auth.ts               # Authelia ForwardAuth middleware
│       └── routes/
│           ├── auth.ts               # Authentication endpoints
│           ├── tournaments.ts        # Tournament CRUD operations
│           ├── participants.ts       # Participant management
│           ├── matches.ts            # Match results and bracket generation
│           ├── rules.ts              # Tournament rules management
│           └── users.ts              # User profiles and statistics
├── frontend/
│   ├── Dockerfile                    # Production React container (nginx)
│   ├── nginx.conf                    # API proxy and WebSocket configuration
│   ├── package.json                  # React dependencies
│   └── src/
│       ├── App.tsx                   # Main React application
│       ├── components/
│       │   └── Layout.tsx            # Navigation and layout structure
│       └── pages/
│           ├── HomePage.tsx          # Landing page with feature overview
│           ├── TournamentsPage.tsx   # Tournament listing and management
│           ├── TournamentDetailPage.tsx # Individual tournament view
│           └── ProfilePage.tsx       # User profile and statistics
└── README.md                         # Comprehensive project documentation

🎮 Tournament Management Features

Tournament Creation & Configuration

Tournament Setup

Bracket Generation

// Intelligent bracket size calculation
const calculateBracketSize = (participants: number, type: TournamentType): number => {
  switch (type) {
    case 'SINGLE_ELIMINATION':
    case 'DOUBLE_ELIMINATION':
      return Math.pow(2, Math.ceil(Math.log2(participants))); // Next power of 2
    case 'ROUND_ROBIN':
      return participants; // Everyone plays everyone
    case 'SWISS_SYSTEM':
      return participants; // Pairing-based system
    default:
      return participants;
  }
};

Participant Management

Registration System

Participant Information

Match Management & Results

Match Result Processing

// Comprehensive match result validation
const updateMatchResult = async (matchId: string, result: MatchResult) => {
  // Validate permissions
  if (!canUpdateMatch(user, match)) {
    throw new Error('Not authorized to update this match');
  }
  
  // Process result and update bracket
  const updatedMatch = await processMatchResult(match, result);
  
  // Generate next round matches if bracket round completed
  if (await isRoundComplete(match.tournamentId, match.roundNumber)) {
    await generateNextRoundMatches(match.tournamentId);
  }
  
  return updatedMatch;
};

Real-time Updates


🚀 Deployment & Integration

Docker Compose Configuration

# Tournament Manager Services
tournament-frontend:
  build: ./tournament-manager/frontend
  container_name: tournament-frontend
  networks:
    - services-network
  labels:
    - traefik.http.routers.tournament-manager.rule=Host(`tournaments.playtopia.com.au`)
    - traefik.http.routers.tournament-manager.middlewares=authelia-with-headers
    - traefik.http.routers.tournament-manager.tls.certresolver=letsencrypt

tournament-backend:
  build: ./tournament-manager/backend
  container_name: tournament-backend
  environment:
    - DATABASE_URL=postgresql://tournament_user:tournament_password@tournament-database:5432/tournament_db
    - FRONTEND_URL=https://tournaments.playtopia.com.au
  depends_on:
    - tournament-database

tournament-database:
  image: postgres:16-alpine
  container_name: tournament-database
  environment:
    - POSTGRES_DB=tournament_db
    - POSTGRES_USER=tournament_user
    - POSTGRES_PASSWORD=tournament_password
  volumes:
    - tournament_postgres_data:/var/lib/postgresql/data

Performance & Security

API Security

Database Optimization

Development Workflow

# Deploy Tournament Manager services
cd /home/thrax/unified-services
docker-compose up -d tournament-frontend tournament-backend tournament-database

# Run database migrations
docker-compose exec tournament-backend npx prisma migrate deploy

# Generate Prisma client
docker-compose exec tournament-backend npx prisma generate

# View service logs
docker-compose logs -f tournament-backend
docker-compose logs -f tournament-frontend

# Access database for debugging
docker-compose exec tournament-database psql -U tournament_user -d tournament_db

📊 API Documentation

Authentication Endpoints

Tournament Management

Participant Operations

Match Management

Rules & Configuration

User Management


📊 Development Status

Production Ready Components

Backend API: 100% Complete

Database Schema: 100% Complete

Infrastructure: 100% Complete

Frontend Structure: Basic Complete

🏆 System Status: PRODUCTION READY FOR BASIC USE

Tournament Manager delivers a complete tournament management platform with:

🎯 Next Development Phase

Frontend Enhancement (Ready for development):

  1. Tournament Dashboard: Complete tournament listing and management interface
  2. Bracket Visualization: Interactive tournament brackets with real-time updates
  3. User Experience: Enhanced mobile responsiveness and user interaction flows
  4. Advanced Features: Tournament templates, statistics dashboards, and export functionality

Tournament Manager represents a comprehensive tournament management solution with professional-grade backend infrastructure, authentication integration, and real-time capabilities. The system is production-ready for API-based tournament management and prepared for continued frontend development.