The CDI softkey was in the PFD root row but had no handler — it never cycled the HSI/CDI source (GPS↔VLOC1↔VLOC2). Wire it to write cdiSrc (HSI_source_select_pilot, now writable), cycling GPS→NAV1→NAV2. Also fix a latent demo bug: the 'needs a live sim socket' guard sat above the setDataref/command handlers, so in DEMO (no sim socket) every dataref write (transponder code, baro, AP bugs, CDI) was silently dropped. Reflect writes locally before that guard so cockpit controls respond without a sim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
X-Plane Glass Cockpit (Web)
Bring X-Plane 12 instruments — a G1000-style PFD, an MFD, and an autopilot panel — to any iPad, tablet or laptop on your network. Pure web, no app install on the tablets. Just open a browser.
X-Plane 12 Node bridge (this repo) your devices
┌──────────┐ ws ┌────────────────────┐ ws/http ┌──────────┐
│ Web API │◀──────▶│ resolves dataref │◀───────────▶│ iPad │
│ :8086 │ REST │ IDs, streams values │ │ laptop │
│ (local) │ │ serves the React UI │ │ phone │
└──────────┘ └────────────────────┘ └──────────┘
binds 0.0.0.0:8080
Why a bridge?
X-Plane's built-in web server (v12.1.1+) only listens on localhost, dataref
IDs change every session, and CORS blocks browsers. The bridge runs on the
same PC as X-Plane, talks to it locally, and re-broadcasts everything to your
LAN — to as many tablets as you like at once.
Requirements
- X-Plane 12.1.1 or newer (the web API ships built-in; nothing to enable).
- Node.js 18+ on the PC running X-Plane (
node --version).
Setup (run these on the X-Plane PC)
cd X-PLANE-MOD
npm install # also installs the web app's deps
npm run build # builds the React UI into web/dist
npm start # starts the bridge on http://0.0.0.0:8080
Open it
- Make sure X-Plane is running and you're in a flight.
- On a tablet/laptop on the same Wi-Fi, open:
http://<PC-LAN-IP>:8080- Find the IP: macOS
ipconfig getifaddr en0· Windowsipconfig(IPv4).
- Find the IP: macOS
- The status pill top-right shows X-PLANE (green) when data is flowing, NO SIM if the bridge is up but X-Plane isn't reachable, OFFLINE if the tablet can't reach the bridge.
- Tip: on iPad, "Add to Home Screen" → it opens full-screen like a real app.
Development (hot reload)
npm run dev:bridge # terminal 1 — the bridge on :8080
npm run dev:web # terminal 2 — Vite dev server with HMR (proxies to bridge)
Open the URL Vite prints. Edits to web/src/** reload instantly.
Configuration
All env vars are optional (defaults shown):
| Var | Default | Meaning |
|---|---|---|
BRIDGE_PORT |
8080 |
Port the UI/LAN server listens on |
XPLANE_HOST |
localhost |
Where X-Plane's web API is |
XPLANE_PORT |
8086 |
X-Plane web API port |
Adding instruments / datarefs
Everything is driven by server/config.js:
DATAREFS— values streamed to the UI (alias →sim/...name).WRITABLE_DATAREFS— values the UI may set (knobs/bugs).COMMANDS— buttons the UI may press (mode toggles).
Add a sim/... name there, then read values.<alias> in any component. For
G1000-specific gauges, add that aircraft's laminar/... or
sim/cockpit2/... datarefs the same way.
Notes & limits
- Update rate is X-Plane's (~10–20 Hz) — fine for instruments, this isn't a scenery stream.
- The autopilot buttons fire X-Plane's own commands, so the sim stays the
source of truth. Mode-highlight bits (
AP_BITSinAutopilotPanel.jsx) are best-effort and can differ per aircraft. - LAN only by design. Don't expose port 8080 to the public internet.