- New game-event-logs collection with timestamp, type, message, actor, structure, targetCollection/targetId, and data (JSON) fields - EventTypes constants registry for modular event category management - emitGameEvent() utility for emitting events from server actions and hooks - Register collection in Payload config - Document event log system architecture in AGENTS.md
6.3 KiB
AGENTS.md — Polaris Task Force
What this is
Next.js 16 + Payload CMS 3.68.5 app for an Arma 3 unit. PostgreSQL database via @payloadcms/db-postgres + Drizzle. Tailwind CSS v4 (no config file — CSS-based). shadcn/ui (new-york style, lucide icons). Dark-themed frontend.
Package manager
Bun is the primary package manager (bun.lock, bunfig.toml). pnpm-lock.yaml also exists; use Bun for installs and running scripts.
Essential commands
bun install # install deps
bun run dev # dev server (webpack, localhost:3000)
bun run devsafe # clears .next cache then dev
bun run build # production build (--max-old-space-size=8000, webpack)
bun run lint # ESLint (next/core-web-vitals + next/typescript)
bun run test # runs test:int then test:e2e sequentially
bun run test:int # vitest integration tests only
bun run test:e2e # playwright e2e tests only
bun run db # drizzle-kit wrapper (e.g. bun run db migrate)
bun run generate:types # regenerates payload-types.ts
bun run generate:importmap # regenerates payload admin importMap
Type checking / linting order
bun run lint runs ESLint. There is no separate typecheck script — TypeScript errors surface during bun run lint and bun run build.
Test details
- Integration tests:
tests/int/**/*.int.spec.ts— Vitest with jsdom. Requires a live PostgreSQL database (connection from.env). Usesdotenv/configviavitest.setup.ts. - E2E tests:
tests/e2e/*.e2e.spec.ts— Playwright (Chromium only). Auto-startsbun run devviawebServerconfig. Currently minimal (homepage smoke test). - Run a single integration test:
bun run vitest run tests/int/api.int.spec.ts - Run a single e2e test:
bun run playwright test tests/e2e/frontend.e2e.spec.ts
Generated files — never edit manually
src/payload-types.ts— regenerated bybun run generate:typessrc/payload-generated-schema.ts— regenerated by Payload db-schema generationsrc/app/(payload)/admin/importMap.js— regenerated bybun run generate:importmapsrc/app/(payload)/layout.tsx— auto-generated by Payload
Path aliases
@/*→./src/*@payload-config→./src/payload.config.ts
App structure
src/app/(frontend)/— public-facing pages (dashboard, logistics, home). Layout has sidebar + auth check.src/app/(payload)/— Payload admin panel and API routes. Auto-generated layout.src/app/my-route/— example custom API route.
Collections (Payload CMS)
Organized by domain under src/collections/:
- users/ — Users (auth, username login), Ranks, Profiles, Awards, Qualifications, Assignments, Experience
- intelligence/ — Missions, Campaigns, Factions, Technologies
- logistics/ — Assets, Resources, Vehicles, Structures
- world/ — Maps, NarrativeEvents
- server/ — MissionFiles, ModLists
- game/ — GameRules (global), GameStructures, GameHardResources, GameEventLogs
Access control helpers live in src/utils/access-control/ (isRole, hasRoles). Roles: guest, user, admin, developer.
Event Log System
src/collections/game/GameEventLogs.ts — append-only game-event-logs collection.
- Schema:
timestamp,type(text/indexed),message(human-readable),actor(→ users),structure(→ game-structures),targetCollection/targetId(polymorphic ref),data(JSON blob). - Emit:
emitGameEvent(payload, { type, message, actor?, structure?, targetCollection?, targetId?, data? })insrc/utils/event-log/emit.ts. - Types:
EventTypesconstants insrc/utils/event-log/eventTypes.ts— add new event categories there without touching the collection. - Wiring: Server actions in
actions.tsemit events after successful mutations.GameStructuresafterChange hook catches admin-panel storage edits.StructuresbeforeChange hook emitsstructure:resize. - UI:
EventLedgercomponent (src/components/frontend/storage/EventLedger.tsx) queries the REST API for a givenstructureIdand renders a scrollable feed. Integrated inStructureStorageView.
Auth
Username-based login (no email login). Users log in via Payload admin with username only.
Database
PostgreSQL via @payloadcms/db-postgres. Schema defined in src/payload-generated-schema.ts. Migrations in src/migrations/ (timestamp-named .ts + .json pairs, registered in migrations/index.ts). Drizzle config reads DATABASE_URI from env.
In development, postgresAdapter uses push: true to auto-sync schema.
Code style
- Prettier: double quotes, trailing commas (all), 100 char print width, semicolons.
- ESLint:
next/core-web-vitals+next/typescript.@typescript-eslint/no-unused-varswarns (prefix unused with_). - Tailwind v4: no
tailwind.config— configured via@tailwindcss/postcssinpostcss.config.mjsand CSS imports. Usecn()from@/lib/utilsfor class merging.
UI components
shadcn/ui components live in src/components/ui/. Use bunx shadcn@latest add <component> to add new ones. Frontend components in src/components/frontend/. Payload admin custom components referenced in payload.config.ts under admin.components.
Environment
.env— local dev (PostgreSQL connection string + PAYLOAD_SECRET).env.example— template (still shows MongoDB URI — outdated, the app uses PostgreSQL).env.test— test/staging databasetest.env— NODE_OPTIONS for playwright (loaded by playwright config)
Deploy
bun run deploy bumps patch version (via bun pm version patch), builds, then runs build/deploy.sh. The build/ directory is gitignored so the deploy script is not in the repo.
Gotchas
.env.exampleshows MongoDB URI but the app uses PostgreSQL — trustDATABASE_URIformat in.env.testas the real reference.bun run buildpasses--max-old-space-size=8000— the build is memory-intensive.- The
devturboscript uses Turbopack;devanddevsafeuse webpack. These are different bundlers with different behavior. - Playwright tests auto-start the dev server — make sure port 3000 is free before running e2e.
- Payload admin layout and importMap are auto-generated — do not edit by hand.
.npmrcsetslegacy-peer-deps=truefor dependency resolution compatibility.