An API-first, headless strategy game inspired by Travian. Build villages, train armies, research technologies, forge alliances, and conquer the map — all through a REST API with a React frontend.
┌──────────────────────────────────────────────────────────┐
│ Frontend │
│ React + TypeScript + Vite │
│ (SPA served by Nginx) │
└─────────────────────┬────────────────────────────────────┘
│ HTTP / REST
┌─────────────────────▼────────────────────────────────────┐
│ API Server │
│ Go (Echo) — cmd/api │
│ • Authentication (GitHub/Discord OAuth) │
│ • REST endpoints for all game actions │
│ • OpenAPI spec + Swagger UI at /docs │
│ • Reads state directly from DB (CRUD) │
└──────┬──────────────────────────────────────┬────────────┘
│ │
│ pgx Redis (Asynq)
│ │
┌──────▼──────────────────────────────────────▼────────────┐
│ Game Server │
│ Go — cmd/server │
│ • Background tick loop (resource production) │
│ • Task queue worker (building, training, combat) │
│ • Map generation & seeding │
│ • Deterministic game simulation │
└──────┬──────────────────────────────────────┬────────────┘
│ │
┌──────▼──────────┐ ┌──────────▼───────────┐
│ PostgreSQL 15 │ │ Redis 7 │
│ Source of truth │ │ Task queue (Asynq) │
│ All game state │ │ Rate limiting │
└─────────────────┘ └──────────────────────┘
The game uses a hybrid active-ticking architecture:
- The API Server handles HTTP requests and acts as a stateless CRUD gateway.
- The Game Server runs a background loop that ticks every second, processing resource production, task completions, troop movements, and combat.
- PostgreSQL is the single source of truth. All state mutations go through database transactions with
SELECT ... FOR UPDATEto prevent race conditions. - Redis powers the async task queue (via Asynq) and rate limiting.
| Layer | Technology |
|---|---|
| Backend | Go 1.24, Echo web framework |
| Database | PostgreSQL 15 (via pgx/v5 + sqlc) |
| Task Queue | Redis 7 + Asynq |
| Frontend | React 18, TypeScript, Vite, TailwindCSS |
| Auth | GitHub + Discord OAuth (Goth) |
| API Spec | OpenAPI 3.0 + oapi-codegen |
| Observability | OpenTelemetry → Jaeger + Prometheus |
| Deployment | Docker Compose, Nginx reverse proxy |
The fastest way to run Katanian locally — one command, everything in Docker:
# Clone the repo
git clone https://github.com/tim1234ltp/Katanian.git
cd Katanian
# Start everything (PostgreSQL, Redis, API, Game Server, Jaeger, Prometheus)
docker compose -f docker-compose.localdev.yml up --buildThe game will be available at:
- API: http://localhost:8080/v1
- Swagger Docs: http://localhost:8080/docs
- Jaeger UI: http://localhost:16686
- Prometheus: http://localhost:9090
Note: Auth is disabled by default in local dev (
AUTH_DISABLED=true). You'll be logged in as the first user automatically.
To run the frontend with hot-reload:
cd web
npm install
npm run devThe Vite dev server runs on http://localhost:5173 and proxies API calls to the backend.
- Go 1.24+
- Node.js 20+ and npm
- Docker and Docker Compose
- sqlc (
go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest)
If you prefer running services natively:
- Start PostgreSQL and Redis locally
- Initialize the database:
psql -U postgres -d katanian -f sql/schema.sql # Optional: load demo data psql -U postgres -d katanian -f sql/demo.sql - Copy and configure environment:
cp .env.example .env
- Run the servers:
# Terminal 1: API Server make run-api # Terminal 2: Game Server make run-server
| Command | Description |
|---|---|
make build |
Build API and Game Server binaries |
make unittest |
Run unit tests (excludes integration) |
make integration |
Run integration tests (requires PostgreSQL) |
make sqlc |
Regenerate Go code from SQL queries |
make oapi |
Regenerate Go code from OpenAPI spec |
make local-up |
Start local dev environment via Docker Compose |
make local-down |
Stop local dev environment |
make uat-up |
Start UAT environment (with AI bots) |
make fmt |
Format all Go code |
├── api/
│ └── openapi.yaml # OpenAPI 3.0 specification
├── cmd/
│ ├── api/ # API Server entrypoint
│ ├── server/ # Game Server entrypoint
│ ├── bot/ # AI bot player (for testing)
│ └── tools/ # CLI utilities
├── config/
│ ├── config.go # Application config (env vars)
│ ├── jaeger/ # Jaeger tracing config
│ ├── prometheus/ # Prometheus metrics config
│ └── redis/ # Redis config
├── docker/
│ ├── Dockerfile.* # Multi-stage Dockerfiles
│ ├── gateway/ # Nginx gateway config
│ └── docker-compose.gateway.yml
├── integration/ # Integration tests
├── internal/
│ ├── api/ # Generated OpenAPI handlers
│ ├── auth/ # OAuth (GitHub, Discord)
│ ├── db/ # sqlc-generated DB layer
│ ├── game/ # Core game engine
│ │ ├── engine.go # Resource production, building, training
│ │ ├── combat.go # Combat simulation
│ │ ├── missions.go # Troop movement & mission logic
│ │ └── settlement.go # Village settling
│ ├── gamedata/ # Static game data (YAML-driven)
│ │ └── data/ # buildings.yaml, units, etc.
│ ├── middleware/ # Auth guard, rate limiting, telemetry
│ ├── payment/ # Stripe integration (optional)
│ ├── queue/ # Task queue (Outbox → Asynq)
│ ├── server/ # HTTP handlers + game server loop
│ ├── telemetry/ # OpenTelemetry setup
│ └── worker/ # Asynq worker handlers
├── sql/
│ ├── schema.sql # Database schema (PostgreSQL DDL)
│ ├── queries/ # SQL queries (used by sqlc)
│ ├── demo.sql # Demo data for local dev
│ └── prod.sql # Production seed data
├── web/ # React frontend (Vite + TypeScript)
├── docker-compose.localdev.yml # Local development
├── docker-compose.uat.yml # UAT with AI bots
├── docker-compose.prod.yml # Production deployment
├── docker-compose.beta.yml # Beta deployment
├── Makefile
├── sqlc.yaml
└── .env.example
All configuration is done through environment variables. See .env.example for the full list.
Key variables:
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
postgres://postgres:password@localhost:5432/katanian?sslmode=disable |
PostgreSQL connection string |
REDIS_ADDR |
localhost:6379 |
Redis address |
PORT |
8080 |
API server port |
AUTH_DISABLED |
false |
Skip authentication (dev only) |
TIME_MULTIPLIER |
1.0 |
Game speed multiplier (e.g., 5.0 = 5x speed) |
ALLOWED_ORIGINS |
http://localhost:5173,http://localhost:8080 |
CORS allowed origins (comma-separated) |
BASE_URL |
http://localhost:8080 |
Public URL for OAuth callbacks |
The full API is documented via OpenAPI 3.0. When the server is running:
- Swagger UI: http://localhost:8080/docs
- Raw spec: http://localhost:8080/swagger.yaml
- Spec file:
api/openapi.yaml
For local development with AUTH_DISABLED=true, pass any UUID as the session_token cookie or X-API-Key header.
For production, Katanian supports:
- GitHub OAuth — set
GH_OAUTH_KEYandGH_OAUTH_SECRET - Discord OAuth — set
DISCORD_OAUTH_KEYandDISCORD_OAUTH_SECRET - API Keys — generated per-user via
/v1/account/keys
curl -X POST http://localhost:8080/v1/village/{village_id}/construct \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{"building_type": "barracks", "slot_id": 22}'- 🏘️ Village Building — 20+ building types with upgrade trees and resource costs
- ⚔️ Combat — Attack, raid, reinforce, and scout with detailed battle reports
- 🔬 Research — Academy tech tree to unlock advanced units
- 🗺️ World Map — Procedurally generated hex map with oases and wilderness
- 🤝 Alliances — Create and manage player alliances
- 🦸 Heroes — Hero system with adventures, items, and equipment
- 🏛️ Celebrations — Small and large celebrations for culture points
- 🏪 Marketplace — Trade resources between villages
- 🤖 AI Bots — Built-in bot players for testing (Romans, Gauls, Teutons)
- 📊 Observability — Full distributed tracing (Jaeger) and metrics (Prometheus)
# Unit tests only
make unittest
# Integration tests (requires PostgreSQL running)
make integration
# Full QA suite (spins up everything + runs integration tests)
make qa-up-
Copy and configure your environment:
cp .env.example .env # Edit .env with your production values: # POSTGRES_PASSWORD, BASE_URL, OAuth keys, etc.
-
Bootstrap a VM (Ubuntu/Debian):
chmod +x scripts/bootstrap-vm.sh ./scripts/bootstrap-vm.sh
-
Start production services:
make prod-up
For HTTPS without port forwarding, set the TUNNEL_TOKEN env var. The production Docker Compose includes a Cloudflare Tunnel sidecar.
The repo includes GitHub Actions workflows:
go.yml— Builds, lints, and tests Go code on every pushweb.yml— Lints and builds the frontend on every pushdeploy.yml— Manual deployment to a VM viaworkflow_dispatch
Contributions are welcome! Here's how to get started:
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-change) - Run tests (
make unittest) - Commit your changes
- Open a Pull Request
Please ensure:
- Go code is formatted (
go fmt ./...) - New game logic has unit tests
- SQL changes include both schema updates and sqlc queries
This project is licensed under the MIT License — see the LICENSE file for details.