- Redesign homepage as authenticated operations dashboard
- Add ProfileSummary, MissionBriefing, RecentEvents, QuickStats components
- Add UpcomingMissions and ActiveCampaigns sidebar widgets
- Redirect /dashboard to / (homepage is now the dashboard)
- Show welcome screen with login link for unauthenticated users
- Add resolveLevel utility to compute level name, progress, and XP thresholds
- Add seedExperience script for populating experience levels
- Update XPDisplay to show level name, progress bar, and percentage to next level
- Update layout to fetch experience levels and pass resolved XP data to sidebar
- NodeShell component wraps all nodes with handle rendering + px-8 content padding
- Handles positioned at node edges with labels outside (no overlap with content)
- Labels: 9px mono font, full opacity, color-matched to socket type
- Removed old TypedHandle + NodeHandles (replaced by NodeShell internals)
- All 18 node components updated to use NodeShell
- Format node dynamically generates handles from template {0}, {1}, etc.
- TypedHandle now shows tiny 8px labels next to handles (color-matched)
- Labels positioned outside the handle, no overlap with node content
- Format node dynamically generates input handles from template {0}, {1}, etc.
- NodeHandles accepts dynamicInputs/dynamicOutputs overrides
- isValidConnection treats dynamic handles (arg-*, option-*) as any-type
- New node types:
- Wait: delays execution for N ticks, supports optional input
- Number: stores a numeric value
- String: stores a string value
- Random: generates random numbers in range [min, max]
- Boolean: stores true/false flag
- Date: stores a date value
- Color-coded nodes matching React Flow palette:
- Wait: yellow
- Number: purple
- String: teal
- Random: pink
- Boolean: emerald
- Date: cyan
- NodeEditDialog now handles all new types with appropriate fields
- Toolbar updated with color-matched buttons
- Browser button elements have default background/border
- Span with onClick provides the same functionality with no defaults
- Maintains keyboard focus states and accessibility
- NarrativeEvents collection redesigned with flowData JSON (React Flow format)
- Custom admin field component: NarrativeFlowEditor with @xyflow/react
- Three node types: NarrativeBeat (blue), Choice (amber), Outcome (emerald)
- NodeEditDialog with type-specific forms replacing prompt() editing
- Right-click context menu (Delete node/edge with Radix primitives)
- Dynamic handles on Choice nodes (one per option)
- Dark-themed canvas with MiniMap, Controls, and animated edges
- All changes sync bidirectionally with Payload form state
- AGENTS.md updated with architecture docs
- Client-side EventLedger component that queries game-event-logs REST API
for a given structureId and renders a scrollable feed
- Actor name prefix with 'You' substitution for the current user, messages
lowercased to fit sentence syntax
- Multi-select dropdown filter (shadcn DropdownMenuCheckboxItem) for event
types with PascalCase formatting
- Narrative/GM events (system: false) styled with amber accent + book icon
- Smart refresh: smooth re-fetch without clearing existing entries, 30s
polling interval, and instant refreshKey trigger from parent actions
- 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
Server action: remove 'other.id === entryId' exclusion from the
split overlap scan so the source item's own footprint is treated
as occupied, forcing the split to find a different position.
UI: disable the split button via findEmptySpot check when no room
exists for the split stack, preventing a failed action.
- Move storage overview from /logistics/storage to /logistics root
- Rename page heading and sidebar label from Storage to Structures
- Update back link on structure detail page
- Remove old /logistics/storage route
ManageStorageDialog now calls router.refresh() after deposit,
withdraw, and transfer so the grid view reflects changes.
Await fetchData() before refreshing.
Resource labels now use pluralize() for correct unit display
(e.g. "1 liter" vs "3 liters").
- Withdraw/Transfer tabs: max = currently stored amount of selected resource
- Deposit tab: max = remaining capacity divided by resource massPerUnit
- Amount auto-clamps when resource selection changes
- Show 'Max: X' hint below each amount input
- Replace static descriptions in admin fields with dynamic `TickDurationDescription` components.
- Add minimum and maximum constraints to duration fields in various schemas.
- Update `TickDurationDescription` to use `useField` hook for better form integration.
- Added Google Fonts import for `Geist` and `Geist Mono` to `styles.css`.
- Aligned, cleaned styling variables and properties consistently.
- Updated `seedUsers.ts` to include a developer role.
- Introduced `bun.lock` file for dependency management.