Update root and per-directory AGENTS.md files to reflect the current state of the codebase: collection inventory, RBAC registry, base management, personnel pages, training minigames, Discord bot transfer and evaluation-reminder flows, banking currency config, migration wrapper, and Playwright/Vivaldi e2e details.
4.9 KiB
AGENTS.md — Frontend Components
Parent:
../../AGENTS.md— commands, auth flow, Next.js 16 rules, deployment.
Overview
100+ client components organized by domain. The (frontend) layout renders guests LandingPage (no app shell); authed users get AppSidebar + SiteHeader + CommandPalette.
Structure
components/frontend/
auth/ 2 files LoginForm, LoginLink (returnTo via usePathname)
account/ 16 files Profile, password, preferences, Discord link
awards/ 4 files Medal/ribbon display, award dialogs
banking/ 9 files Account cards, ledger, deposit/withdraw/transfer dialogs
baseManagement/ 4 files StaffRoster, HireStaffDialog, EmploymentCard, UpgradeCard (structure page)
blocks/ 7 files AppSidebar (data in sidebarData.ts), NavCore, NavUser, XPDisplay
dashboard/ 6 files ProfileSummary, QuickStats, MissionBriefing, RecentEvents
eod/ 4 files Minefield Clearance minigame
evaluations/ 0 files EMPTY directory (placeholder — no components yet)
flappy/ 4 files Flight Simulator canvas game, leaderboard, sounds
helpdesk/ 8 files Ticket list/detail, create dialog, timeline
impersonation/ 2 files Admin impersonation banner/controls
intelligence/ 17 files Mission cards/attendance/comms, campaign/faction cards
locker/ 13 files Grid, equipment editor, loadouts, wardrobe
logistics/ 8 files Shipment cards/actions, toast notifications
market/ 10 files Listing cards, negotiation flow, NPC chat, patience meter
notifications/ 2 files Bell (polling), inbox page
personnel/ 3 files NpcDirectory, NpcCard, NpcProfile (/personnel/contacts)
profile/ 3 files Profile page components (incl. rating dialog)
projects/ 12 files Jira-like boards, releases, sprints
qualification/ 6 files Aim trainer arena/game/canvas/leaderboard, sounds
radio/ 5 files Radio Traffic game, message generator, leaderboard
realtime/ 1 file GameTickRealtime (SSE -> router.refresh)
roster/ 1 file Org chart view
session/ 1 file Session expiry UI (pairs with useSessionExpired hook)
shims/ 1 file Frontend shim renderer
storage/ 14 files Structure grid, storage dialogs, event ledger
transfers/ 7 files Assignment transfer request/decision UI
wiki/ 11 files Index, editor + toolbar, content renderer, revisions, standards dialog
+ root files: LandingPage.tsx, SiteHeader.tsx, ClientDate.tsx, PayloadButtons.tsx
Conventions
Server → Client data flow
Pages are server components that fetch via getPayload(), then pass data as props to client components. Client components receive typed props and never call Payload directly.
Item compound component
storage/ uses a compound <Item> component for grid cells with slots: <Item.Slot name="icon">, <Item.Slot name="stats">, <Item.Menu>. Attachments render as stacked badges on the grid cell; popover shows full detail on hover.
SSE consumers
GameTickRealtimemounts in(frontend)/layout.tsxfor all authed users.ShipmentToastsmounts only for logistics-qualified users.- Both use
useGameTick()hook (customptf:game-tickevent dispatch).
Nested dialogs
Market negotiation uses MakeOfferDialog nested inside ListingCard dialog. Loadout editor uses EquipmentEditorDialog nested inside locker grid. When a parent dialog unmounts (e.g., sold listing), the child stays visible for 3.5s minimum via useNow() hook for readability before refresh.
Route anomalies
logistics/vehicles/VehiclesList.tsx is a client component placed directly in the route directory (not under components/frontend/). This is the only route with an inline component file.
Where to look
| Task | Path |
|---|---|
| Add a new page | src/app/(frontend)/<domain>/page.tsx + create client component here |
| Add nav entry | src/components/frontend/blocks/sidebarData.ts (nav data extracted from AppSidebar) |
| Modify auth gate | src/app/(frontend)/layout.tsx (conditional renders LandingPage or shell) |
| Add SSE consumer | src/hooks/useGameTick.ts + mount in layout |
| NPC dialogue/chatter | src/lib/market/npcDialogue.ts (pure, client-safe import) |
| Minigame game rules | src/lib/aim-trainer.ts etc. — pure libs, components consume them |
| Keyboard shortcuts | src/components/command-palette/ |
| Admin custom fields | src/components/admin/ (awards designers, CollapsibleGroupField, narrative-flow, shims) |
Anti-patterns
- NEVER call
getPayload()in client components — fetch in server page, pass as props - NEVER add
useRouter().refresh()in SSE consumers without a guard — use theuseGameTick()hook - NEVER use shadcn defaults for dark theme — the admin panel's theme handles styling
- NEVER place server-side logic (hooks, Payload calls) in
"use client"files