Two-player 3D naval combat in a 7×7×7 grid. Server-authoritative gameplay, Cognito auth, DynamoDB persistence, BYOK AI via Anthropic API. All game modes are server-managed sessions.
Client (S3/CloudFront) Vite + TS + Three.js + Tone.js
CloudFront Distribution /* → S3 | /api/* + /ws/* → ALB
API Server (Fargate + ALB) Node.js/TS + Express + ws
AWS Managed Services Cognito · DynamoDB · S3 · SES
packages/
shared/ @contact/shared — pure engine + types + observability. No DOM, no SDK deps.
client/ @contact/client — Vite SPA: renderer, audio, ui, net, ai-opponent
server/ @contact/server — Fargate: REST + WebSocket + DynamoDB + SES
infra/ CDK V2 app — all AWS resources
tests/ Mirrors packages/ — 1174 tests, 83 files. NOT co-located with source.
scripts/ CLI: simulate.ts, analyze-log.ts, audio analysis tools
Each directory has its own CLAUDE.md with detailed context.
npm run test:run # vitest run (CI / one-shot)
npm test # vitest watch
npm run typecheck # tsc --noEmit + server typecheck
npm run dev # Vite client dev server (port 5173)
npm run dev:server # tsx watch server (port 3001)
npm run build # typecheck + client production build
npm run cdk:deploy # dev: CDK deploy → post-deploy → client build → S3 sync
npm run cdk:deploy:prod # prod: same pipeline (--require-approval broadening)Game rules are injectable via GameConfig. Server populates from env vars and transmits to client at session join. Engine functions accept config slices; never import constants directly.
Key defaults: 7×7×7 grid, 5 starting credits, 90s turns, 2 consecutive timeouts = forfeit, 90s reconnect window. createGameConfig(overrides?) factory builds a frozen config.
- Online Multiplayer: both players route all actions through the server via WebSocket.
- BYOK AI: human actions through server normally. AI turns: client calls Anthropic API with the player's own key, routes tool-call results through server as standard WebSocket actions. The Anthropic API key never touches CONTACT servers.
| State | Authority | Anti-cheat Note |
|---|---|---|
| Ship placements | Server | Enemy fleet never transmitted to client |
| Fire results | Server | Hit/miss/sunk resolved server-side |
| Credit balances | Server | Tamper-proof economy |
| Perk effects | Server | Effect results only, not raw grid data |
| Turn state machine | Server | Phase, currentPlayer, available slots |
| Anthropic API key | Client ONLY | BYOK: never touches CONTACT servers |
- No
THREE.OrbitControls: custom drag/zoom implementation. NoTHREE.CapsuleGeometry: doesn't exist in r128. - No UI frameworks: vanilla DOM only. No React, Vue, Svelte.
- No
localStorage/sessionStoragefor game state. Exceptions: BYOK API key (opt-in with disclosure),contact_pending_join_codein sessionStorage (invite deep links, survives OAuth redirect). - Observability: if it changes game state, it emits a log event. No exceptions.
- Config flows server → client: client reads game rules from session config, never from imported constants.
- GameController is wrapped by GameSession, not modified directly.
- Decoy: false positive across fire, drone, sonar. Decoy hit counts as hit for credits.
- Silent Running: masks recon (sonar/drone/G-SONAR) but NOT damage (torpedo/depth charge). 2 opponent turns.
- Acoustic Cloak: masks all recon. 2 opponent turns. Consumed on deploy (unlike jammer).
- Radar Jammer: inverts sonar (yes↔no), forces drone all-false. Stays in inventory until triggered.
- Modifier priority: Silent Running > Acoustic Cloak > Radar Jammer.
- Turn slots:
{ pingUsed, attackUsed, defendUsed }. OnlyattackUsedgatesendTurn(). Perk purchases consume no slot. - Coordinates: 0-indexed internally, 1-indexed for display.
grid[col][row][depth]. - Credit awards: hit=+1, consecutive=+3 bonus, sink=+15. Starting credits=5.
- AI safety limits: 8 API calls/turn, 200-turn game cap, 3-turn sliding context window.
Build with CDK V2. See infra/CLAUDE.md for construct details and deploy commands.
| Environment | Account | AWS Profile |
|---|---|---|
| Development | 269559394705 |
development |
| Production | 555768437821 |
production |
| Shared Services | 217139788415 |
shared_services |