R2D2-Holocron/holocron-frontend
Joshua Belke a7b67ed106
Some checks failed
Holocron Frontend CI / lint-and-test (push) Has been cancelled
docs(fusion): standalone track-fusion gating demonstration
Self-contained page documenting where track fusion works and where the
prototype silently missed duplicates. Draggable contact pair over a
to-scale cell grid, live per-gate readout, and the coverage-by-latitude
comparison. Opens straight off disk, no build or server needed.
2026-08-04 19:25:49 -04:00
..
.dual-graph chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
.storybook chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
config chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
cypress chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
docs docs(fusion): standalone track-fusion gating demonstration 2026-08-04 19:25:49 -04:00
src feat(fusion): latitude-correct track fusion with deterministic clustering 2026-08-04 18:41:04 -04:00
src-tauri chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
.prettierignore chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
.prettierrc chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
CLAUDE.md chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
cypress.config.ts chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
Dockerfile.dev refactor(compose): unify into single file with local/dev/demo profiles 2026-05-28 09:57:46 -04:00
Dockerfile.local refactor(compose): unify into single file with local/dev/demo profiles 2026-05-28 09:57:46 -04:00
eslint.config.js chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
index.html chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
package-lock.json chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
package.json chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
postcss.config.js chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
QUICKSTART.md chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
README.md chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
server.cjs feat(frontend): add MQTT theater discovery and per-theater views 2026-06-02 02:04:18 -04:00
tailwind.config.js chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
tsconfig.json chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
tsconfig.node.json chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
vite.config.ts chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00
vitest.shims.d.ts chore: rename holochron -> holocron and integrate R2D2 holocron components 2026-05-28 09:31:30 -04:00

NATO Tactical Display - React Version

A real-time tactical display system built with React, Cesium, and MQTT for visualizing military assets on a 3D globe with MIL-STD-2525 symbology.

🚀 Features

  • Real-time Asset Tracking: Live updates via MQTT and WebSocket
  • 3D Visualization: Interactive globe using Cesium with satellite imagery and terrain
  • Military Symbology: MIL-STD-2525 compliant symbols using milsymbol.js
  • Map Layers: Toggle visibility by layer — UAVs, USVs, UUVs, Contacts (and other). Layer toggles control both the map and the Navigation list.
  • Compact View Mode: Icon-only 3D / 2.5D / 2D buttons with tooltips to save space
  • Navigation List: Asset list filtered by layer, sorted by layer then identifier, with layer badges. Click a row to select, fly to, and show details.
  • Asset Selection: Click an asset on the map or in the Navigation list to select it. Selected asset is highlighted on the map and in the list.
  • Asset Detail Panel: When an asset is selected, view SIDC (20-digit and human-readable breakdown: Context, Standard Identity, Symbol Set, Status, HQ/TF/Dummy, Echelon, Entity Type), Call Sign, Lat/Long/Altitude, Heading, Speed, and a Sensors section (placeholder when no sensor data).
  • Range Rings: For the selected asset, optional range circles (e.g. 5 km, 10 km) on the map. Radius can be set via description.range_ring_km or defaults to 5 and 10 km.
  • Multiple View Modes: 3D, 2.5D (Columbus View), and 2D map views
  • Trail Visualization: Path history for each tracked asset
  • Responsive UI: Modern, tactical-themed interface with compact status (connection · asset count · last update)

📋 Prerequisites

  • Node.js (v16 or higher)
  • npm or yarn
  • MQTT broker (e.g., Mosquitto) running on localhost:1883
  • For desktop app (Tauri): Rust toolchain

🛠️ Installation

  1. Install dependencies:
npm install

🏃 Running the Application

The application consists of two parts:

1. Backend Server (Node.js + WebSocket + MQTT)

Start the backend server that bridges MQTT and WebSocket:

npm run server

This will start:

  • HTTP server on port 3001
  • WebSocket server on port 9002
  • MQTT connection to mqtt://localhost:1883

2. Frontend (React + Vite)

In a separate terminal, start the React development server:

npm run dev

This will start the Vite dev server on port 3333.

3. Access the Application

Open your browser and navigate to:

http://localhost:3333

4. Desktop App (Tauri)

The app can run as a native desktop application using Tauri v2:

npm run tauri:dev

This starts the Vite dev server and opens a native window. The backend server must be running separately (npm run server) for full functionality.

To build a production desktop app:

npm run tauri:build

The built app will be in src-tauri/target/release/. To generate app icons for distribution, run:

npm run tauri icon path/to/your-icon.png

📁 Project Structure

nato-tactical-display/
├── src-tauri/                 # Tauri desktop app backend (Rust)
│   ├── src/
│   │   ├── main.rs
│   │   └── lib.rs
│   ├── tauri.conf.json
│   └── Cargo.toml
├── src/
│   ├── components/
│   │   ├── CesiumViewer.tsx       # 3D map component
│   │   ├── ControlPanel.tsx      # Status and asset list
│   │   └── ControlPanel.css      # Panel styling
│   ├── hooks/
│   │   ├── useWebSocket.ts       # WebSocket connection hook
│   │   └── useAssetTracking.ts   # Asset management hook
│   ├── utils/
│   │   ├── militarySymbol.ts    # SIDC generation and breakdown
│   │   └── layers.ts             # Layer keys and asset→layer mapping
│   ├── App.tsx                   # Main application
│   ├── App.css                   # Application styles
│   ├── main.tsx                  # React entry point
│   └── index.css                 # Global styles
├── server.cjs                    # Backend server
├── index.html                     # HTML template
├── vite.config.ts                 # Vite configuration
└── package.json                   # Dependencies

🔧 Configuration

Environment Variables

You can customize the configuration using environment variables:

Backend (server.cjs):

  • PORT: HTTP server port (default: 3001). Use PORT=3002 npm run start:dev when 3001 is in use.
  • WS_PORT: WebSocket server port (default: 9002)
  • MQTT_BROKER: MQTT broker URL (default: mqtt://localhost:1883)
  • MQTT_TOPIC_PREFIX: Topic prefix (default: r2d2/holocron)
  • MQTT_CLIENT_ID: MQTT client ID (optional; auto-generated if not set)
  • MQTT_USERNAME: MQTT broker username (optional)
  • MQTT_PASSWORD: MQTT broker password (optional)
  • MAPTILER_KEY: MapTiler API key (optional)

Dev proxy (Vite forwards /api and /health to the backend):

  • API_PORT or PORT: Backend port the proxy targets (default: 3001). Set both when using a different port: PORT=3002 API_PORT=3002 npm run start:dev.

Frontend:

  • WebSocket URL is loaded from /api/config (no hardcoding in App.tsx)
  • Map tiles: set MAPTILER_KEY in the server environment; the frontend loads it from /api/config (no keys in client code)

MQTT Message Format

The system expects CATL (Common Advanced Tactical Language) format messages:

{
  "identifier": "ASSET-001",
  "description": {
    "name": "Fighter-01",
    "context": "ContextEnum_REALITY",
    "standard_identity": "StandardIdentityEnum_FRIEND",
    "symbol_set": "SymbolSetEnum_AIR",
    "status": "EntityStatusEnum_PRESENT"
  },
  "pose": {
    "position": {
      "latitude_longitude_altitude": {
        "latitude": 46.72,
        "longitude": 8.67,
        "altitude": [{ "value": 5000 }]
      }
    }
  },
  "velocity": {
    "speed_and_rate": {
      "heading": 90
    }
  }
}

🎨 Features Breakdown

Asset Visualization

  • Military Symbols: Automatically generated from CATL standard identity codes
  • Fallback Display: Colored points for assets without symbology data
  • Trail Rendering: 60-second path history with glow effects
  • Label Display: Asset names with dynamic positioning

Control Panel

  • Compact Status: Single row — status dot, connection state, asset count, last update time
  • Layers: Checkboxes for UAVs, USVs, UUVs, Contacts. Off layers are hidden on the map and in the Navigation list.
  • View Mode: Icon buttons (globe, globe-horizon, map) for 3D, 2.5D, 2D with tooltips
  • Navigation: Asset list filtered by layers, sorted by layer then ID; layer badge per row; click to select and fly to asset
  • Asset Details: When an asset is selected, SIDC breakdown, position (Lat/Long/Alt), Heading, Call Sign, optional Speed, and Sensors (or “No sensor data”)
  • Range Rings: Selected asset shows configurable range circles on the map (e.g. 5 km, 10 km)

Asset Types & Colors

  • 🟨 Air Assets: Yellow/Amber
  • 🔵 Surface Assets: Blue/Cyan
  • 🟢 Ground Assets: Green
  • ⚪ Unknown: Gray/White

Identity Indicators

  • 🟦 Friend: Cyan
  • 🟥 Hostile: Red
  • 🟩 Neutral: Green
  • 🟨 Unknown: Yellow

🔨 Build for Production

To create a production build:

npm run build

The built files will be in the dist/ directory.

To preview the production build:

npm run preview

🐛 Troubleshooting

WebSocket Connection Failed

  • Ensure the backend server is running on port 3001
  • Check that WebSocket port 9002 is not blocked by firewall
  • Verify MQTT broker is running and accessible

Assets Not Appearing

  • Check MQTT broker is publishing to assets/status/# topic
  • Verify message format matches CATL specification
  • Check browser console for parsing errors

Cesium Not Loading

  • Ensure you have internet connection for CDN resources
  • Check MapTiler API key is valid
  • Verify no CSP (Content Security Policy) blocks

Performance Issues

  • Limit number of simultaneous assets (< 100 recommended)
  • Reduce trail time in CesiumViewer.tsx
  • Lower map tile resolution

Tauri Desktop App

  • Port 3333 in use: Ensure no other process is using port 3333; Tauri uses strictPort and will fail if the port is taken
  • Rust not found: Install Rust via rustup
  • First build slow: The initial tauri:dev or tauri:build compiles Rust dependencies; subsequent runs are faster

📝 Development

Adding New Features

  1. New Asset Types: Update getAssetType() in militarySymbol.ts
  2. Custom Symbols: Modify generateSIDC() for additional SIDC codes
  3. UI Components: Add to src/components/
  4. Hooks: Add custom hooks to src/hooks/

Code Style

  • Use ES6+ features
  • Follow React hooks best practices
  • Use functional components
  • Implement proper error handling
  • Add PropTypes or TypeScript for type safety

🔐 Security Considerations

  • WebSocket connections are not encrypted by default (use WSS in production)
  • MQTT credentials should be secured with environment variables
  • Implement authentication for production deployments
  • Validate all incoming data
  • Sanitize user inputs

📚 Technologies Used

  • React 18: UI framework
  • Vite: Build tool and dev server
  • Tauri v2: Native desktop app wrapper
  • Cesium: 3D globe and mapping
  • WebSocket: Real-time communication
  • MQTT: Message broker integration
  • milsymbol.js: Military symbol rendering
  • Express: Backend HTTP server

📄 License

This project is for demonstration purposes. Ensure compliance with all applicable regulations when deploying in production environments.

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Test thoroughly
  5. Submit a pull request

💡 Tips

  • Use npm run dev for hot module reloading during development
  • Use npm run tauri:dev for a native desktop window with hot reload
  • Turn layers (UAVs, USVs, UUVs, Contacts) off to focus on specific asset types; list and map stay in sync
  • Click an asset on the map or in the Navigation list to select it and see details and range rings
  • Use the view mode icons (globe / globe-horizon / map) to switch 3D, 2.5D, 2D
  • Assets are automatically cleaned up after 5 minutes of inactivity

📞 Support

For issues or questions:

  1. Check the browser console for errors
  2. Verify MQTT messages are being received
  3. Check network requests in DevTools
  4. Review server logs for connection issues