AGENTS.md notes on the themes, plain CSS for container queries and driving the app in Chrome; TODO.md gets the mobile app and rematch as open work; the spec is marked implemented.
114 lines
7.5 KiB
Markdown
114 lines
7.5 KiB
Markdown
# AGENTS.md
|
|
|
|
Guidance for coding agents working in this repository. Keep it current: when you learn something that would have
|
|
saved time, add it here.
|
|
|
|
## Project
|
|
|
|
Online Mancala (the Turkish *Mangala* rules) with a web app, an Android/iOS app and a Node backend.
|
|
|
|
| Path | What |
|
|
|---|---|
|
|
| `packages/mancala.js` | Game engine; rules are plug-ins in `src/common/game_rules` |
|
|
| `packages/core` | Code shared by the apps: models, WebSocket client (`RTMTWS`), channel names, history helpers, themes, `PitAnimator`, translations (en, tr) |
|
|
| `apps/backend` | Express + `ws`: matchmaking, games, auth, saved games, HTTP API |
|
|
| `apps/frontend` | React web app, built with Parcel |
|
|
| `apps/mobile` | React Native app |
|
|
| `apps/keycloak` | Keycloak image with the realm and a Java extension for guest login |
|
|
| `apps/postgres` | Init script creating the `keycloak` and `mancala` databases |
|
|
| `apps/compose.yaml` | Postgres, Valkey, Keycloak, backend, frontend |
|
|
| `config/nginx.conf` | The production server's nginx config (Certbot managed) |
|
|
| `docs/specs/<feature>` | Specs: `requirements.md`, `design.md`, `tasks.md` |
|
|
| `TODO.md` | Open work, known bugs and deployment steps; read it before starting |
|
|
|
|
Specs that exist: `keycloak-auth` (login, guests, tokens), `game-history` (saved games, live games, replay),
|
|
`game-clock` (5 minutes per player, ending games on time) and `web-redesign` (the web app's look: themes, board,
|
|
pages).
|
|
|
|
## Running locally
|
|
|
|
```sh
|
|
yarn build:packages # repo root; builds mancala.js and core
|
|
cd apps && docker compose up -d --build postgres valkey keycloak # needs apps/.env, see README.md
|
|
cd apps/backend && yarn dev # http://localhost:5005
|
|
cd apps/frontend && yarn dev # http://localhost:1234 (must be 1234, Keycloak only allows that)
|
|
```
|
|
|
|
Postgres is on `localhost:5433` (5432 is often taken), Valkey on `6379`, Keycloak on `8080`
|
|
(admin console `/admin`). The backend's and frontend's defaults point at these. The mobile app points at production
|
|
unless `useLocalServer` is set in `apps/mobile/src/const/config.ts`.
|
|
|
|
## Checks
|
|
|
|
| What | Command | Notes |
|
|
|---|---|---|
|
|
| Engine | `cd packages/mancala.js && npx jest` | |
|
|
| Core | `cd packages/core && npx jest` | |
|
|
| Backend | `cd apps/backend && npx tsc --noEmit -p . && npx jest` | Needs Docker: Postgres and Valkey run in testcontainers |
|
|
| Keycloak extension | `cd apps/keycloak/extension && mvn test` | Needs Docker; starts Keycloak with the real realm file |
|
|
| Web app | `cd apps/frontend && yarn build` | There is no `tsconfig.json`, so nothing type-checks it; use a temporary one when needed (with `"types": ["styled-jsx", "react", "react-dom"]`). 1 type error (`react-dom/client`) is known |
|
|
| Mobile | `cd apps/mobile && npx tsc --noEmit -p .` and `npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output /tmp/x.bundle` | 11 type errors are known and older than recent work |
|
|
|
|
There is no automated end-to-end suite. Changes to the game flow were checked by driving Chrome with
|
|
`playwright-core` (installed outside the repo, `executablePath: /usr/bin/google-chrome`) against the local stack.
|
|
|
|
## How we work
|
|
|
|
- The user writes in Turkish; code, comments, commit messages and specs are in English.
|
|
- Larger features start with a spec in `docs/specs/<feature>/` (requirements with acceptance criteria, design with
|
|
decisions and reasons, tasks as a checklist). Implement the tasks in order, one commit each, and tick them. Small
|
|
fixes need no spec. When resuming a feature, read its spec and `tasks.md` first.
|
|
- Work on feature branches; commit messages follow `type(scope): summary` with a short body.
|
|
- Never add AI attribution (Co-Authored-By lines, "Generated with …") to commits or PRs.
|
|
- Do not commit files the user changed but did not ask to commit; stage only your own changes (hunks if needed).
|
|
- New dependencies get exact versions.
|
|
|
|
## Things that are easy to get wrong
|
|
|
|
**Packages and builds**
|
|
- The apps use `packages/core` and `packages/mancala.js` through `link:` dependencies, i.e. their built `dist`.
|
|
After changing a package, run `yarn build` in it (or `yarn dev` to rebuild on change), or the apps use stale code.
|
|
Running dev servers do not notice a rebuilt package: restart the backend, and restart Parcel after deleting
|
|
`apps/frontend/.parcel-cache`.
|
|
- Backend and frontend Docker images are built from the repo root: `docker build -f apps/backend/Dockerfile .`.
|
|
- The mobile app uses `RTMTWS` from core (its own `src/rtmt` copy is unused), so changing the core WebSocket client
|
|
changes mobile too. Metro needs `watchFolders` and `nodeModulesPaths` (already in `metro.config.js`).
|
|
|
|
**Backend**
|
|
- User ids: Keycloak users are `kc:<sub>`; legacy mobile users are their `userKey`, which is a secret. Anything
|
|
saved or listed publicly goes through `publicUserId()`; clients get `toClientGame()`, never spectator ids.
|
|
- Live games: memory is the source of truth, Valkey is a write-through copy restored on startup; the backend
|
|
assumes a single instance. Finished games are written to Postgres once, with retry when it is down.
|
|
- Postgres or Valkey being down must not stop games; reads fall back, writes are retried.
|
|
- The game clock is stored as each player's time at the start of the turn plus `turnStartedAt`; compute the time
|
|
left with `getClockTimes`, never store a ticking value. `GAME_CLOCK_MS=40000` makes games short for manual tests.
|
|
- `RTMT.listenOnClientConnectionChange` adds a listener (several are allowed).
|
|
- Jest 27 lacks Node's web globals that testcontainers needs; `tests/support/NodeEnvironment.js` copies them in.
|
|
- A Valkey client pointed at a dead port keeps Jest alive for `disconnectTimeout`; tests pass a short one.
|
|
|
|
**Web app**
|
|
- styled-jsx only scopes JSX written directly in a component's render; elements built in helper functions or
|
|
`map` callbacks need `.parent :global(.child)` rules.
|
|
- Pages are full-height flex columns: a block with `overflow: hidden` needs `flex-shrink: 0` or it gets squeezed.
|
|
- Colours come from CSS variables of the theme class on `<html>` (`styles/app.css`); the web app's themes
|
|
(`theme/themes.ts`) are passed to core's `ThemeManager`, which the mobile app uses with its own default themes.
|
|
- Styles that need container queries (`@container`, `cqw`), such as the board's, are plain `.css` files imported by the
|
|
component; styled-jsx 5.0 does not handle them. `BoardView` fills its container and stands upright below 600 px.
|
|
- When a script drives the app in Chrome, wait for the header (`.hdr`) and a few seconds after the first load before
|
|
navigating; navigating during the guest login leaves an invalid token. Open the lobby with the "New Game" button,
|
|
not by URL, or the matchmaking message goes out before the WebSocket is open.
|
|
- The WebSocket client emits `open` after authentication; anything the server must know about a connection
|
|
(spectating a game, live game previews) is sent on `open`, because the server forgets it when a user goes offline.
|
|
|
|
**Keycloak**
|
|
- The realm file is imported only when the realm does not exist; changes to it must also be made in a running
|
|
Keycloak (or recreate the database).
|
|
- Listing some `requiredActions` in the realm file replaces Keycloak's whole default list, so the file contains all
|
|
of them.
|
|
- The guest authenticator uses an internal Keycloak SPI: keep the version in `extension/pom.xml` and `Dockerfile` in
|
|
sync and run `mvn test` when upgrading.
|
|
- Keycloak sets `Secure` cookies; browsers send them to `http://localhost`, simple HTTP clients do not.
|
|
|
|
**Mobile**
|
|
- `apps/mobile/release_android.sh` contains signing passwords (see `TODO.md`); do not copy them anywhere.
|