Sovereign Conquest (Phase 3)
What is included
- Go API server (turn-based command engine)
- Postgres (authoritative game state)
- Nginx static web UI (single-page interface; proxies /api to the Go server)
- Phase 1 loop: register/login, scan, move, trade buy/sell, turn regeneration, port regeneration tick, activity log
- Phase 2 systems: planets + production ticker, corporations + corp bank + corp chat, mines + sweep + mine strikes, seasons + rankings, admin soft-wipe endpoint
- Phase 3 systems: player-only market intel (SCAN snapshots), market analytics + route suggestion, scheduled events (anomalies/invasions/limited-time sectors), mobile-friendly UI upgrades
Quick start
- Unzip the archive.
- From the project root, run: docker compose up --build
- Open: http://localhost:3000
Initial admin account (seeded)
- On startup, the server ensures an initial admin account exists.
- Defaults:
- Username: admin
- Password: ChangeMeNow!
- The seeded admin account requires a password change on first login.
- Configure via environment variables:
- INITIAL_ADMIN_USERNAME
- INITIAL_ADMIN_PASSWORD
- Bootstrap recovery behavior:
- If no admin users exist and the configured initial admin username already exists as a non-admin (for example from an older dev database), the server will promote that user to admin and reset its password to INITIAL_ADMIN_PASSWORD so you can regain access.
- Admin "god mode": admin players have zero turn costs and can MOVE to any existing sector (teleport).
UI note
- The login header shows the build version immediately; once the API is reachable, the UI overwrites it with the live backend version from
/api/version(also exposed by/api/healthz). - The header includes a "Report A Bug" link which opens a separate bug report window. Bug reports (with optional attachments) are delivered to the Admin account via in-game direct messaging.
- The top bar includes a Messages bell which opens the Messages page (inbox/sent, reply, delete). Unread messages are shown as a badge count.
Build note
- This archive includes
server/go.sumand a committedserver/vendor/tree. The default API image build auto-detectsvendor/modules.txtand uses-mod=vendor, so bothdocker compose up --buildand the repository-root image build avoid live access toproxy.golang.orgorsum.golang.orgafter the base images are available locally. - If you intentionally want a networked module restore or need extra build workarounds, set build args via a local
.envfile (or Portainer stack variables):- Important: these values feed compose interpolation (
build.network+build.args). Setting them underservices.api.environmentonly affects the runtime container and will not affect the image build. - If your builder still has broken/restricted DNS during image builds (a common Portainer/remote-builder failure mode), set:
SC_BUILD_NETWORK=hostThis maps to composebuild.network(equivalent todocker build --network=host).- If host networking is unavailable, you can override build-time DNS inside the build container:
SC_BUILD_DNS="1.1.1.1 8.8.8.8"(space-separated) orSC_BUILD_DNS="1.1.1.1,8.8.8.8"(comma-separated)- Note: some builder sandboxes mount
/etc/resolv.confread-only; in that case the build prints a warning and continues without applyingSC_BUILD_DNS. - If
SC_BUILD_DNSis unset and a networked module download/build fails with a DNS-looking error, the build auto-retries once using a public DNS fallback.
GOPROXY=https://proxy.golang.org|direct(recommended default when you are not using vendoring)GOPROXY=direct(common whenproxy.golang.orgis blocked but GitHub is reachable)GOSUMDB=off(common whensum.golang.orgis blocked)SC_USE_VENDOR=1is supported, but vendoring is auto-detected whenvendor/modules.txtis present.- If module downloads fail with TLS/x509 errors (corporate proxy / private module proxy CA), add your CA certificate(s) as
.crtfiles under./server/certs/and rebuild.
- Important: these values feed compose interpolation (
GHCR / single-container image
- The repository root now ships a Dockerfile that builds an all-in-one image for GHCR and generic
docker build .workflows. - That image serves both the Go API and the bundled web UI from the same container on port
8080. - Build locally:
docker build -t sovereign-conquest .
- Run locally against Postgres:
docker run --rm -p 8080:8080 -e DATABASE_URL=postgres://sovereign:sovereign@host.docker.internal:5432/sovereign_conquest?sslmode=disable -e JWT_SECRET=change-me sovereign-conquest
- The GitHub Actions workflow at
.github/workflows/docker-image.ymlpublishesghcr.io/<owner>/sovereign-conquestfrom the repository root. - Local development still supports the split setup with
docker compose up --buildusing./server/Dockerfileand./web/Dockerfile.
Default ports
- Web UI: http://localhost:3000
- API: http://localhost:8080
- Postgres: localhost:5432 (user sovereign, password sovereign, db sovereign_conquest)
Core commands
- SCAN
- MOVE {to}
- TRADE {BUY|SELL} {ORE|ORGANICS|EQUIPMENT} {qty}
Phase 2 commands
- PLANET
- PLANET INFO
- PLANET COLONIZE [name...]
- PLANET LOAD {ORE|ORGANICS|EQUIPMENT} {qty}
- PLANET UNLOAD {ORE|ORGANICS|EQUIPMENT} {qty}
- PLANET UPGRADE CITADEL
- CORP
- CORP INFO
- CORP CREATE {name...}
- CORP JOIN {name...}
- CORP LEAVE
- CORP SAY {message...}
- CORP DEPOSIT {credits}
- CORP WITHDRAW {credits}
- MINE
- MINE DEPLOY {qty} (consumes ship equipment cargo)
- MINE SWEEP (removes hostile mines in the sector)
- SHIPYARD (Protectorate sectors only)
- SHIPYARD
- SHIPYARD BUY {SCOUT|TRADER|FREIGHTER|INTERCEPTOR}
- SHIPYARD SELL
- SHIPYARD UPGRADE {CARGO|TURNS}
- RANKINGS
- SEASON
Phase 3 commands
- MARKET [ORE|ORGANICS|EQUIPMENT]
- Uses only your scanned intel (SCAN) to avoid omniscient pricing.
- ROUTE [ORE|ORGANICS|EQUIPMENT]
- Suggests a trade route using scanned intel only (freshness-weighted).
- EVENTS
- Lists active events in sectors you have discovered.
Admin: soft wipe (new season)
- Set ADMIN_SECRET in docker-compose.yml (or .env) to enable admin endpoints.
- POST /api/admin/soft_wipe with header: X-Admin-Secret: <ADMIN_SECRET>
- Body (optional): {"season_name":"Season X","reset_corps":false}
Resetting the universe (local dev)
- Stop containers, then remove the database volume: docker compose down -v
- Start again: docker compose up --build
Notes
- All state-changing actions go through a single transactional command endpoint.
- Turns regenerate on demand (each command call recalculates turns since last regen).
- Ports and planets regenerate on server ticks to keep the economy and production moving even when nobody is online.
- Events are generated/expired on an event tick (EVENT_TICK_SECONDS). Set EVENT_TICK_SECONDS=0 to disable event generation.
- Protectorate fighter counts fluctuate on a tick (PROTECTORATE_TICK_SECONDS). Set PROTECTORATE_TICK_SECONDS=0 to disable fluctuations.