Weiqi.com is an online platform for playing the ancient board game Go (also known as Weiqi or Baduk). This project aims to provide a seamless and engaging experience for players of all skill levels, from beginners to advanced players. The platform includes features like real-time multiplayer, AI integration, game analysis, and more.
- Real-Time Multiplayer: Play Go against other players in real-time.
- Dynamic Rating System: Track player skill levels using a dynamic rating system (e.g., Elo or Glicko).
- Match History: View detailed records of past games, including moves and outcomes.
- Game Timer: Supports various timing systems (e.g., byo-yomi, Fischer) for competitive play.
- AI Opponent: Practice against an AI with adjustable difficulty levels.
- Spectator Mode: Watch ongoing games in real-time.
- Custom Game Settings: Adjust board size, komi, and handicaps.
- Resign Button: Allow players to resign gracefully.
- Draw Offers: Enable players to offer or accept draws.
- Game Analysis: Analyze games with AI-powered tools and heatmaps.
- Player Profiles: Display statistics, ratings, and achievements.
- Leaderboard: Compete for the top spot on the global or regional leaderboard.
- Friend System: Add friends and challenge them directly.
- Chat System: Communicate with opponents and spectators during games.
- JWT Authentication: Secure user authentication and WebSocket communication.
- Reconnection Handling: Gracefully handle player disconnections and reconnections.
- Scalable Backend: Built to handle a large number of concurrent games and users.
- Cross-Platform Support: Responsive design for web and mobile devices.
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ │ │ │ │ │
│ Next.js │◄────► Spring Boot │◄────► PostgreSQL │
│ Frontend │ API │ Backend │ │ Database │
│ │ │ │ │ │
└────────────────┘ └───────┬────────┘ └────────────────┘
│
┌───────▼────────┐
│ │
│ Redis │
│ (Caching) │
│ │
└────────────────┘
- TypeScript-based React application
- Responsive UI with Tailwind CSS
- Go board rendering with custom components
- Real-time game updates via WebSockets
- Redux for state management
- Java-based RESTful API
- WebSocket support for real-time gameplay
- JWT authentication and authorization
- Game logic implementation
- Matchmaking system
- PostgreSQL for user data, game records, and settings
- Redis for caching, sessions, and real-time game state
- REST API for standard requests
- WebSocket for real-time game events
- JWT for secure authentication
This application uses Docker for easy setup and development. Follow these steps to get started.
- Docker and Docker Compose
- Git
git clone https://github.com/yourusername/weiqi.com.git
cd weiqi.comThis project uses Mozilla SOPS for encrypting sensitive environment variables:
-
Install SOPS following the official documentation
-
Set up GPG for encryption:
# Install GPG if not already installed # macOS: brew install gnupg # Ubuntu/Debian: sudo apt-get install gnupg # Windows: Download from https://www.gnupg.org/download/ # Generate a new GPG key gpg --full-generate-key # Select RSA and RSA, 4096 bits, and follow the prompts # List your keys to get the fingerprint gpg --list-secret-keys --keyid-format=long # Export your public key to share with team members gpg --armor --export your.email@example.com > your-name-pubkey.asc
-
The new team member generates their GPG key and exports their public key as shown above
-
Add the public key to the project's
keys/directory:# From the project root cp your-name-pubkey.asc keys/ # Create a branch for your changes git checkout -b add-gpg-key/your-name # Add and commit your public key git add keys/your-name-pubkey.asc git commit -m "Add [Your Name]'s GPG public key" # Push the branch and create a pull request git push -u origin add-gpg-key/your-name # Then create a PR from your branch to main via GitHub interface
-
When your PR is opened, the GitHub Actions workflow (
sops-onboard.yml) will automatically:- Import all public keys from the
keys/directory - Update the
.sops.yamlconfiguration with all fingerprints - Re-encrypt all
.env.encfiles to include the new key - Commit these changes directly to your PR branch
- Import all public keys from the
-
After your PR is reviewed and merged:
# Switch back to main and pull the latest changes git checkout main git pull # Decrypt the environment files ./scripts/decrypt.sh
# Decrypt an encrypted .env file to .env.dec
./scripts/decrypt.sh
# Or decrypt manually
sops --decrypt --input-type dotenv --output-type dotenv .env.enc > .env.dec
# Edit an encrypted file directly (opens in your default editor)
sops .env.enc
# Re-encrypt after making changes
./scripts/encrypt.shThis project uses GitHub Actions to automate the SOPS key management process:
-
When a PR with changes to
keys/*.ascis opened or updated, thesops-onboard.ymlworkflow runs -
The workflow automatically:
- Imports all public keys from the
keys/directory - Updates the
.sops.yamlconfiguration with all fingerprints - Re-encrypts all
.env.encfiles to include the new keys - Commits and pushes these changes directly to the PR branch
- Imports all public keys from the
-
After the PR is reviewed and merged, all team members can access the encrypted files with their keys.
To rotate your GPG key (recommended annually):
-
Generate a new GPG key as shown in the initial setup
-
Export your new public key and replace your old one:
# Export your new public key gpg --armor --export your.new.email@example.com > your-name-new-pubkey.asc # Create a branch for your changes git checkout -b rotate-gpg-key/your-name # Replace your old key with the new one mv your-name-new-pubkey.asc keys/your-name-pubkey.asc # Commit and create a PR git add keys/your-name-pubkey.asc git commit -m "Rotate [Your Name]'s GPG key" git push -u origin rotate-gpg-key/your-name # Then create a PR from your branch to main via GitHub interface
-
After your PR is reviewed and merged, the GitHub workflow will automatically update all encrypted files via a second PR.
To remove a team member:
-
Remove their public key from the
keys/directory:# Create a branch for the change git checkout -b remove-team-member/former-teammate # Remove their key git rm keys/former-teammate-pubkey.asc git commit -m "Remove [Former Teammate]'s GPG key" git push -u origin remove-team-member/former-teammate # Then create a PR from your branch to main via GitHub interface
-
After this PR is merged, the GitHub workflow will automatically re-encrypt all files without their key via a second PR.
Problem: "Failed to get the data key required to decrypt the SOPS file" or "Screen or window too small"
This is a common issue in WSL (Windows Subsystem for Linux) environments where GPG can't properly prompt for passphrases.
Solution:
-
Configure GPG for WSL compatibility by adding these lines to
~/.gnupg/gpg.conf:echo "use-agent" >> ~/.gnupg/gpg.conf echo "pinentry-mode loopback" >> ~/.gnupg/gpg.conf
-
Reload the GPG agent:
gpg-connect-agent reloadagent /bye
-
Set the GPG TTY environment variable:
export GPG_TTY=$(tty)
-
Try decryption again:
./scripts/decrypt.sh
What this fixes:
use-agent: Ensures GPG uses the GPG agent for handling keyspinentry-mode loopback: Allows GPG to prompt for passphrases directly in the terminal instead of using a separate dialog (which fails in WSL)
- Never commit unencrypted
.envfiles to the repository - Keep your GPG private key secure and never share it
- Use a strong passphrase for your GPG key
- Rotate your keys periodically (annually recommended)
- Always pull the latest
.env.encbefore making changes - If you're using WSL, apply the GPG configuration fix above to avoid decryption issues
The .gitignore file is configured to allow .env.enc files while ignoring unencrypted .env files.
Locally, we use docker containers for easy spin up, have two different environment setup. Locally we use the weiqi-dev supabase for auth, and in prod we use weiqi-prod.
Start all services using Docker Compose:
docker-compose upFor detached mode:
docker-compose up -d- Frontend: http://localhost:3000
- Backend API: http://localhost:8081
- Database UI: http://localhost:8082
- Email:
admin@admin.com - Password:
admin
- Email:
To connect to the PostgreSQL database from tools like DBeaver, TablePlus, etc:
- Host:
localhost - Port:
5432 - Database:
compose-postgres - Username:
compose-postgres - Password:
compose-postgres
The frontend code is located in the goweb directory. Changes will automatically be reflected due to the volume mapping.
The backend code is in the goweb-spring directory. Spring Boot dev tools will automatically reload changes.
docker-compose downTo remove volumes as well:
docker-compose down -v- Port conflicts: If you have services running on ports 3000, 5432, 6379, or 8081, stop them or modify the port mappings in
docker-compose.yml - Database connection issues: Ensure PostgreSQL container is running with
docker ps - Frontend not connecting to backend: Check network settings and CORS configuration