Overview
Hyperscape uses Railway for backend deployment with automated GitHub Actions integration. The server handles both API requests and serves the built frontend for unified deployment.Architecture
Services
| Service | Platform | URL |
|---|---|---|
| Backend/API | Railway | hyperscape-production.up.railway.app |
| Frontend | Cloudflare Pages | hyperscape.club |
| Database | Railway PostgreSQL | Internal |
| Assets/CDN | Cloudflare R2 | cdn.hyperscape.club |
Automated Deployment
GitHub Actions Workflow
Deployments trigger automatically on push tomain:
- Checkout code
- Trigger Railway deployment via GraphQL API
- Wait for deployment to start
- Poll deployment status (5 attempts, 30s intervals)
- Report success or failure
Required Secrets
Configure in GitHub repository settings:| Secret | Purpose | Where to Get |
|---|---|---|
RAILWAY_TOKEN | API authentication | Railway dashboard → Account → Tokens |
RAILWAY_PROJECT_ID:e5f5ba11-0380-4d71-aa0b-343d89a58c0dRAILWAY_SERVICE_ID:f0b42e3b-3001-4ef1-926f-af6c3c138777RAILWAY_ENVIRONMENT_ID:194f3565-ba2f-4c98-87d2-85dfc3a5110b
Build Configuration
Nixpacks (nixpacks.toml)
Railway uses Nixpacks for builds:
- Builds shared, server, AND client in single deployment
- Copies client build to server’s
public/directory - Skips asset download (manifests fetched from CDN at runtime)
- Forces fresh Turbo builds (no cache)
Alternative: Docker Build
For Docker-based deployments, useDockerfile.server:
Environment Variables
Required
Optional
Railway-Specific
Railway automatically sets these:| Variable | Purpose |
|---|---|
RAILWAY_ENVIRONMENT | Environment name (production/staging) |
RAILWAY_SERVICE_ID | Service identifier |
DATABASE_URL | PostgreSQL connection string (if service added) |
Manifest Fetching
The server fetches manifests from CDN at startup instead of bundling them:items.jsonnpcs.jsonresources.jsontools.jsonbiomes.jsonworld-areas.jsonstores.jsonmusic.jsonvegetation.jsonbuildings.json
- Production: Always fetches from
PUBLIC_CDN_URL - Development: Skips if local manifests exist
- Fallback: Uses existing local manifests if CDN fetch fails
packages/server/world/assets/manifests/ and served to clients via /manifests/ route with 5-minute cache headers.
CORS Configuration
The server accepts requests from multiple origins: Production Domains:https://hyperscape.clubhttps://www.hyperscape.clubhttps://hyperscape.pages.devhttp://hyperscape.pages.dev(HTTP fallback)https://hyperscape-production.up.railway.app
http://localhost:*(any localhost port)https://*.hyperscape.pages.dev(Cloudflare preview deployments)https://*.up.railway.app(Railway preview deployments)
packages/server/src/startup/http-server.ts
Frontend Serving
The server serves the built client frompublic/ directory:
Routes:
/→public/index.html(no-cache headers)/assets/*→ Client assets (if they exist inpublic/assets/)/manifests/*→ Game data manifests (5-minute cache)/assets/world/*→ World assets (1-year cache, immutable)
index.html for client-side routing.
Debugging
Debug Endpoints
Check public directory contents:Build Verification
Railway build logs show:Health Check
Manual Setup
If not using GitHub Actions:Create Railway project
- Go to railway.app
- Create new project from GitHub repo
- Select
HyperscapeAI/hyperscape
Configure service
- Builder: Nixpacks (auto-detected)
- Root Directory:
/(monorepo root) - Start Command:
cd packages/server && bun dist/index.js
Troubleshooting
Build Fails
Check Railway logs for error messages:- Missing dependencies → Add to
nixpacks.tomlaptPkgs - Build timeout → Optimize build steps
- Out of memory → Upgrade Railway plan
Frontend Not Loading
Symptom: 503 error or “Frontend not available” Cause: Client build not copied topublic/
Solution: Verify build command includes:
Manifests Not Loading
Symptom: Game data missing or errors about missing manifests Cause: CDN fetch failed and no local manifests exist Solution:- Verify
PUBLIC_CDN_URLis set correctly - Check CDN is accessible from Railway
- Ensure manifests exist at
${PUBLIC_CDN_URL}/manifests/
Database Connection Failed
Symptom: Server crashes with database errors Cause:DATABASE_URL not set or PostgreSQL service not added
Solution:
- Add PostgreSQL service in Railway dashboard
- Verify
DATABASE_URLis set automatically - Run migrations:
bunx drizzle-kit push
Production Checklist
- Railway project created and connected to GitHub
- PostgreSQL service added
- Environment variables configured (JWT_SECRET, PRIVY_*, PUBLIC_CDN_URL)
- GitHub Actions secrets set (RAILWAY_TOKEN)
- Build succeeds and server starts
- Frontend accessible at Railway URL
- WebSocket connections working
- Manifests fetched from CDN successfully
- Database migrations applied