| 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. 3 type errors are known and older than recent work |
| 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.
- 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.
-`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.
- Board components size themselves from the `--board-unit` CSS variable; `BoardView` takes an optional `width`.
- 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.