1
0
Fork 0
polaris-task-force/src/components/frontend/AGENTS.md
Z8MB1E a8e147e52a docs: add AGENTS.md subdirectories and login case study
Add domain-specific AGENTS.md files for collections, components, lib,
utils, and bot. Add login-return-url case study documenting the
return-URL flow design decisions and debugging lessons learned.
2026-08-19 19:48:35 -04:00

3.5 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/        4 files    Profile, password, preferences, Discord link
  banking/        9 files    Account cards, ledger, deposit/withdraw/transfer dialogs
  blocks/         6 files    AppSidebar, NavCore, NavUser, XPDisplay
  dashboard/      6 files    ProfileSummary, QuickStats, MissionBriefing, RecentEvents
  flappy/         4 files    Canvas game, leaderboard, sounds
  helpdesk/       6 files    Ticket list/detail, create dialog, timeline
  intelligence/  13 files    Mission cards/attendance/comms, campaign/faction cards
  locker/        12 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
  realtime/       1 file     GameTickRealtime (SSE -> router.refresh)
  roster/         1 file     Org chart view
  storage/       14 files    Structure grid, storage dialogs, event ledger

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

  • GameTickRealtime mounts in (frontend)/layout.tsx for all authed users.
  • ShipmentToasts mounts only for logistics-qualified users.
  • Both use useGameTick() hook (custom ptf:game-tick event 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/NavCore.tsx
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)
Keyboard shortcuts src/components/command-palette/

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 the useGameTick() 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