Skip to main content

Overview

The Hyperscape client automatically deploys to Cloudflare Pages on push to main via GitHub Actions. This provides:
  • Global CDN - Fast loading worldwide
  • Automatic HTTPS - SSL certificates managed by Cloudflare
  • Preview deployments - Every commit gets a preview URL
  • Custom domains - hyperscape.gg, hyperscape.club

Automated Deployment

Workflow Trigger

The .github/workflows/deploy-pages.yml workflow triggers on:
Why Trigger on Shared Changes: The client depends on packages/shared for packet definitions. When packets change on the server, the client must rebuild to stay in sync. This prevents “Missing packet handler” errors. Example Scenario:
  1. Server adds new packet type (e.g., worldTimeSync)
  2. Shared package exports new packet definition
  3. Client rebuild triggered automatically
  4. Client includes new packet handler
  5. No runtime errors

Deployment Steps

1. Checkout Code:
2. Setup Bun:
3. Install Dependencies:
--frozen-lockfile prevents npm rate-limiting by using only the committed lockfile.
4. Build Client:
5. Deploy to Pages:

Multi-Line Commit Message Fix

Problem

Wrangler fails when commit messages contain newlines:

Solution

Extract only the first line (commit 3e4bb48):
Processing:
  1. Extract first line with head -1
  2. Remove quotes with tr -d '"'
  3. Truncate to 100 chars with cut -c1-100

Production URLs

Primary Domain

DNS Configuration:
  • CNAME: hyperscape.gghyperscape.pages.dev
  • Managed by Cloudflare Pages

Alternative Domain

Preview Deployments

Every commit gets a preview URL:
Example:

Required GitHub Secrets

Configure in Settings → Secrets → Actions:

Create Cloudflare API Token

  1. Go to Cloudflare Dashboard
  2. Navigate to My ProfileAPI Tokens
  3. Click Create Token
  4. Use Edit Cloudflare Workers template
  5. Add AccountCloudflare PagesEdit permission
  6. Copy token and add to GitHub Secrets

Environment Variables

Build-Time Variables

These are baked into the client build:
Build-time variables cannot be changed after deployment. To update, trigger a new build.

Cloudflare Pages Dashboard

You can also set environment variables in the Cloudflare Pages dashboard:
  1. Go to PageshyperscapeSettingsEnvironment variables
  2. Add variables for Production environment
  3. Trigger a new deployment

Manual Deployment

Using Wrangler CLI

Using GitHub Actions

Trigger manual deployment from GitHub UI:
  1. Go to Actions tab
  2. Select “Deploy Client to Cloudflare Pages” workflow
  3. Click “Run workflow”
  4. Select branch (usually main)
  5. Choose environment (production or preview)
  6. Click “Run workflow”

Concurrency Control

The workflow uses concurrency control to prevent multiple deployments:
Behavior:
  • Only one deployment per branch at a time
  • New deployment cancels in-progress deployment
  • Prevents race conditions and wasted resources

Deployment Summary

After successful deployment, the workflow outputs:

Troubleshooting

Build Failures

Check build logs:
  1. Go to Actions tab in GitHub
  2. Click on failed workflow run
  3. Expand “Build client” step
  4. Check error messages
Common Issues:
  • Missing environment variables
  • TypeScript errors
  • Dependency resolution failures
  • Out of memory (increase NODE_OPTIONS)

Deployment Failures

Check wrangler logs:
  1. Expand “Deploy to Cloudflare Pages” step
  2. Look for wrangler error messages
Common Issues:
  • Invalid CLOUDFLARE_API_TOKEN
  • Project name mismatch
  • Multi-line commit messages (fixed in commit 3e4bb48)

Preview URL Not Working

Check deployment status:
  1. Go to Cloudflare Dashboard
  2. Navigate to Pageshyperscape
  3. Check Deployments tab
  4. Verify deployment succeeded
Common Issues:
  • Deployment still in progress
  • Build failed (check logs)
  • DNS propagation delay (wait 5-10 minutes)

Assets Not Loading

Check CDN URL:
Check R2 CORS:
Verify assets exist:

CORS Errors

Problem: Client on hyperscape.gg cannot load assets from assets.hyperscape.club. Solution: Configure R2 CORS (see R2 CORS Configuration).

R2 CORS Configuration

Automated Configuration

The deploy-cloudflare.yml workflow includes a CORS configuration step:

Manual Configuration

Script Contents:
CORS Config File (commit 055779a):
Use nested allowed.origins/methods/headers structure. The old flat format (allowedOrigins) causes wrangler to fail.

Verify CORS

CSP Configuration

Content Security Policy

The client includes CSP headers in public/_headers:
Recent Updates (Feb 26 2026): Allow data: URLs for WASM (commit 8626299):
  • Required for PhysX WASM loading
  • img-src 'self' data: https: blob:
  • font-src 'self' data: https://fonts.gstatic.com
Allow Google Fonts (commit e012ed2):
  • Required for Rubik font
  • style-src 'self' 'unsafe-inline' https://fonts.googleapis.com
  • font-src 'self' data: https://fonts.gstatic.com
Remove broken report-uri (commit 8626299):
  • report-uri /api/csp-report removed (endpoint didn’t exist)

Vite Configuration

Node Polyfills Fix (commit e012ed2)

Problem: Production builds failed with “Failed to resolve module specifier” errors. Solution: Add aliases to resolve polyfill shims:

Production Checklist

  • CLOUDFLARE_API_TOKEN configured in GitHub Secrets
  • PUBLIC_PRIVY_APP_ID configured in GitHub Secrets
  • R2 CORS configured for asset loading
  • Custom domains configured in Cloudflare Pages dashboard
  • CSP headers configured in public/_headers
  • Environment variables set for production
  • Build succeeds locally with bun run build:client

Deployment Guide

General deployment documentation

Configuration

Environment variables and settings

Troubleshooting

Common issues and solutions

Railway Deployment

Game server deployment