Frontend
A deep dive into the Next.js 16 frontend — components, rendering, and state management.
Component Overview
The frontend contains 18 React components organized under app/components/. Each handles a specific domain of the dashboard.
GalaxyCanvas
24,502-node galaxy map rendered on Canvas API with trust-colored pulsing and gate connections.
DualHeartbeat
Dual EKG monitor (Activity + Trust) with 300-point rolling buffer at ~30fps.
CHIGauge
SVG circular arc gauge showing the global Civilization Health Index (0-100).
TrustCompass
5-axis SVG radar chart for player reputation with archetype classification.
SystemPanel
Deep-dive panel with vitals, gate connections, neighbors, and player list.
AlertBell
Notification bell with dropdown showing detected anomalies by severity.
TimeLapse
Replay controller with 1x/2x/4x speed, range selector, and progress scrubber.
SearchPalette
Ctrl+K command palette for instant system search across all 24K systems.
PulseCards
Shareable SVG snapshot images (600x315px, Twitter card optimized).
WalletModal
Sui wallet connection/disconnect powered by @mysten/dapp-kit.
Galaxy Canvas
The main view renders all 24,502 solar systems as interactive nodes on an HTML5 Canvas. Visual properties encode real data:
| Visual Property | Data Encoded |
|---|---|
| Brightness | Player activity level (more players = brighter glow) |
| Color | Trust level: Green (≥70), Orange (40-70), Red (<40) |
| Node Size | Depth-based sizing from 3D coordinate normalization |
| Selection Ring | Dashed pulsing ring with glow effect on selected system |
| Gate Lines | Cyan flowing lines from selected system to gate destinations |
Canvas 2D Context — Render Stack
Performance
Dual Heartbeat EKG
Two synchronized heartbeat lines at the bottom of the screen visualize the relationship between activity and trust in real time:
| Pattern | Activity | Trust | Diagnosis |
|---|---|---|---|
| Thriving | High | High | Genuine civilization growth |
| Fever | High | Dropping | War, exploitation — trust is breaking |
| Hibernation | Low | Stable | Quiet but the social fabric is intact |
| Extinction | Dropping | Dropping | Civilization is collapsing |
Buffer: Rolling array of 300 data points (~30fps update rate)
Rendering: Quadratic Bezier curve interpolation (ctx.quadraticCurveTo)
Animation: requestAnimationFrame, shift buffer left, append new sample
Lines: Activity (white, 0.9 opacity) | Trust (green, 0.8 opacity)
Data Generation:
actBase = 50 + sin(t * 1.1) * 12 + sin(t * 2.7) * 6
actSpike = beatPhase < 0.3 ? sin(beatPhase / 0.3 * PI) * 25 : 0
activity = clamp(actBase + actSpike + random_noise)Trust Compass
Every player gets a 5-dimension reputation profile rendered as an SVG pentagon radar chart. The dimensions map directly to the on-chain PlayerReputation struct:
| Dimension | Measures | Question |
|---|---|---|
| Reliability | Behavioral consistency, assembly count | “Can they be counted on?” |
| Commerce | Trade fairness, infrastructure investment | “Are they honest in deals?” |
| Diplomacy | Cross-system cooperation, low aggression | “Do they bring people together?” |
| Stewardship | Infrastructure contribution, deployments | “Do they build for others?” |
| Volatility | Combat involvement (inverted: lower = better) | “Could they betray me?” |
Player Archetypes
Dimension patterns automatically classify players into behavioral archetypes:
Civilization Builder
Stewardship ≥ 80, Reliability ≥ 70
Trusted Trader
Commerce ≥ 80, Reliability ≥ 70
Diplomat
Diplomacy ≥ 75, Volatility < 30
Warlord
Volatility ≥ 70, Commerce < 40
Wildcard
50 ≤ Volatility < 70
Newcomer
Default archetype
State Management
The frontend uses Zustand 5 for lightweight client-side state with localStorage persistence for watchlist and wallet state:
// Key state slices:
interface AppStore {
selectedSystem: string | null; // Currently selected system ID
selectedPlayer: string | null; // Currently viewed player address
view: "galaxy" | "timelapse"; // Active view mode
trustFilter: "all" | "healthy" | "stressed" | "hostile";
watchlist: string[]; // Bookmarked system/player IDs
walletAddress: string | null; // Connected Sui wallet
}