Imported from KovalDenys1/Boardly (
AGENTS.md). Install upstream withnpx skills add KovalDenys1/Boardly. Copyright stays with the author.
Boardly Agent Guide (Codex)
Use this file to work effectively in this repository with minimal regressions.
Mission
Improve Boardly as a reliable real-time multiplayer platform with strong game integrity, sync correctness, and operational safety.
Read First (for non-trivial tasks)
README.md.github/copilot-instructions.mddocs/ARCHITECTURE.mddocs/OPERATIONS.mddocs/SECURITY_MODEL.md
Architecture Snapshot
- Next.js app server (HTTP API/auth/pages):
:3000 - Supabase Realtime: Broadcast (lobby events) + Postgres Changes (lobby/player table sync)
- PostgreSQL + Prisma (hosted on Supabase)
Core flow:
Client action → API route → DB update → Supabase Realtime Broadcast → client reconcile
High-Risk Areas (read before editing)
lib/supabase-server.ts(broadcastToLobby— must always beawaited beforereturn NextResponse.json())hooks/useRealtimeConnection.ts(client Broadcast + Postgres Changes subscriber)app/api/game/[gameId]/state/route.tslib/game-engine.tslib/games/*lib/guest-auth.ts- auth routes under
app/api/auth/*
Non-Negotiables
- Server-authoritative gameplay: client may be optimistic, server snapshots win.
- Use
NEXTAUTH_SECRETas the primary signing secret; do not introduce newJWT_SECRET-based logic. - Guest identity must use signed tokens (
X-Guest-Token), not raw client IDs. - Be defensive around reconnects, duplicate events, and timer/auto-action paths.
- Keep changes minimal and readable; avoid broad refactors unless requested.
Branch and PR Policy
- For each ticket/feature/fix, create a dedicated branch from
develop(for examplefeature/<ticket>-<short-name>,fix/<ticket>-<short-name>,chore/<short-name>). - Every task commit must reference its ticket or issue number in the commit message so the ticket timeline can be traced back to the implementation commit later (for example
fix(#229): reassign lobby host on creator leaveorchore(#226): tighten mobile header layout). - Pull requests merged into
developshould includeCloses #...,Fixes #..., orResolves #...in the PR body so the linked issue can be auto-closed by automation when the PR is merged. - Open PRs from task branches into
develop. Do not push task commits directly todevelop. - Promote to production only through PRs from
developintomain. - Treat direct pushes to
mainanddevelopas emergency-only exceptions. - After PR merge, delete the local task branch (
git branch -d <branch>) in the same work session. The remote branch is auto-deleted by repository settings. - After each merge wave, run local branch cleanup and keep only long-lived branches (
main,develop) plus the currently active task branch. - Prefer fewer, larger-coherent PRs over many tiny PRs: if fixes are tightly related and touch the same subsystem, batch them into one task branch/PR.
- Before opening a new PR, check open PR count; if there are already 3+ open fix PRs to
develop, prioritize merging existing PRs first unless it's a production blocker.
Fast Command Cookbook
Setup:
npm installnpm run db:generatenpm run db:push
Run locally:
npm run dev
Quality checks:
npm run ci:quick(lint + typecheck)npm testnpm run ready:build-test(full local gate)
Operational checks:
npm run check:envnpm run check:dbnpm run ops:alerts:check
Verification Matrix (run what matches your change)
UI-only:
npm run lint- relevant Jest tests if components/hooks changed
API / auth / guest flow:
npm run ci:quicknpm test- manual guest join/play smoke test if behavior changed
Realtime / game engine:
npm run ci:quicknpm test- manual flow: create/join/start/play/reconnect/finish
DB / Prisma / RLS:
npm run db:validatenpm run db:generatenpm run db:rls:smoke(when relevant)npm run check:db(safe-by-default diagnostics; usenpm run check:db:verbosefor local debugging details)
Codex Automation (MCP)
This repo includes cross-platform MCP wrappers and Codex helpers (PowerShell + Bash):
scripts/mcp-github.ps1scripts/mcp-github.shscripts/mcp-postgres.ps1scripts/mcp-postgres.shscripts/mcp-filesystem.ps1scripts/mcp-filesystem.shscripts/mcp-memory.ps1scripts/mcp-memory.shscripts/codex-mcp-setup.ps1scripts/codex-mcp-setup.shscripts/codex-mcp-health-check.ps1scripts/codex-mcp-health-check.shscripts/codex-quick-check.ps1scripts/codex-quick-check.sh
Note: codex-mcp-setup and codex-mcp-health-check now use shared tsx orchestration (scripts/codex-mcp-setup.ts, scripts/codex-mcp-health-check.ts) with thin .ps1/.sh wrappers.
First-time setup (registers MCP servers in ~/.codex/config.toml):
- Windows:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/codex-mcp-setup.ps1 - macOS/Linux:
bash scripts/codex-mcp-setup.sh
Expected MCP server names:
boardly-githubboardly-postgresboardly-filesystemboardly-memory
Requirements:
GITHUB_TOKEN(orGITHUB_PERSONAL_ACCESS_TOKEN) in.env/.env.localDATABASE_URLin.env/.env.localMCP_POSTGRES_CA_CERT_PATHin.env/.env.localfor strict TLS trust (path to CA PEM/CRT file)
External MCP scaffold template (not auto-registered):
docs/codex-mcp.external-template.toml
Next.js MCP
- The repo now includes root
.mcp.jsonfornext-devtools-mcp. - For Next.js runtime MCP, start the app with
npm run dev. Next.js 16 exposes the MCP endpoint automatically during dev. - Use
nextjs_indexfirst to discover the running server, thennextjs_callfor tools likeget_project_metadata,get_routes, andget_errors. get_errorsandget_page_metadataare only useful after opening the app in a real browser session.next devmay rewritetsconfig.jsonandnext-env.d.tsfor local type integration. Do not commit those changes unless they are intentional and reviewed.
Owner Preferences (Codex Collaboration Defaults)
Use these defaults unless the user overrides them in the current chat.
- Autonomy: balanced (ask before important behavior/config changes; proceed on small safe edits).
- Questions: ask in batches with options when configuring tools/files.
- Auto-approve profile: medium (read-only + common quality commands).
- Quick-check default: working (
env + db + ci:quick + smoke tests). - Env output preference: quiet (do not print env values/prefixes during checks).
- VS Code tasks: keep basic one-click tasks available.
- When tradeoffs exist: propose 2-3 variants before editing.
Codex IDE Workflows
Use these as default automation routines when the task does not require something custom.
Quick local confidence pass (recommended before/after non-trivial edits):
- Windows:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/codex-quick-check.ps1 - macOS/Linux:
bash scripts/codex-quick-check.sh
Skip DB when working offline / DB is unavailable:
- Windows:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/codex-quick-check.ps1 -SkipDb - macOS/Linux:
bash scripts/codex-quick-check.sh --skip-db
Notes:
codex-quick-checkuses quiet env checking by default (npm run check:env:quiet).
Full pre-PR local gate:
npm run ready:build-test
Git hooks (Lefthook, auto-installed via npm install/npm ci through prepare):
- Install manually (if needed):
npm run hooks:install - Run pre-commit hook manually:
npm run hooks:pre-commit - Run pre-push hook manually:
npm run hooks:pre-push - Emergency bypass (one-off):
git commit --no-verify/git push --no-verify
Refresh Codex MCP registration (after script/path changes):
- Windows:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/codex-mcp-setup.ps1 -Force - macOS/Linux:
bash scripts/codex-mcp-setup.sh --force
MCP health check (detailed local sanity):
- Windows:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/codex-mcp-health-check.ps1 - macOS/Linux:
bash scripts/codex-mcp-health-check.sh
Suggested Codex task prompts (examples):
- "Investigate this realtime bug with minimal diff, run
npm run ci:quickand only relevant tests." - "Implement feature X and update tests for changed behavior; avoid broad refactors."
- "Trace guest auth flow end-to-end and verify
NEXTAUTH_SECRET-based token logic only."
Working Style for Agents
- Prefer targeted reads (
rg, specific files) before editing. - Preserve existing patterns (Next.js app router, Prisma, Supabase Realtime handler structure).
- Do not create one-off docs unless requested; update canonical docs when behavior changes.
- For bug fixes, add/adjust tests near the changed behavior when practical.
- Never expose secrets from
.envin outputs or commits.
Good Entry Points by Task Type
New API behavior:
app/api/**/route.tslib/*service/helper used by route__tests__/api/*
Realtime bug:
lib/supabase-server.ts(server-side broadcast)hooks/useRealtimeConnection.ts(client-side subscription)hooks/use-lobby-list.ts(lobby list Postgres Changes)__tests__/app/*
Game logic:
lib/games/*lib/game-engine.ts__tests__/lib/games/*
Lobby UX/state sync:
app/lobby/[code]/hooks/*app/lobby/[code]/components/*__tests__/app/*
Realtime Gotchas
Critical non-obvious invariants — read before touching any API route or realtime code:
- Always
await broadcastToLobby()beforereturn NextResponse.json(). Vercel terminates the serverless function as soon as the response is sent; any unresolvedvoidpromise is killed and the broadcast never reaches clients (this was bug #509). - Never use
notifySocket— that function and all oflib/socket/were deleted in the Supabase Realtime migration. UsebroadcastToLobbyfromlib/supabase-server.ts. - Topic format is
lobby:{code}(norealtime:prefix) — the Supabase REST broadcast API strips the prefix internally. guess_the_spystate must be sanitized viasanitizeSpyStateForBroadcast()before sending — raw Postgres Changes would leak the spy's identity to all subscribers.player-joinedmust use explicit Broadcast (not Postgres Changes) — PG Changes on the Players table don't include the username, which would require an extra client-side DB join.