Desktop app - lightweight wrapper around Dataface Cloud web UI
Problem
Dataface Cloud is a web app. For analysts, a desktop app provides a better daily-driver experience:
- Always running. A menu bar / system tray icon that's always there. Click to open. No "which browser tab was it" friction.
- Deep links.
dataface://org/project/dashboard/revenueopens directly. Shareable links from Slack/email open in the app, not a random browser tab. - Notifications. Native OS notifications for scheduled dashboard refreshes, alerts, or AI agent completion.
- Local data sources. Connect to DuckDB, SQLite, or local Postgres without exposing them to the internet. The desktop app can run
dftnatively and connect to local databases that a cloud-hosted web app can't reach. - Offline capability. View cached dashboards and profiling data when not connected. Edit YAML locally, sync when back online.
dft agentintegration. The terminal agent TUI could be embedded as a panel alongside the web UI. Native terminal emulation in the app.
The web UI is the real product — the desktop app is a thin shell that adds native OS affordances on top. Avoid building a separate desktop UI — keep it as close to "browser wrapper + native hooks" as possible.
Context
What the desktop app wraps:
- Dataface Cloud web UI (apps/cloud/) — Django server-side rendered, htmx, Vega-Lite charts
- Chat interface (M1) — conversational AI with inline dashboard previews
- Dashboard editor — YAML editing with live preview
- Inspector — table profiling and schema browsing
Existing local tooling:
- dft serve — local HTTP server for dashboards (localhost:9876)
- dft mcp serve — MCP server with embedded HTTP server (localhost:8765)
- dft agent (planned) — terminal AI agent
- dft inspect — local table profiling
The desktop app could run the local server internally, giving users a "Dataface on your laptop" experience that connects to local databases and optionally syncs with Dataface Cloud.
Possible Solutions
Option A: Tauri (Rust + System WebView) [Selected]
Wraps the web UI using the OS's native WebView (WebKit on macOS, WebView2 on Windows). Rust backend for native integrations.
| Metric | Value |
|---|---|
| Bundle size | 3–10 MB |
| Memory (idle) | 30–50 MB |
| Language | Rust (backend) + existing web frontend |
| Cross-platform | macOS, Windows, Linux |
| Stars | 85k+ |
Pros:
- Tiny bundle — ships like a native app, not a 200MB Electron blob
- Strong security model (capability-based permissions)
- Rust backend can spawn dft serve and dft agent as child processes
- Can call Python (our existing codebase) via CLI or sidecar
- Modern, fast-growing ecosystem
Cons: - WebView rendering can vary slightly across OSes (edge case, usually fine for dashboard-style apps) - Younger ecosystem than Electron
Note on Rust: Rust is already in the stack via vl-convert-python (Vega-Lite chart rendering — a PyO3 Rust binary). Tauri's Rust is similarly contained — it's the desktop shell (~200 lines of Rust for sidecar management, tray icon, deep links), not core application logic. No concern about introducing a new language.
Option B: Electron (Chromium + Node.js)
Bundles full Chromium. The battle-tested option — VS Code, Slack, Discord use it.
Pros:
- Identical rendering everywhere (bundled Chromium)
- Massive ecosystem, easy to find help
- Node.js backend can shell out to dft easily
Cons: - 80–200 MB bundle size - 150–300 MB memory at idle - Shipping a full browser feels heavy for what is essentially a wrapper - Overkill for our use case
Option C: Neutralino.js (Lightweight Alternative)
Even lighter than Tauri — uses system WebView + a small C++ runtime.
Pros: ~2 MB bundle. Very simple.
Cons: Smaller ecosystem, fewer native APIs, less mature.
Option D: Progressive Web App (PWA)
No desktop app — just make the web app installable via browser PWA support.
Pros: Zero additional code. Works today.
Cons: No system tray, limited notifications, no local database access, no deep links, no native file system access. Doesn't solve the core problems.
Plan
Tauri wrapper around Dataface Cloud, with local dft sidecar for local data sources.
Architecture
┌─────────────────────────────────────────────┐
│ Tauri Desktop App │
│ ┌─────────────────────────────────────┐ │
│ │ WebView (system native) │ │
│ │ └── Dataface Cloud web UI │ │
│ │ (loaded from localhost or cloud)│ │
│ ├─────────────────────────────────────┤ │
│ │ Rust Backend (thin) │ │
│ │ ├── Sidecar: dft serve (local) │ │
│ │ ├── Sidecar: dft agent (terminal) │ │
│ │ ├── System tray / menu bar │ │
│ │ ├── Deep link handler │ │
│ │ ├── Notifications │ │
│ │ └── Auto-updater │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
Two modes:
1. Cloud mode — WebView loads app.dataface.com. The desktop shell adds native affordances (tray, deep links, notifications). No local server needed.
2. Local mode — Tauri spawns dft serve as a sidecar process. WebView loads localhost:9876. Local databases accessible. Offline-capable.
Implementation Steps (Sketch — Scope at M3)
- Scaffold Tauri app —
cargo create-tauri-app, configure for Python sidecar - WebView shell — load Cloud URL or local
dft serve - System tray — icon, quick-open, recent dashboards
- Deep link handler — register
dataface://protocol, route to correct view - Sidecar management — spawn/stop
dft serveanddft agentas child processes - Auto-updater — Tauri's built-in updater for distributing new versions
- Native notifications — dashboard refresh complete, agent finished, alerts
- Build & distribute — macOS
.dmg, Windows.msi, Linux.AppImage
Dependencies (Must Be Mature Before M3)
- Cloud web UI chat interface (M1)
- Embeddable dashboards in chat (M1)
dft agentterminal TUI (M1–M2)- Cloud dashboard editor (M2)
- Authentication / org management (M2)
Implementation Progress
Not yet started. M3 target — dependencies in M1–M2 must land first.
QA Exploration
- [ ] QA exploration completed (or N/A for non-UI tasks)
Review Feedback
- [ ] Review cleared