A Ground Control Station — GCS — is the software an operator uses to fly, observe, and command unmanned vehicles from a computer. Think of it as air-traffic-control + cockpit + mission-planner + flight-recorder, all on one screen, for vehicles that don't carry humans.
If you've seen drone footage on the news and wondered "sino nagpapalipad niyan?" — they're probably looking at a GCS.
Because the existing options all have the same problems. Some are open source but carry licenses that make them risky for commercial or defense use. Some are closed and locked to one vendor's hardware. Some are cloud-coupled when you need something that works offline. And almost none of them are built to handle more than one type of vehicle.
Domain-driven design with a hexagonal architecture. The core is pure types — no frameworks, no UI, no network calls. Just the concepts the system reasons about: vehicles, positions, commands, missions, safety rules. All tested. All typed. All portable.
Then ports — abstract interfaces that define how the core talks to the outside world. Want to connect a new drone? Write an adapter. The core doesn't change. Parang outlet lang — same plug, different devices.
The documentation chain goes from concept of operations all the way through to architecture — everything cross-linked and traceable. I don't write code without a paper trail. Every line traces back to a requirement, and every requirement traces back to a scenario. Old habit from defense work. It works.
Foundation is green. The domain types are done and tested — every safety-critical function covered. Port interfaces are defined. Documentation chain is complete. License machinery is in CI.
Next up: the first real hardware adapter, then the desktop application. Building the system from the inside out — domain first, then interfaces, then hardware, then UI. Matagal pero matibay.
The operator console
Here's what the multi-domain operator console looks like. Two assets on the map, live telemetry, full command controls.
Operator console — asset roster, live map, telemetry panel, command controls
Multi-asset view — HAWK-3 active in flight, HAWK-7 offline and disavowed
Full command palette: tilt, photo, record, directional movement, rotation, ascend/descend, hold, return-to-launch, land, and emergency. Pipeline, RBAC, safety, ROE, authorization, and recorder tabs across the top. This isn't a toy — it's an operator workstation.
Architecture: hexagonal, five layers
The system is organized in five layers. Inner layers have zero dependencies on outer layers. The domain doesn't know Electron exists. The ports don't know which database you're using. Everything flows inward.
Layer 1 — Domain (the rules). Pure TypeScript. No I/O, no frameworks, no runtime dependencies. Assets, capabilities, missions, waypoints, commands, authorization tokens, mode-state machine, specification pattern for composable rules, Result<T, E> for failure-as-data. Every safety-critical function tested.
Layer 2 — Ports (the seams). Interfaces only. VehicleAdapter, EffectorAdapter, Recorder, Clock, Logger. Every external concern goes through one of these. Swap implementations without touching the core.
Layer 3 — UI. Component library built on design tokens. Multiple theme palettes (Carbon, Matrix, Woodland, Dossier). Brand-configurable for white-labeling.
Layer 4 — Adapters. Concrete implementations of ports. MAVLink for PX4/ArduPilot. Tello SDK for DJI Tello. Future: STANAG 4586 for military interop. Each adapter is a separate package — add one, the rest don't change.
Layer 5 — Apps. Electron desktop operator console + Node.js services (telemetry bus, recorder, plugin host). Zero-trust IPC, signed bundles, CSP that denies egress.
The type-level engagement gate
This is the part that makes defense engineers sit up. The compiler — not runtime code, the COMPILER — refuses to construct an engage_effector command without an AuthorizationToken. You literally cannot build the data structure that represents "fire" without proving authorization exists. It's a compile-time safety gate.
Two-person consent, legal authority chain, all enforced at the type level. If the token isn't there, the code doesn't compile. Not "it throws an error at runtime." Not "it logs a warning." It. Does. Not. Compile.
Why this matters: Most GCS software checks authorization at runtime — an if-statement that can be bypassed, forgotten, or broken by a refactor. This one makes unauthorized engagement a type error. The compiler is the safety officer.
Multi-domain on day one
The type model includes: air | ground | surface | subsurface | space. The same UI, mission planner, and recorder serve every unmanned platform. Adding a ground vehicle is one new adapter package — no domain changes, no port changes, no UI changes, no app changes.
Other GCS software typically commits to one domain — air for most open-source options, multi for the expensive closed ones. Our type model commits multi-domain on day one. Adapters land when the hardware is on hand.
Security posture — zero-trust by construction
Every layer assumed potentially compromised: workstation, network, asset link, operator session, even our own bundled code.
Electron with contextIsolation and sandbox. CSP that denies egress. Bundle integrity verified at startup. Adapter communication over authenticated channels only. Recorder is append-only — you can't delete flight records. Authorization flows through typed tokens, not runtime flags.
License and IP discipline
Apache-2.0 with patent grant — matters for defense customers. Dependency allowlist enforced in CI (MIT, BSD, Apache, ISC, 0BSD, Zlib, CC0, PostgreSQL only). Everything else blocked at the pipeline. GPL, AGPL, BSL, SSPL — all forbidden. Every AI model gets a model card. Every contributor's IP is tracked.
Some things are parked specifically because of licensing: DJI SDK, certain AI models, Mapbox v2+, video codecs. If the license isn't clean, it doesn't go in. Period.
Competitive landscape
The market breaks into three buckets:
Open source but GPL: Great software, but the license means defense customers can't redistribute without source disclosure. That's a dealbreaker for most programs.
Closed and vendor-locked: Powerful, but tied to one vendor's hardware and often cloud-coupled. Air-gapped deployment? Good luck.
Enterprise but air-only: Closest to what we're building, but single-domain and not full-stack.
Our position: Apache-2.0 (redistributable), multi-domain (not just drones), air-gapped capable (no cloud dependency), with the audit and supply-chain hygiene that defense legal reviews actually look at first.
Stack
Electron + React + TypeScript + Zustand + XState for the operator console. Node.js services for telemetry, recording, and plugins. Python, C++, and Rust sidecars for protocol-heavy work. MapLibre for 2D maps, CesiumJS for 3D (deferred). PostgreSQL + PostGIS for storage.
What's built today
Green build. All tests passing. Lint clean. All licenses on allowlist.
Layer 1 (domain) — complete with full test coverage on safety-critical functions. Layer 2 (ports) — all interfaces defined. Layer 3 — design tokens and theme palettes. License and IP machinery — in CI. Documentation chain — overview through architecture, all cross-linked.
What's next
In order: UI component library, SIL flight simulator (software-in-the-loop), Electron desktop app, first real hardware adapter (Tello), then MAVLink adapter for PX4/ArduPilot vehicles, then the recorder implementation.
Building from the inside out. Domain first. Hardware last. Matagal pero matibay.