A web-based training simulation for satellite ground station operations, built with TypeScript and vanilla JavaScript.
SignalRange simulates a commercial satellite ground station environment where operators learn to configure and troubleshoot RF equipment chains. The training scenarios are set at North Atlantic Teleport Services (NATS), a fictional satellite ground station facility in Vermont serving the TIDEMARK constellation.
Difficulty: Beginner | Duration: 25-35 min
Your first day at NATS. Charlie Brooks walks you through a routine health check on TIDEMARK-1, already online at 53ยฐW. Learn what each equipment panel shows, what the indicators mean, and what "normal" looks like.
Difficulty: Beginner | Duration: 20-25 min
Take TIDEMARK-1 offline for antenna feed maintenance, then restore service. Learn the proper power-down sequence (HPA โ BUC โ LNB โ Antenna) and why RF safety protocols matter.
Difficulty: Beginner | Duration: 25-30 min
Coming soon
Difficulty: Intermediate | Duration: 30-35 min
TIDEMARK-2 has reached GEO at 45ยฐW. Given only the beacon frequency (3,947.8 MHz), calculate the LNB local oscillator frequency, configure the spectrum analyzer, and acquire the beacon independently.
- 9m C-band Antenna - Pointing, tracking modes, polarization control
- LNB - Local oscillator, gain, thermal stabilization
- BUC - Block upconverter with mute control
- HPA - High power amplifier with safety interlocks
- IF Filter Bank - Bandwidth selection
- GPSDO - GPS-disciplined oscillator for frequency reference
- Spectrum Analyzer - Real-time RF visualization
- Receiver/Transmitter Modems - Signal demodulation and generation
- Node.js 18.x or 20.x (LTS recommended)
- npm 9.x or later
# 1. Clone the repository
git clone https://github.com/thkruz/SignalRange.git
cd SignalRange
# 2. Install dependencies
npm install
# 3. Set up environment variables
cp .env.example .env
# 4. Pull campaign assets from R2 (audio/images)
npm run r2:pull
# 5. Start the development server
npm run devThe app will be available at http://localhost:3000 (or the port shown in terminal).
Copy .env.example to .env and configure:
| Variable | Required | Description |
|---|---|---|
PUBLIC_SUPABASE_URL |
For auth features | Your Supabase project URL |
PUBLIC_SUPABASE_ANON_KEY |
For auth features | Supabase anonymous/public key |
PUBLIC_USER_API_URL |
No | User API endpoint (has default) |
PUBLIC_ASSETS_BASE_URL |
No | Leave empty for local dev |
For local development without authentication features, the default .env.example values work out of the box.
Campaign assets (audio files, character images) are stored in Cloudflare R2 and not committed to the repository.
# Download assets from R2 (no authentication required)
npm run r2:pull
# Preview what would be downloaded
npm run r2:pull:dryAssets are downloaded to public/assets/campaigns/ and public/assets/characters/.
| Command | Description |
|---|---|
npm run dev |
Start webpack dev server with hot reload |
npm run build |
Production build to dist/ |
npm run preview |
Preview production build with Wrangler |
npm run r2:pull |
Download campaign assets from R2 |
npm run test |
Run Jest test suite |
npm run type-check |
TypeScript type checking |
npm run lint |
Run ESLint |
Assets not loading?
Run npm run r2:pull to download campaign audio and images.
TypeScript errors?
Run npm run type-check to see detailed type errors.
Port already in use?
The dev server defaults to port 3000. Check for other processes or modify webpack.config.js.
SignalRange is deployed on Cloudflare Workers with static assets. There are two environments:
| Environment | URL | Purpose |
|---|---|---|
| Production | https://app.signalrange.space | Live user-facing application |
| UAT | https://uat.signalrange.space | Pre-production testing and validation |
# Deploy to UAT (test changes first)
npx wrangler deploy --env uat
# Deploy to Production (after UAT validation)
npx wrangler deploy --env productionAlways deploy to UAT first to validate changes before promoting to production.
AGPLv3 - See LICENSE.md