Airspace Simulator is a non-secure browser-based simulator for practicing command and control workflows in a simulated operational airspace. It is intended for learning, experimentation, and software development around airspace visualization, track management, grid references, map interaction patterns, and scenario-building tools.
This project is personal. It is not owned, operated, sponsored, or endorsed by any government entity. The repository is unclassified and should only contain unclassified, non-sensitive, non-operational information.
- Fork the repository on GitHub: danvanbueren/airspace-sim.
- Clone your fork locally:
git clone https://github.com/<your-github-username>/airspace-sim.git
cd airspace-sim/airspace-simThe Next.js application and package.json live in the nested airspace-sim/ directory inside the repository root.
- Install dependencies:
bun install- Start the development server:
bun dev- Open the local app URL printed by Next.js, typically http://localhost:3000.
Before opening a pull request, make sure tests pass and the app still builds:
bun run test
bun run buildTesters can help by running the simulator locally, trying realistic workflows, and reporting confusing behavior, broken controls, visual issues, or crashes.
To run the app locally:
git clone https://github.com/danvanbueren/airspace-sim.git
cd airspace-sim/airspace-sim
bun install
bun devThen open http://localhost:3000. Try creating tracks, editing callsigns and platform types in the Track Management window, dragging the map, switching settings, drawing bearing/range lines, changing keybinds, and refreshing the page to confirm persisted settings still behave as expected.
To test a production-style local deployment:
bun run build
bun startReport issues in GitHub Issues. Helpful reports include:
- What you expected to happen.
- What actually happened.
- Steps to reproduce the issue.
- Browser, operating system, and screen size.
- Screenshots or screen recordings when they clarify the problem.
- Any visible error messages from the app or browser console.
Do not include classified, sensitive, operational, export-controlled, or personally identifying information in issues, screenshots, sample scenarios, or pull requests.
docs/ # Contributor docs (not in-app UI).
+-- architecture/ # Application and simulation architecture deep dives.
+-- plans/ # Implementation plans with shipped-commit checklists.
+-- performance/ # Performance analysis, optimization plan, instrumentation.
airspace-sim/
+-- app/
| +-- components/
| | +-- global/ # Classification bars, commit display, markdown renderer, and global UI pieces.
| | +-- map/ # Map view, context menu, and cursor coordinate overlay.
| | +-- floating/ # Draggable map overlays: action panels, alarm alerts, track windows.
| | | +-- actionPanels/ # Operator button panels on the map.
| | | +-- alerts/ # Alarm alert panel and detail modal.
| | | +-- shared/ # Shared frosted panel chrome and overlay layer.
| | | +-- windows/ # Track management floating windows.
| | +-- panels/ # Settings toolbelt and settings modal pages.
| +-- constants/ # Shared UI constants (for example, z-index layering).
| +-- content/ # Markdown and static copy for in-app settings pages.
| +-- contexts/ # React contexts for map state, theme, app settings, simulation.
| +-- data/ # Static JSON and seed data (airports, routes, startup alerts).
| +-- hooks/
| | +-- global/ # Global interaction guards and measurement hooks.
| | +-- map/ # Map setup, controls, track/sensor/airport layers, bearing/range tools.
| | +-- simulation/ # Simulation tick loop (requestAnimationFrame).
| +-- simulation/ # Track engine, flight world, sensor, initiation, correlation, merge.
| +-- tools/
| | +-- actionPanels/ # Action panel registry, layout math, templates, normalization.
| | +-- browser/ # Browser storage and device support helpers.
| | +-- external/ # External service helpers.
| | +-- formatting/ # Date/time, grid reference, callsign, and track field formatting.
| | +-- map/ # Map style paint helpers (for example, water and label theming).
| | +-- milstd2525/ # Symbol codes, familiar icons, and platform-specific type catalog.
| +-- buildInfo.js # Project metadata, links, version, and copyright text.
| +-- globals.css # Global styles.
| +-- layout.js # Root Next.js layout and providers.
| +-- page.js # Main simulator shell.
+-- public/
| +-- map-styles/ # Local MapLibre style JSON files.
+-- tests/ # Node test runner suites (formatting, simulation, milstd2525).
+-- AGENTS.md # Workspace guidance for AI coding agents.
+-- CLAUDE.md # Pointer to shared agent guidance.
+-- jsconfig.json # JavaScript path alias configuration.
+-- next.config.mjs # Next.js configuration.
+-- bun.lock # Locked dependency versions.
+-- package.json # Project scripts and dependencies.
+-- README.md # Short pointer to the root README.
Paths above are relative to the repository root unless noted. Application paths under airspace-sim/ are relative to that directory.
For contributor documentation (architecture, plans, performance investigations), see docs/.
- Next.js (docs) powers the application framework, development server, routing, build, and production start flow.
- React (docs) provides the component model, hooks, context providers, and client-side UI behavior.
- Material UI (docs) provides the UI component library used for panels, buttons, forms, modals, typography, alerts, and layout.
- Emotion (docs) supports Material UI styling.
- MapLibre GL JS (docs) renders the interactive map and map layers.
- milsymbol (docs) generates full MIL-STD-2525-style tactical symbols when familiar icons or info fields are disabled.
- Custom familiar platform silhouettes (
createFamiliarTrackIcon.js) provide simplified identity-colored icons for common air, surface, and subsurface tracks. - react-markdown with remark-gfm renders the in-app roadmap page from markdown.
- mgrs (package docs) converts coordinates into MGRS.
- Fontsource Roboto (docs) supplies the Roboto font used by Material UI.
- Bun (docs) manages dependencies and local scripts.
The current locked versions are defined in bun.lock; use that file as the source of truth when checking exact dependency versions.
bun devStarts the Next.js development server.
bun run buildCreates a production build.
bun startStarts the production server after a successful build.
bun run testRuns the Node test runner over tests/formatting, tests/simulation, and tests/milstd2525.
bun run generate:flight-worldRegenerates app/data/airports.json and app/data/airRoutes.json from OurAirports open data.
The simulator splits UI (Next.js + MapLibre) from simulation (track engine modules). Simulation state flows from TrackEngine through React context into map hooks; operator actions call back into the engine API.
- Provider stack in
app/layout.js(map state, theme, settings, keybinds, sensor display toggles, simulation context). - Full-screen map workspace with track/sensor/airport layers, context menu, bearing/range tool, and floating Track Management windows.
- Settings persisted in browser cookies; simulation tuning passed to
TrackEngineassimulationSettings.
Deep dive: docs/architecture/application-architecture.md
Four core systems plus merge and an orchestrator:
| System | Role |
|---|---|
| Flight world | Global aircraft on weighted routes; stable IDs across pan/zoom |
| Sensor simulation | Noisy radar/IFF returns inside scan bounds |
| Track initiation | 3-hit plot trails promote uncorrelated returns to firm tracks |
| Correlation | Links returns to existing active tracks before initiation runs |
| Track merge | Collapses duplicate tracks competing for the same return |
| TrackEngine | Fixed tick order, snapshots, sensor history buffers |
Design highlights:
- Rendering is not simulation — Off-screen tracks may be hidden on the map without deleting engine state.
- Two distance knobs — Correlation threshold (default 5 NM) vs plot association threshold (default 3 NM).
- Correlation modes — Active, extrapolated, and suspend (editable in Track Management).
Deep dive: docs/architecture/simulation-architecture.md — tick pipeline, per-sensor scan order, merge rules, symbology, settings reference, and development utilities.
| Topic | Document |
|---|---|
| Bearing/range tool rewrite | docs/plans/bearing-range-tool-rewrite-plan.md |
| Off-viewport track persistence | docs/plans/viewport-track-persistence-plan.md |
| Performance optimization | docs/performance/ |
Near-term and exploratory work includes:
- Reference point editing and management.
- Pre-built training scenarios and recurring tactical picture templates.
- End-to-end control loops for mission practice.
- Automated picture call calculations inspired by ParrotSour workflows.
- Additional fuel, weapons, timeline, and mission-planning concepts represented with unclassified simulated data only.
The in-app Settings → Roadmap page (app/content/settings-roadmap.md) is the live checklist with completed items and commit links.
Airspace Simulator is a spiritual successor to John McCarthy's ParrotSour, with a focus on making command and control practice more approachable in a modern web application. The long-term goal is to provide a training sandbox where aircrew, operators, controllers, students, and hobbyist developers can rehearse airspace management concepts without relying on classified systems or operational data.
The mission is to build a practical, extensible, and transparent simulator that can support:
- Interactive map familiarization and airspace visualization.
- Track creation, labeling, and management workflows.
- Bearing/range measurement and map annotation tools.
- Multiple grid reference formats used in operational discussions.
- Scenario construction for repeatable training events.
- Sensor, radar, IFF, and track automation experiments using simulated data only (see Simulation Architecture).
- Full-screen map workspace with light and dark map styles and theme-aware water/label paint.
- Modular, draggable action panels (Settings → Action Panels) with cookie-backed layout; defaults match the former Category Select and Fixed Function panels.
- Glass panels for alarm alerts and settings, plus operator-configurable action panels on the map.
- Global flight simulation on weighted air routes between curated airports (no viewport-random spawning); can be paused via Enable simulation engine.
- Separated sensor, initiation, and correlation pipeline (see Simulation Architecture).
- Simulated radar and IFF returns with history playback and configurable action-panel sensor toggles.
- Track merge after correlation — collapses duplicate tracks competing for the same sensor return; formation pairs correlating separately are left alone (details).
- Automatic track initiation after three per-sensor plot updates on uncorrelated returns only.
- Manual track initiation and editing from the map context menu, with correlation mode (active / extrapolated / suspend); editing an auto track converts it to manual.
- Reference point creation from the map context menu (Initiate Ref Point) — suspended, drop-protected markers with MIL-STD control-measure symbology, auto-assigned RP## labels, and a simplified Reference Point management window.
- Track Management window with domain, identity, MIL-STD type, searchable platform-specific type, searchable nationality, callsign validation, optional symbol info fields, live attention-flag pills, and scrollable content when the map viewport is too short to show every field.
- On-map track attention flags (amber, monospace, synchronized flash) pinned beside tracks; up to five lines with overflow summary. Emergency IFF codes (
7500,7600,7700) raise both attention flags and alarm alerts. - Automatic drop of uncorrelated tracks after a countdown (invisible DROP-RISK, then visible DROP attention, then removal); drop protect shows a PROT attention flag and recover actions in the context menu.
- Settings page matrix for inhibiting track attentions and alarm alert types; central signal registry in
app/simulation/signalDefinitions.js. - Modular seed alarm alerts on page load (
app/data/seedAlarmAlerts.js); system notices can include a left-side icon and external link action. - Familiar platform silhouettes with MIL-STD-2525 fallback, callsign labels, and speed-scaled heading vectors on the map.
- Optional airport and air route overlay layers.
- Bearing/range measurements with configurable persistence (Settings → Look & Feel) and rebindable persist modifier (Settings → Keybinds).
- Bearing/range line context menus and line removal controls (permanent lines only).
- Group criteria circle toggle (default Caps Lock) that draws a 3 NM radius ring at the cursor, synced to the OS Caps Lock state when bound to Caps Lock.
- Complete Control Reference in Settings → Usage Guide documenting every map control combo (with a link to Keybinds for rebinding).
- Cursor coordinate overlay with selectable grid reference systems.
- Supported coordinate displays include DD, DDM, DMS, GARS, Geohash, GEOREF, Killbox-style GARS, and MGRS.
- Configurable keyboard and mouse controls persisted in browser cookies, including click-to-center on the map.
- In-app settings, keybinds, about, and markdown-backed roadmap pages.
- Node test suites for formatting, simulation, and symbol helpers (
bun run test). - Error forwarding into an in-app alert panel for easier testing feedback.
- Desktop-first experience with keyboard and mouse controls; mobile and tablet devices see an unsupported-platform page instead of the simulator.
Airspace Simulator targets desktop and laptop browsers. Mobile phones and tablets are detected on the server and client and shown a dedicated unsupported-platform page, because touch input and small viewports are not yet supported. A future mobile-first redesign may revisit this policy.
Use simulated data only. Do not commit, upload, paste, screenshot, or describe classified, controlled, sensitive, operational, or real-world mission data. When in doubt, leave it out and use fictional examples.