AGENTS.md · git:20260918.5adb6d7 · 2026-09-18 · sha256 061997bb00dde9cd
AGENTS.md git:20260918.5adb6d7A
Immutable. This exact content is served forever at /api/v1/blob/061997bb00dde9cd.
# AGENTS.md — agent notes for Infinite Pokémon ## What this repo is A self-hosted, Pokémon-style adventure. Two runtimes share one engine: - **Local game** — Node server (`game/server/`) + SQLite (`node:sqlite`), WebSocket protocol on `/play`, REST under `/api/`, Electron shell in `desktop/` (loads the exported site's `/game/` route inside its iframe). - **Website + browser demo** — Next.js App Router static export (`output: 'export'`, `trailingSlash: true`, webpack build via `next build --webpack` because shared code uses NodeNext `.js` import specifiers; `next.config.mjs` maps them via `resolve.extensionAlias`). The demo runs the engine in a Web Worker (`game/browser/worker.ts`) over an in-memory store snapshotted to IndexedDB. ## Key directories - `app/` — website: `(en)`, `(zh)`, `(game)` route groups each with their own root layout (multiple-root-layout i18n). Copy lives in `app/content.ts` (EN + zh-CN). `public/` is GENERATED: `npm run sync:assets` copies `game/assets/` into it; never edit files in `public/` directly. - `game/engine/` — gameplay rules. Must stay free of Node builtins (no `node:*`, no `node:sqlite`). Persistence goes through the `WorldStore` interface in `game/engine/store.ts`; platform backups via optional `backupDatabase`. Hashing uses `game/shared/sha256.ts` (pure TS, identical in both runtimes). - `game/server/` — Node-only: Store (SQLite), SaveLibrary, Codex harness, preview pack loader, portable-save import (`import.ts`, host-only `/api/host/import`). - `game/browser/` — MemoryStore, IndexedDB storage with cross-tab Web Lock (`infinite-pokemon-demo-save`), portable save builder, the demo worker. The worker entry is guarded against double-evaluation (`__ipDemoWorkerActive`). - `game/client/` — React + Phaser client. `App.tsx` picks transport: WebSocket to the server, or `DemoSocket` (`demo-transport.ts`, WebSocket-compatible wrapper around the worker) when the static export marker meta tag is present and `/api/info` is unreachable. `?demo-debug=1` enables a teleport test hook. ## Commands - `npm run build` — typecheck, sync assets, static-export site to `out/`, build server. - `npm run dev` — dev server with Vite middleware (legacy client dev flow; client entry `game/client/index.html` + `main.tsx` kept for this). - `npm run dev:web` — Next dev server for the site. - `npm test` — node:test unit/integration suite. `npm run test:demo` — Playwright smoke of the browser demo (play → reload/resume → export). Requires `out/`. - `npm run capture:showcase` — replays the demo headlessly and captures the four landing-page screenshots into `game/assets/showcase/`. ## Conventions and invariants - Never move `game/assets/` (referenced by scripts, tests, Electron). Showcase screenshots go in `game/assets/showcase/`. - Website copy is bilingual from `app/content.ts`; game dialogue stays English. - The exported web bundle must never contain Node server code, SQLite, Codex, or private runtime data — verify with a grep over `out/_next` after changing deps. - Demo saves are portable JSON (`format: 'infinite-pokemon-save'`, `formatVersion: 1`); import always creates a NEW isolated preview run and never overwrites local saves. - Do not commit changes to `infinite-pokemon-website/` (abandoned directory).