A full-stack Wordle game with single-player and multi-player modes, featuring real-time gameplay synchronization through pure WebSocket implementation and modern web development practices.
- Dual Game Modes: Classic singleplayer and real-time multiplayer battles
- Advanced State Management: Redux Toolkit with Thunk middleware
- Optimized Routing: TanStack Router with code splitting
- Real-time Communication: WebSocket-based multiplayer synchronization
- Accessible UI: React Aria Components for WCAG compliance
- Type Safety: Zod schema validation + Go validator
- DevOps Ready: Complete Docker ecosystem with compose setup
- Node.js 22.14
- Go 1.24
- Docker
- PostgreSQL 17 (available in server/docker-compose.yaml`)
- Make (available on most Unix-like systems, installable on Windows)
This project uses Make
to simplify Docker Compose commands. The general command structure is:
make [action] [target]
Where:
[action]
can bedev
,prod
,stop
, ordown
.[target]
can beserver
,client
, or omitted to apply to both.
Available Commands:
- Run Development Environment:
- Start backend server (dev mode):
make dev server
- Start frontend client (dev mode with HMR):
make dev client
- Start both backend and frontend (dev mode):
make dev
- Start backend server (dev mode):
- Run Production Environment:
- Build and start backend server (prod mode):
make prod server
- Build and start frontend client (prod mode):
make prod client
- Build and start both backend and frontend (prod mode):
make prod
- Build and start backend server (prod mode):
- Stop Services:
- Stop backend server containers:
make stop server
- Stop frontend client container:
make stop client
- Stop both containers:
make stop
- Stop backend server containers:
- Stop and Remove Services:
- Stop and remove backend containers/network:
make down server
- Stop and remove frontend container/network:
make down client
- Stop and remove all containers, networks, and volumes defined in docker-compose:
make down
- Stop and remove backend containers/network:
Example: To start the entire application in development mode:
make dev
This will build the necessary Docker images (if they don't exist) and start the server, client, and PostgreSQL database containers.
The codebase is organized into client
and server
directories, promoting a clear separation of concerns.
client
: Contains the React frontend application code.server
: Contains the GoFiber backend application code.cmd/main.go
: Entry point for the server application, responsible for setting up dependencies (database, repositories, services) and initializing routes.internal
: Houses the core application logic.api
orhandler
: Contains the Route Handlers (e.g., Fiber handlers). These are responsible for receiving HTTP requests or WebSocket messages, validating input (using Go validator), calling the appropriate service methods, and formatting the response.service
: Contains the Service Layer. This layer encapsulates the core business logic of the application (e.g., validating a guess, starting a new game). Services orchestrate calls to one or more repositories and contain logic that doesn't belong directly in the handlers or data access layer.repository
: Contains the Repository Layer. This layer abstracts the data persistence details. It defines interfaces for data access operations (e.g.,FindGameByID
,SaveGuess
) and provides implementations (e.g., using GORM and PostgreSQL like inserver/internal/infrastructure/gorm/repository/game.go
). This makes it easier to swap out the database technology if needed.
pkg
: Contains shared utilities like custom error handling (errors
).
Dockerfile
: Defines the container image for deployment.docker-compose.yml
: Defines the multi-container setup (client, server, database).Makefile
: Provides convenient commands for managing the Docker environment.
This separation ensures that:
- Route handlers are lean and focus only on request/response handling.
- Business logic is centralized and reusable within the service layer.
- Database interactions are isolated within the repository layer, improving testability (services can be tested with mock repositories) and maintainability.
sequenceDiagram
Client->>Route: HTTP POST /submit
Route->>Service: SubmitGuess(ctx, dto)
Service->>Repository: BeginTransaction()
Repository->>Service: Tx Context
Service->>Repository: QueryGame(tx, id)
Repository->>Database: SELECT ... FROM tbl_game
Service->>Service: Validate business rules
Service->>Repository: SaveGuess(tx, guess)
Service->>Repository: Commit()
Repository->>Database: COMMIT
Service->>Route: Domain Model
Route->>Client: JSON Response
Single Player
Guess the hidden 5-letter word in 6 attempts with color-coded feedback:
- ๐ฉ Correct letter & position
- ๐จ Correct letter, wrong position
- โฌ Letter not in word
Multiplayer Mode
- Create a room and share ID
- Real-time opponent progress tracking to guess the word
- Synchronized game state via WebSocket
- Victory/defeat notifications
graph TD
A[TanStack Router Client] -->|HTTP| B[GoFiber API]
A -->|WebSocket| B
B --> C[(Game State in PostgreSQL)]
Choice: Redux Toolkit with slice-based organization
Rationale:
- Predictable state container for complex game logic
- Thunk middleware for async game initialization
- Memoized selectors for performant board rendering
- Serializable actions for potential game replay system
Choice: Native WebSocket over Socket.IO
Rationale:
- No protocol overhead for faster message delivery
- Direct control over connection lifecycle
- Go's concurrency model (goroutines) for efficient message broadcasting
Implementation: Zod โ Go structs with GORM โ Database constraints
Benefits:
- Frontend validation with Zod schemas
- GORM model โ database schema alignment
- End-to-end type safety from UI to DB
Solution: TanStack Router + React Aria
Advantages:
- Type-safe route parameters
- Automatic code splitting
- Built-in focus management
- Screen reader support
- Keyboard navigation
Approach: Docker Compose with multi-stage builds and Make
to simplify Docker Compose commands
Optimizations:
- Separate build/runtime containers
- Alpine-based final images
- Shared network for service discovery
- Centralized logging