Overview
The @hyperscape/website package is the official marketing website for Hyperscape, featuring a modern landing page with 3D effects, responsive design, and the $GOLD token page.
Tech Stack:
Next.js 15 : React framework with static export
React 19 : UI framework
Three.js : 3D rendering and effects
React Three Fiber : Declarative Three.js
Tailwind CSS 4 : Utility-first styling
Framer Motion : Animations
GSAP : Advanced animations
Lenis : Smooth scrolling
Package Structure
packages/website/
├── src/
│ ├── app/
│ │ ├── page.tsx # Landing page
│ │ ├── gold/
│ │ │ └── page.tsx # $GOLD token page
│ │ ├── layout.tsx # Root layout with metadata
│ │ └── globals.css # Global styles and theme
│ ├── components/
│ │ ├── Header.tsx # Navigation header
│ │ ├── Footer.tsx # Footer with links
│ │ ├── Background.tsx # Reusable background component
│ │ ├── Hero/ # Landing page hero
│ │ ├── Features/ # Features section
│ │ ├── CTA/ # Call-to-action section
│ │ └── GoldToken/ # $GOLD token page
│ └── lib/
│ └── fonts.ts # Font configuration
├── public/
│ ├── images/ # Static images
│ └── fonts/ # Custom fonts
├── next.config.ts # Next.js configuration
├── tailwind.config.ts # Tailwind configuration
└── package.json
Development
Commands
# From packages/website/
bun run dev # Start dev server (port 3334)
bun run build # Build static site
bun run start # Start production server
bun run lint # Run ESLint
bun run typecheck # TypeScript type checking
Port Allocation
Port Service 3334 Website dev server
The website runs on port 3334 to avoid conflicts with the game client (3333) and other services.
Configuration
Next.js Config
Location: packages/website/next.config.ts
const config : NextConfig = {
output : "export" , // Static site generation
images : {
unoptimized : true , // No image optimization for static export
} ,
trailingSlash : true , // Add trailing slashes to URLs
transpilePackages : [
"three" ,
"@react-three/fiber" ,
"@react-three/drei" ,
"@react-three/postprocessing" ,
] ,
typescript : {
ignoreBuildErrors : true , // R3F types don't work with jsx: preserve
} ,
eslint : {
ignoreDuringBuilds : true , // Warnings acceptable for initial build
} ,
};
TypeScript build errors are ignored because React Three Fiber types conflict with Next.js’s jsx: preserve mode. The code works at runtime.
Environment Variables
Location: packages/website/.env.example
# External URLs
NEXT_PUBLIC_DOCS_URL = https://hyperscape-ai.mintlify.app/
NEXT_PUBLIC_GAME_URL = https://play.hyperscape.club
NEXT_PUBLIC_DISCORD_URL = https://discord.gg/f4ZwhAbKye
NEXT_PUBLIC_TWITTER_URL = https://x.com/hyperscapeai
NEXT_PUBLIC_GITHUB_URL = https://github.com/hyperscape-ai
Copy .env.example to .env.local and fill in values.
Pages
Landing Page (/)
Components:
Header - Navigation with logo and links
Hero - Main hero section with logo, tagline, and CTA
Features - Feature cards with icons
CTA - Call-to-action banner
Footer - Links and social media
Background - Gradient background with image overlay
Features:
Responsive layout (mobile, tablet, desktop)
Staggered animations with Framer Motion
Smooth scrolling with Lenis
Dark fantasy theme with gold accents
$GOLD Token Page (/gold)
Components:
GoldToken - Complete token page with scroll design
Two-column hero - Token image and description
Token details - Contract address with copy-to-clipboard
Features - Token utility and benefits
How it works - Token mechanics
CTA - Call-to-action with banner
Token Information:
1 $GOLD = 1 gold in-game
Be the richest player at launch
Exclusive items for top holders
Styling
Theme Configuration
Location: packages/website/src/app/globals.css
Custom CSS variables for consistent theming:
@theme {
/* Typography */
--font-display: 'Cinzel' , serif;
--font-body: 'Rubik' , system-ui , sans-serif ;
/* Gold palette */
--gold-essence: #d4a84b;
--gold-flame: #ffd866;
--gold-dim: #c49530;
--gold-ember: #b8860b;
/* Background depths */
--bg-depth: #0a0a0c ;
--bg-surface: #141416 ;
--bg-elevated: #1e1e22 ;
/* Glass effects */
--glass-surface: rgba(10 , 10 , 12 , 0 .85 );
--glass-border: rgba(45 , 40 , 32 , 0 .5 );
--glass-highlight: rgba(212 , 168 , 75 , 0 .1 );
}
Utility Classes
.glass /* Glass morphism effect */
.glow-gold /* Gold glow filter */
.text-gradient-gold /* Gold gradient text */
.border-gradient-gold /* Gold gradient border */
.btn-primary /* Primary button style */
.btn-secondary /* Secondary button style */
.animate-slow-zoom /* 60s zoom animation */
.animate-float /* 6s float animation */
.animate-glow-pulse /* 2s glow pulse */
.container-padding /* Responsive container padding */
Responsive Container Padding
/* Mobile: 12px */
.container-padding { padding-left : 0.75 rem ; padding-right : 0.75 rem ; }
/* Tablet (640px+): 16px */
@media ( min-width : 640 px ) {
.container-padding { padding-left : 1 rem ; padding-right : 1 rem ; }
}
/* Desktop (1024px+): 24px */
@media ( min-width : 1024 px ) {
.container-padding { padding-left : 1.5 rem ; padding-right : 1.5 rem ; }
}
Components
Background
Location: packages/website/src/components/Background.tsx
Reusable background with gradient overlay:
< Background
image = "/images/app_background.png" // Default
opacity = { 0.04 } // Default
/>
< Background
image = "/images/gold_background.png" // Custom for $GOLD page
opacity = { 0.04 }
/>
Features:
Fixed positioning (stays in place during scroll)
Horizontal gradient with dark center, gold-tinted edges
Customizable background image
Adjustable opacity
Hero
Location: packages/website/src/components/Hero/Hero.tsx
Landing page hero section:
Features:
Responsive layout (stacks on mobile)
Logo with glow effect
Tagline with gradient text
CTA button with hover effects
Staggered animations (logo → tagline → button)
Features
Location: packages/website/src/components/Features/Features.tsx
Feature cards section:
Features:
Grid layout (1 column mobile, 2 columns desktop)
Icon + title + description
Hover effects
Responsive sizing
CTA
Location: packages/website/src/components/CTA/CTA.tsx
Call-to-action section:
Features:
Banner background image
Gradient overlay
Centered text and button
Responsive padding
GoldToken
Location: packages/website/src/components/GoldToken/GoldToken.tsx
Complete $GOLD token page:
Sections:
Two-column hero (token image + description)
Token details with contract address
Features grid
How it works
CTA section
Features:
Scroll-style design
Copy-to-clipboard for contract address
Responsive layout
Gold theme throughout
Fonts
Font Configuration
Location: packages/website/src/lib/fonts.ts
import { Cinzel } from "next/font/google" ;
import localFont from "next/font/local" ;
export const cinzel = Cinzel ({
subsets : [ "latin" ] ,
variable : "--font-display" ,
display : "swap" ,
});
export const rubik = localFont ({
src : "../../public/fonts/rubik.woff2" ,
variable : "--font-body" ,
display : "swap" ,
});
Usage:
Cinzel : Display font for headings
Rubik : Body font for content
Location: packages/website/src/app/layout.tsx
export const metadata : Metadata = {
metadataBase : new URL ( "https://hyperscape.club" ) ,
title : "Hyperscape - The First AI-Native MMORPG" ,
description : "Where autonomous agents powered by ElizaOS play alongside humans..." ,
keywords : [ "MMORPG" , "AI gaming" , "RuneScape" , "ElizaOS" , ... ] ,
openGraph : {
title : "Hyperscape - The First AI-Native MMORPG" ,
images : [{ url : "/images/og-image.jpg" , width : 1200 , height : 630 }] ,
} ,
twitter : {
card : "summary_large_image" ,
site : "@hyperscapeai" ,
} ,
};
Page-Specific Metadata
// packages/website/src/app/gold/page.tsx
export const metadata : Metadata = {
title : "$GOLD Token - Hyperscape" ,
description : "The official token of Hyperscape. 1 $GOLD = 1 gold in-game." ,
};
Deployment
Static Export
The website builds to a static site for deployment:
bun run build
# Output: out/ directory
Build Output:
HTML files for each page
Optimized CSS and JavaScript
Static assets (images, fonts)
No server-side rendering required
Deployment Targets
Compatible with:
Vercel (recommended)
Netlify
Cloudflare Pages
GitHub Pages
Any static hosting
Dependencies
Core Dependencies
{
"next" : "^15.1.0" ,
"react" : "^19.0.0" ,
"react-dom" : "^19.0.0" ,
"@react-three/fiber" : "^9.0.0" ,
"@react-three/drei" : "^10.0.0" ,
"@react-three/postprocessing" : "^3.0.0" ,
"three" : "^0.170.0" ,
"gsap" : "^3.12.0" ,
"framer-motion" : "^11.15.0" ,
"lenis" : "^1.1.0" ,
"detect-gpu" : "^5.0.0"
}
Dev Dependencies
{
"@types/three" : "^0.170.0" ,
"@types/node" : "^22.0.0" ,
"@types/react" : "^19.0.0" ,
"@types/react-dom" : "^19.0.0" ,
"typescript" : "^5.9.2" ,
"tailwindcss" : "^4.0.0" ,
"@tailwindcss/postcss" : "^4.0.0" ,
"postcss" : "^8.5.0" ,
"eslint" : "^9.0.0" ,
"eslint-config-next" : "^15.1.0"
}
Image Optimization
Images are unoptimized for static export:
// next.config.ts
images : {
unoptimized : true ,
}
For production, consider:
Pre-optimizing images with Sharp
Using WebP format
Responsive image sizes
GPU Detection
Location: Uses detect-gpu package
import { getGPUTier } from "detect-gpu" ;
const gpuTier = await getGPUTier ();
if ( gpuTier .tier < 2 ) {
// Disable heavy 3D effects
// Use CSS fallback animations
}
Reduced Motion
Respects user preferences:
@media (prefers-reduced-motion : reduce) {
* ,
* ::before ,
* ::after {
animation-duration : 0.01 ms !important ;
animation-iteration-count : 1 !important ;
transition-duration : 0.01 ms !important ;
}
}
Accessibility
Features
Semantic HTML structure
ARIA labels on interactive elements
Keyboard navigation support
Focus visible states
Reduced motion support
High contrast text (WCAG AA compliant)
Color Contrast
All text meets WCAG AA standards:
Primary text: #f5f0e8 on #0a0a0c (17.8:1)
Secondary text: #c4b896 on #0a0a0c (10.2:1)
Muted text: #7d7460 on #0a0a0c (4.8:1)
Customization
Adding a New Page
Create page file in src/app/:
// src/app/about/page.tsx
import { Metadata } from "next" ;
import { Header } from "@/components/Header" ;
import { Footer } from "@/components/Footer" ;
import { Background } from "@/components/Background" ;
export const metadata : Metadata = {
title : "About - Hyperscape" ,
description : "Learn about Hyperscape" ,
};
export default function AboutPage () {
return (
<>
< Background />
< main className = "relative z-10" >
< Header />
{ /* Your content */ }
< Footer />
</ main >
</>
);
}
Add link to Header component
Customizing Theme
Edit CSS variables in src/app/globals.css:
@theme {
--gold-essence: #d4a84b; /* Change primary gold color */
--bg-depth: #0a0a0c ; /* Change background color */
}
Assets
Images
Location: packages/website/public/images/
Image Purpose Dimensions hero-image.pngLanding page hero Variable gold-banner.png$GOLD page hero Variable gold-cta.png$GOLD CTA section Variable cta-banner.pngLanding CTA Variable app_background.pngDefault background Variable gold_background.png$GOLD page background Variable logo.pngHyperscape logo Variable wordmark.pngHyperscape wordmark Variable token.png$GOLD token icon Variable og-image.jpgOpen Graph image 1200×630
Fonts
Location: packages/website/public/fonts/
rubik.woff2 - Body font (self-hosted for performance)
Build Output
Static Export
Output Structure:
out/
├── index.html # Landing page
├── gold/
│ └── index.html # $GOLD token page
├── _next/
│ ├── static/ # CSS, JS bundles
│ └── ...
├── images/ # Static images
└── fonts/ # Font files
Bundle Size
Optimized for performance:
Tailwind CSS purged (only used classes)
Three.js tree-shaken
Code splitting by route
Static generation (no runtime overhead)
Integration with Monorepo
Workspace Configuration
// Root package.json
{
"workspaces" : [
"packages/*"
]
}
The website package is included in the monorepo but independent - it doesn’t depend on other Hyperscape packages.
Turbo Configuration
// turbo.json
{
"tasks" : {
"build" : {
"dependsOn" : [ "^build" ] ,
"outputs" : [ "out/**" , ".next/**" ]
} ,
"dev" : {
"cache" : false ,
"persistent" : true
}
}
}
Troubleshooting
TypeScript Errors
Issue: R3F types conflict with Next.js
Solution: Build errors are ignored in config. If you need strict type checking:
// Use type assertions for R3F components
< mesh position = {[ 0 , 0 , 0 ] as [number , number , number]}>
Image Optimization
Issue: Images not optimized in static export
Solution: Pre-optimize images before adding:
# Using Sharp CLI
npx sharp-cli -i input.png -o output.png --webp
Font Loading
Issue: FOUT (Flash of Unstyled Text)
Solution: Fonts use display: swap for better UX. Consider preloading:
// In layout.tsx
< link rel = "preload" href = "/fonts/rubik.woff2" as = "font" type = "font/woff2" crossOrigin = "anonymous" />
Package Overview All packages in the monorepo
Development Setup Local development workflow
Deployment Production deployment guide