iPad Roadmap

HAProxy UI ships today as a macOS/Linux/Windows desktop app. The next distribution target is iPad, deliberately without a rewrite. The intended use is an iPad-as-ops-console: landscape on a desk, a drag-and-pinch flow graph, the same editing power.

Decision: stay on Tauri 2 + SvelteKit

Flutter was considered and rejected. The rewrite cost is not justified for a secondary surface, and the ops-console use case maps cleanly onto the current stack with touch and responsive work only. No backend rewrite. Estimated 3–4 weeks.

These rules are load-bearing

The constraints below exist to prevent iOS-precluding decisions. They are already how the canvas is built — this is not future work to retrofit, it is the current contract. Read this before designing any feature.

Input

  • Pointer Events only. No mouse* or touch* handlers anywhere. One code path serves finger, trackpad and Pencil.

  • No hover-only affordances. Every state must be reachable by tap. :hover styles are enhancements only.

  • Tap targets ≥ 44×44 pt (iOS HIG). min-h-11 min-w-11 is the floor.

  • Right-click becomes long-press. The contextmenu event is desktop-only; long-press handlers own context menus.

Layout

  • Assume landscape. Primary widths: 1366×1024 (12.9″), 1194×834 (11″), 1024×768 (10.9″). Portrait is honored but not the design target.

  • Sidebars and panels collapse to a drawer below 1024 px, using the bits-ui sheet rather than a custom modal.

  • Safe-area insets on every fixed-position element, via env(safe-area-inset-*).

  • No pixel-fixed widths on root containers. min-w-* / max-w-*, never w-[1366px].

Graph

Every @xyflow/svelte instance uses this configuration, and initial node positions in src/lib/graph/layout.ts are integer multiples of the snap grid:

panOnDrag: [1, 2], // 1 = one finger, 2 = two
zoomOnPinch: true,
zoomOnScroll: false,
panOnScroll: false,
selectionOnDrag: false,
selectionKeyCode: 'Meta',
snapGrid: [16, 16],
minZoom: 0.2,
maxZoom: 2,

Scroll-zoom is off and pinch-zoom is on, which is the opposite of the desktop default and is what makes trackpad and finger behave the same way. Do not deviate without an iPad regression test.

Rust backend

  • No blocking I/O in commands. On iOS the main thread is the UI thread. Use tokio::spawn_blocking or async I/O.

  • No std::process::Command. The iOS sandbox blocks fork/exec. If HAProxy tooling is needed, use a Rust crate or proxy through the Dataplane HTTP API.

  • No keyring call without a #[cfg(target_os)] guard — already partially in place, keep enforcing.

  • No filesystem paths outside app_data_dir(). The iOS sandbox is strict.

Dependencies and web platform

  • No new native npm dependency without a Tauri 2 mobile compatibility check.

  • No Electron APIs. Tauri exposes window.__TAURI__.

  • Everything must work in WKWebView (iOS Safari ~15 baseline). No bleeding-edge CSS, no SharedArrayBuffer without COOP/COEP, no navigator.share without a fallback.

Phases

Phase

Work

Estimate

0

Toolchain — Xcode 15+, Rust, tauri ios init

~1 day

1

iPad build runs — "ios": { "deviceType": "ipad" }, icon set, launch storyboard, safe-area CSS, status bar

~2–3 days

2

Flow graph touch — apply the fixed xyflow config everywhere, 44 pt node targets, long-press menus, pointercancel

~1 week

3

Landscape ops polish — keyboard passthrough, responsive columns at 1366/1194/1024, external display and Stage Manager

~3–4 days

4

Input flexibility — (pointer: fine) for hover and smaller targets, (pointer: coarse) for touch-first, Pencil hover on M2

~2 days

5

Distribution — Ad Hoc .ipa, or itms-services:// OTA for local installs

—

Distribution notes

  • A free Apple ID allows sideloading only, with 7-day certificate renewal. A paid account ($99/yr) enables TestFlight and App Store distribution.

  • The iPad build does not use tauri-plugin-updater — it is reinstalled via the App Store. The desktop updater pipeline does not apply.

When to reconsider Flutter

Only if one of these bites after Phase 2:

  1. xyflow drag latency exceeds 16 ms on M1 or newer

  2. iPad-exclusive features become blockers (Pencil hover, Stage Manager drag-out)

  3. The team adopts Dart as a primary stack for unrelated reasons

  4. iPhone support becomes a requirement


Was this article helpful?