Modern ground control station using Tauri + Svelte + Rust.
mavkit — async MAVLink SDK)wasm-pack and the wasm32-unknown-unknown target for default Vite/web buildsnix develop) for a preconfigured shellInstall dependencies:
pnpm install
Common commands:
pnpm run dev:desktop
pnpm run check
pnpm run test
pnpm run build:frontend
pnpm run dev:web
SvelteKit's Vite commands default to the pure web platform: pnpm exec vite serves the browser/WASM frontend, and pnpm exec vite build writes dist/web. Use pnpm run dev:web when you also want SITL and the WebSocket bridge managed for you.
Dev commands start ArduPilot SITL automatically for live vehicle workflows. For a no-SITL walkthrough, select the built-in Demo vehicle transport in the normal web or desktop app.
pnpm run dev:desktop is the local desktop SITL workflow. It picks a free instance, starts ArduPilot SITL in Docker, launches Tauri dev, and tears the SITL container down automatically when the app exits or you press Ctrl+C.
pnpm run dev:desktop
In the desktop app, TCP mode is preselected for this workflow and the matching 127.0.0.1:<port> address is prefilled. If another stack is already using the baseline port, the script prints the chosen TCP address before the app opens. pnpm run dev:web starts SITL plus a WebSocket bridge and preselects the bridge URL. pnpm run dev:android starts SITL and preselects an emulator-friendly TCP address; set IRONWING_ANDROID_SITL_HOST for physical devices or custom networking.
After connecting to a vehicle, the sidebar shows vehicle status and flight controls.
0.0.0.0:14550)127.0.0.1:5760)Arming may take a few seconds after a fresh SITL start while the EKF converges.
Use the mode dropdown in the left panel to switch modes (STABILIZE, GUIDED, LOITER, RTL, LAND, etc.). The dropdown auto-populates based on vehicle type after the first heartbeat.
Quick-action buttons for RTL, Land, and Loiter are available below the dropdown.
Takeoff automatically sets GUIDED mode, arms the vehicle, and sends the NAV_TAKEOFF command. You do not need to arm or set mode manually beforehand.
On the Flight Data tab, right-click anywhere on the map to send the vehicle to that location. The vehicle must be armed and in GUIDED mode. The goto command uses the vehicle's current altitude.
Connect → Takeoff (10m) → right-click map to fly around → Land or RTL
Requires Android SDK + NDK. Run on a connected device or emulator. The dev command starts SITL automatically:
pnpm run dev:android # Dev build on device/emulator
pnpm run build:android # Build APK
Android supports UDP, BLE, and Classic SPP transports. Serial is excluded (doesn't compile for Android targets).
Browser-based E2E tests now run against the production frontend bundle with the @platform/* boundary resolved to a mocked browser implementation. This is a browser-only UI workflow: it validates user-visible behavior, not real Tauri, Rust, or SITL integration.
IRONWING_PLATFORM=mock, which swaps the native @platform/* imports for browser-safe mock implementations.window.__IRONWING_MOCK_PLATFORM__ controller exposed by src/platform/mock/backend.ts.# One-shot: build the frontend bundle, start a local preview, run Playwright
pnpm run e2e:browser
Other useful commands:
pnpm run e2e:browser:headed # Run tests with a visible browser window
pnpm run e2e # Run all browser and native E2E lanes sequentially
pnpm run e2e:browser uses Playwright's built-in webServer support to build the frontend, start a preview server, run the browser suite, and clean up afterward.
Four spec files in e2e/:
connect_link failure and verifies the app surfaces the validation error cleanly.Each Playwright invocation still runs serially (workers: 1). Traces, screenshots, and video are captured on failure.
pnpm run dev:desktop remains the real SITL workflow: it starts ArduPilot SITL and launches the native Tauri app with the matching TCP address prefilled.pnpm run e2e:native is the thin real-stack desktop lane: it builds a debug Tauri app, starts SITL, launches the native app through tauri-driver, and runs one WebDriverIO smoke test against the real Rust + frontend stack.
tauri-driver on PATH (cargo install tauri-driver --locked) or IRONWING_TAURI_DRIVER_PATH=/path/to/tauri-driverWebKitWebDriver on Linuxpnpm run e2e:native
Keep this lane intentionally small. Broad UI coverage still belongs in the browser-only Playwright suite above.
Frontend bundles are separated by target under dist/:
| Command | Output |
|---|---|
pnpm exec vite build |
dist/web |
pnpm run build:frontend |
dist/web |
pnpm run build:desktop |
dist/tauri |
pnpm run build:android |
dist/tauri |
pnpm run build:web |
dist/web |
pnpm run e2e:browser |
dist/e2e |
Set IRONWING_OUT_DIR to override a specific build artifact directory.
.github/workflows/ci.yml: frontend checks/build/tests + Rust check/tests on every push and PR