Skip to main content

Overview

The @hyperscape/client package is the web game client:
  • Vite for fast builds with HMR
  • React 19 UI framework
  • Three.js 3D rendering (WebGPU with WebGL fallback)
  • Privy authentication
  • Farcaster miniapp SDK
  • Tauri desktop app support
  • Solana wallet integration

Rendering

WebGPU with WebGL Fallback

The client uses THREE.WebGPURenderer with automatic fallback to WebGL for compatibility: WebGPU (Preferred):
  • Modern high-performance rendering
  • TSL post-processing effects
  • Cascaded shadow maps (CSM)
  • Requires Chrome 113+, Edge 113+, or Safari 17+
WebGL (Fallback):
  • Graceful degradation for older browsers and WebViews
  • Single directional shadow maps (no CSM)
  • Disabled TSL post-processing
  • Works in WKWebView (Tauri), older Safari, and browsers without WebGPU
Backend Detection:
import { isWebGPURenderer, getRendererBackend } from "@hyperscape/shared";

const renderer = await createRenderer();
const isWebGPU = isWebGPURenderer(renderer);  // true or false
const backend = getRendererBackend(renderer); // "webgpu" or "webgl"
The settings panel displays the active renderer type to users.

Package Location

packages/client/
├── src/
│   ├── auth/           # Privy authentication
│   ├── constants/      # Client constants
│   ├── game/           # Game loop and logic
│   │   ├── character/  # Character rendering
│   │   ├── chat/       # Chat system
│   │   ├── components/ # Game-specific components
│   │   ├── dashboard/  # Agent dashboard
│   │   ├── hud/        # HUD elements
│   │   ├── interface/  # Interface manager
│   │   ├── panels/     # Game panels (inventory, bank, combat, etc.)
│   │   ├── systems/    # Client-side game systems
│   │   └── types/      # Game type definitions
│   ├── hooks/          # React hooks
│   ├── lib/            # Networking, utilities, error handling
│   ├── screens/        # UI screens
│   ├── types/          # TypeScript types
│   ├── ui/             # UI system
│   │   ├── components/ # Reusable UI components (Window, TabBar, Portal, etc.)
│   │   ├── controls/   # Form controls (Slider, Toggle, Select, etc.)
│   │   ├── core/       # Core UI systems (drag-and-drop, window management, presets)
│   │   ├── stores/     # Zustand state stores
│   │   ├── theme/      # Theme system
│   │   └── types/      # UI type definitions
│   ├── utils/          # Helper functions
│   └── index.tsx       # React entry point
├── public/             # Static assets (fonts, textures, LUTs)
├── tests/              # E2E (Playwright) and unit tests (Vitest)
├── scripts/            # Deployment scripts
├── vite.config.ts      # Vite configuration
├── vitest.config.ts    # Vitest configuration
├── playwright.config.ts # E2E test configuration
├── wrangler.toml       # Cloudflare Pages config
└── .env.example        # Environment template

Screens

Located in src/screens/:
// From packages/client/src/screens/
LoginScreen.tsx           // Privy authentication
LoadingScreen.tsx         // Asset loading
UsernameSelectionScreen.tsx  // First-time username
CharacterSelectScreen.tsx // Choose character
CharacterEditorScreen.tsx // Create/edit character with VRM preview
DashboardScreen.tsx       // Game hub / lobby
GameClient.tsx            // Main 3D gameplay
AdminScreen.tsx           // Admin dashboard
ScreenPurpose
LoginScreenPrivy authentication
UsernameSelectionScreenFirst-time username entry
CharacterSelectScreenChoose existing character
CharacterEditorScreenCreate/edit character (VRM preview)
DashboardScreenGame hub and lobby
GameClientMain 3D gameplay
LoadingScreenAsset loading state
AdminScreenAdmin dashboard and tools

UI System Architecture

UI System (src/ui/)

Complete UI system with components, hooks, stores, and theming:
src/ui/
├── components/        # UI components (45+ files)
│   ├── Window.tsx     # Draggable, resizable windows
│   ├── Tab.tsx        # Tab component
│   ├── TabBar.tsx     # Tab container
│   ├── Slider.tsx     # Range slider
│   ├── Portal.tsx     # React portal
│   ├── MenuButton.tsx # Menu buttons
│   ├── ActionBar.tsx  # Action bar
│   ├── BuffBar.tsx    # Buff display
│   ├── ItemSlot.tsx   # Inventory slot
│   ├── Minimap.tsx    # Minimap component
│   ├── ScrollableArea.tsx # Scrollable containers
│   ├── VirtualList.tsx    # Virtual scrolling
│   ├── VirtualGrid.tsx    # Virtual grid
│   └── ...
├── controls/          # Form controls
│   ├── ColorControl.tsx
│   ├── KeybindControl.tsx
│   ├── SelectControl.tsx
│   ├── SliderControl.tsx
│   └── ToggleControl.tsx
├── core/              # Core UI systems
│   ├── drag/          # Drag-and-drop (@dnd-kit)
│   ├── edit/          # Edit mode (L key unlock)
│   ├── notifications/ # Toast notifications
│   ├── presets/       # Layout presets and cloud sync
│   ├── responsive/    # Breakpoints, mobile layout
│   ├── settings/      # Settings schema
│   ├── tabs/          # Tab management
│   ├── tooltip/       # Progressive tooltips
│   ├── virtual/       # Virtual scrolling
│   └── window/        # Window management
├── stores/            # Zustand stores
│   ├── windowStore.ts       # Window state
│   ├── themeStore.ts        # Theme state
│   ├── dragStore.ts         # Drag state
│   ├── editStore.ts         # Edit mode state
│   ├── presetStore.ts       # Layout presets
│   ├── keybindStore.ts      # Keybindings
│   ├── notificationStore.ts # Notifications
│   ├── accessibilityStore.ts # Accessibility
│   ├── complexityStore.ts   # UI complexity
│   └── questStore.ts        # Quest tracking
├── theme/             # Theme system
│   ├── themes.ts      # Dark theme
│   └── animations.ts  # CSS animations
└── types/             # TypeScript types

Game Components (src/game/components/)

Domain-organized game UI components:
src/game/components/
├── chat/              # Chat system
│   ├── ChatBox.tsx
│   ├── ChatMessage.tsx
│   ├── ChatInput.tsx
│   └── ChatTabs.tsx
├── currency/          # Currency display
│   ├── CurrencyDisplay.tsx
│   ├── CurrencyExchange.tsx
│   ├── CurrencyIcon.tsx
│   ├── CurrencyInput.tsx
│   └── CurrencyTooltip.tsx
├── dialog/            # NPC dialogue
│   ├── DialogBox.tsx
│   ├── DialogChoices.tsx
│   ├── DialogHistory.tsx
│   ├── DialogPortrait.tsx
│   └── DialogText.tsx
├── equipment/         # Equipment panel
│   ├── CharacterModel.tsx
│   ├── EquipmentPanel.tsx
│   ├── EquipmentSlot.tsx
│   ├── ItemComparison.tsx
│   └── StatsSummary.tsx
├── map/               # World map
│   ├── WorldMap.tsx
│   ├── MapControls.tsx
│   ├── MapMarker.tsx
│   ├── MapLegend.tsx
│   └── MapTooltip.tsx
├── quest/             # Quest system
│   ├── QuestLog.tsx
│   ├── QuestEntry.tsx
│   ├── QuestObjective.tsx
│   ├── QuestRewards.tsx
│   └── QuestTracker.tsx
├── settings/          # Settings panel
│   ├── SettingsPanel.tsx
│   ├── SettingsCategory.tsx
│   └── SettingsControl.tsx
└── skilltree/         # Skill tree
    ├── SkillTree.tsx
    ├── SkillNode.tsx
    ├── SkillConnection.tsx
    └── SkillTooltip.tsx

HUD Components (src/game/hud/)

src/game/hud/
├── StatusBars.tsx           # Health/Constitution display
├── ActionProgressBar.tsx    # Action progress
├── Minimap.tsx              # World minimap
├── MinimapCompass.tsx       # Compass overlay
├── MinimapStaminaBar.tsx    # Stamina indicator
├── MinimapOverlayControls.tsx
├── RadialMinimapMenu.tsx    # Radial menu
├── HomeTeleportButton.tsx   # Teleport home
├── ContextMenu.tsx          # Right-click menus
├── EntityContextMenu.tsx    # Entity interactions
├── EscapeMenu.tsx           # Pause menu
├── ConnectionIndicator.tsx  # Network status
├── level-up/                # Level-up system
│   ├── LevelUpNotification.tsx
│   ├── LevelUpPopup.tsx
│   └── UnlocksSection.tsx
├── overlays/                # Screen overlays
│   ├── DeathScreen.tsx
│   ├── DisconnectedOverlay.tsx
│   └── KickedOverlay.tsx
└── xp-orb/                  # XP progress orbs
    ├── XPProgressOrb.tsx
    ├── XPProgressOrbs.tsx
    └── FloatingXPDrops.tsx

Anchor-Based Positioning

Windows use Unity/Unreal-style anchors for responsive scaling:
  • 9 anchor points: corners, edges, center
  • Offset-based: Windows store offset from anchor, not absolute position
  • Responsive: Preserves anchor relationships on resize
  • Default anchors:
    • Chat, Skills/Prayer: bottom-left
    • Minimap: top-right
    • Inventory, Menubar: bottom-right
    • Action bar: bottom-center

Drag-and-Drop System

Powered by @dnd-kit with custom enhancements:
  • Inventory items: Drag to move, combine, or drop
  • Action bar: Drag skills, prayers, combat styles
  • Tabs: Drag to reorder or combine windows
  • Windows: Drag headers to move
  • Context menus: Right-click for OSRS-style menus

Environment Variables

Development

# Required for persistent authentication
PUBLIC_PRIVY_APP_ID=your-privy-app-id

# Server URLs (defaults to localhost)
PUBLIC_API_URL=http://localhost:5555
PUBLIC_WS_URL=ws://localhost:5555/ws
PUBLIC_CDN_URL=http://localhost:8080

Production (Cloudflare Pages)

# Required
PUBLIC_PRIVY_APP_ID=your-privy-app-id

# Production endpoints
PUBLIC_API_URL=https://hyperscape-production.up.railway.app
PUBLIC_WS_URL=wss://hyperscape-production.up.railway.app/ws
PUBLIC_CDN_URL=https://assets.hyperscape.club
PUBLIC_APP_URL=https://hyperscape.club

# Optional
PUBLIC_ENABLE_FARCASTER=true
DEBUG_RPG=0
PUBLIC_PRIVY_APP_ID must match the PRIVY_APP_ID set in the server environment. Mismatched IDs will cause authentication failures.
All PUBLIC_* variables are exposed to the browser. Never put secrets in client environment variables.

Running

Development

bun run dev:client    # Vite dev server with HMR
Opens at http://localhost:3333

Production Build

cd packages/client
bun run build         # Build to dist/
bun run preview       # Preview production build

Dependencies

PackagePurpose
reactUI framework (v19)
react-domReact DOM renderer
three3D rendering (v0.181)
@hyperscape/sharedCore engine
@privy-io/react-authAuthentication
@farcaster/miniapp-sdkFarcaster integration
@dnd-kit/coreDrag-and-drop core
@dnd-kit/sortableSortable lists
@pixiv/three-vrmVRM avatar support
@solana/wallet-adapter-reactSolana wallet
@tauri-apps/apiDesktop app integration
livekit-clientVoice chat
lucide-reactIcons
d3Data visualization
tailwindcssUtility CSS
viteBuild tool

Deployment

Cloudflare Pages (Production)

The client deploys to Cloudflare Pages with automatic GitHub integration: Configuration:
  • Build command: cd packages/client && bun install && bun run build
  • Build output: packages/client/dist
  • Root directory: / (monorepo root)
  • Node version: 22
Environment Variables (Cloudflare Pages):
PUBLIC_PRIVY_APP_ID=<from-privy-dashboard>
PUBLIC_API_URL=https://hyperscape-production.up.railway.app
PUBLIC_WS_URL=wss://hyperscape-production.up.railway.app/ws
PUBLIC_CDN_URL=https://assets.hyperscape.club
PUBLIC_APP_URL=https://hyperscape.club
Deployment Process:
  1. Push to main branch
  2. Cloudflare Pages detects changes to packages/client/**
  3. Builds client with Vite
  4. Deploys to hyperscape.pages.dev and hyperscape.club
  5. Creates preview deployments for pull requests
Preview Deployments:
  • URL pattern: https://<branch>-<hash>.hyperscape.pages.dev
  • Automatic for every PR
  • Uses production environment variables
  • CORS automatically allows *.hyperscape.pages.dev origins

Vite Configuration

// packages/client/vite.config.ts
export default defineConfig({
  envPrefix: 'PUBLIC_',  // Expose PUBLIC_* vars to client
  build: {
    outDir: 'dist',
    sourcemap: true,
    rollupOptions: {
      output: {
        manualChunks: {
          'three': ['three'],
          'react': ['react', 'react-dom']
        }
      }
    }
  }
});
Only PUBLIC_* prefixed environment variables are exposed to the client. Never put secrets in client environment variables.

Key Files

FilePurpose
src/index.tsxReact entry point
src/game/Game loop and logic
src/screens/UI screens
src/ui/UI system (windows, drag-drop, stores)
vite.config.tsVite configuration
vitest.config.tsUnit test configuration
playwright.config.tsE2E test configuration
wrangler.tomlCloudflare Pages config