Overview
Showdown Trivia follows a clean architecture approach with a clear separation between business logic, infrastructure, and presentation layers. The project is organized following Go best practices with a modular structure.Directory Layout
Core Directories Explained
cmd/web
The application entry point at cmd/web/main.go. This is where:
- Configuration is loaded
- Dependencies are initialized (database, services, metrics)
- The web application is bootstrapped and started
- Graceful shutdown is handled
- Initialize Prometheus registry
- Connect to MongoDB
- Wire up services (user, question, game)
- Create session store
- Start the HTTP server
internal/core
The business logic layer following Domain-Driven Design principles.
internal/core/entities
Domain entities and value objects that represent core business concepts.
internal/core/game
Game management logic:
- Game state management
- Game lifecycle (start, end, scoring)
- Game rules and validation
- Player management within games
domain.go, game.go, service.go, game_test.go
internal/core/question
Question service that handles:
- Fetching questions from external API
- Question format validation
- Question difficulty management
domain.go, interfaces.go, service.go
internal/core/user
User management:
- User registration and authentication
- User profile management
- User validation
domain.go, interfaces.go, service.go
internal/repository
Data access layer that abstracts database operations:
- MongoDB connection management
- User persistence
- Repository pattern implementation
store.go, user.go
internal/web
The HTTP/WebSocket layer handling all web interactions.
internal/web/handlers
HTTP request handlers for:
- Authentication (signin, signup, signout)
- Game creation and joining
- Active games listing
- Form rendering and processing
internal/web/ws
WebSocket management:
- Hub pattern for connection management
- Real-time game state broadcasting
- Client connection lifecycle
- Room-based messaging
hub.go, hub_test.go, client.go, message.go
internal/web/metrics
Prometheus metrics instrumentation:
- Active WebSocket connection gauge
- HTTP request duration histogram
- Custom metrics registration
metrics.go
internal/web/static
Static assets served by the application:
- CSS files (Tailwind output)
- JavaScript files
- Images and icons
internal/web/views
HTML templates (likely using templ or similar):
- Page layouts
- Component templates
- Partials and fragments
internal/config
Centralized configuration management:
- Environment variable loading
- Configuration validation
- Default values
- Server port
- Database URL
- Log level
- Environment (dev/prod)
internal/logger
Structured logging wrapper:
- Consistent log formatting
- Log level management
- Context-aware logging
internal/trivia_api
External API client for fetching trivia questions:
- HTTP client wrapper
- API response parsing
- Error handling
- Rate limiting (if applicable)
trivia_api.go, trivia_api_test.go, question.go, error.go
Code Organization Patterns
Clean Architecture Layers
- Domain Layer (
internal/core): Pure business logic, no external dependencies - Application Layer (
internal/coreservices): Use cases and business workflows - Infrastructure Layer (
internal/repository,internal/trivia_api): External integrations - Presentation Layer (
internal/web): HTTP/WebSocket handlers and views
Dependency Flow
Interface-Based Design
Services define interfaces (ininterfaces.go files) that:
- Enable dependency injection
- Facilitate testing with mocks
- Decouple layers
- Make the codebase more maintainable
File Naming Conventions
domain.go- Domain entities and value objectsservice.go- Business logic implementationinterfaces.go- Interface definitions*_test.go- Test fileserror.go- Custom error types
Configuration Files
.air.toml
Hot reload configuration for development. Watches for changes in .go, .templ, .html files and automatically rebuilds.
golangci.toml
Linter configuration with enabled linters:
- Standard Go checks (govet, errcheck, staticcheck)
- Code quality (gocyclo, goconst, revive)
- Style enforcement (goimports, misspell)
- Additional checks (bodyclose, nakedret)
compose.yaml
Docker Compose setup for local development with:
- App container
- MongoDB database
- Prometheus monitoring
- Grafana dashboards
tailwind.config.js
Tailwind CSS configuration for styling.
Entry Point Flow
When the application starts (cmd/web/main.go):
- Load configuration from environment variables
- Initialize structured logger
- Create session store with secure cookies
- Connect to MongoDB
- Initialize repository layer
- Create user service
- Create trivia API client
- Create question service
- Initialize Prometheus registry
- Create web application with all dependencies
- Start HTTP server on configured port
- Listen for shutdown signals (SIGINT, SIGTERM)
Testing Strategy
Test files are co-located with implementation:internal/core/game/game_test.gointernal/web/form/game_test.gointernal/web/form/user_test.gointernal/web/ws/hub_test.gointernal/trivia_api/trivia_api_test.go
testing package.