Skip to content

T-CKC1-tauri-desktop-wrapper

Status: closed/superseded · Impact: medium · Complexity: large

D-0012-monorepo-tooling names a Rust Tauri app as the validating case for the polyglot moon workspace — a TypeScript app and a Rust app side by side, the Rust toolchain running under moon. This task stands up a thin Tauri v2 desktop app under apps/desktop that embeds the same static dashboard SPA bundle D-0013-dashboard-app ships, proving the workspace is genuinely polyglot rather than JS-only.

This is the last/later item in the monorepo+dashboard arc and is a strong candidate for its own later milestone rather than part of the initial monorepo+dashboard push: it needs the Rust toolchain proven, the SPA bundle committed, and a system Rust + Tauri build environment that the earlier tasks don’t require. Treat it as the polyglot capstone — schedule it after the dashboard ships, on its own milestone if convenient.

No desktop app and no apps/ tree exist yet. The dashboard is a web SPA served by the existing Bun/Hono server; its committed static bundle is the input Tauri would embed.

LocationRole today
apps/Does not exist — created (empty) by T-RVMG; no apps/desktop
plugin/lib/services/dashboard/server.tsBun/Hono server: GET /, GET /api/state, POST /api/refresh; the dashboard data layer
plugin/lib/services/dashboard/server.ts#makeAppHono app factory wiring the three routes above
plugin/lib/services/dashboard/dashboard-service.tsLifecycle supervisor behind sdlc dashboard start/stop/list
.moon/toolchains.ymlDeclares the Bun javascript toolchain and a rust toolchain (added by T-RVMG) — no Rust project consumes it yet

The SPA bundle Tauri embeds (apps/dashboard source, built to a static dist, committed into the plugin as web-dist/) is produced by T-CW4K and T-JDEV — those land before this task.

A thin Tauri v2 desktop app at apps/desktop that embeds the committed static dashboard SPA and is the polyglot validating case for the moon workspace.

apps/desktop/
tauri.conf.json Tauri v2 config: frontendDist → committed SPA bundle; product name, window
moon.yml moon project: declares the rust toolchain; `build` task = `tauri build`
src-tauri/
Cargo.toml Rust crate: tauri v2 + tauri-build dependencies
src/
main.rs Tauri entry point; spawns the dashboard server as a sidecar (v1)
  • tauri.conf.json points frontendDist at the committed static dashboard bundle (the web-dist/ artifact from T-JDEV) — Tauri embeds exactly that static dist, no rebuild of the SPA.
  • The Rust crate under src-tauri/ builds with moon’s rust toolchain (T-RVMG), making apps/desktop the second ecosystem in the workspace alongside the TypeScript apps/dashboard.
  • Data layer (v1): sidecar. main.rs spawns the existing Bun/Hono dashboard server as a Tauri sidecar and the embedded SPA talks to it over its relative /api base — exactly as the SPA does in the browser. Zero data-layer rework. The open invoke-vs-sidecar decision is recorded in the Approach.
  1. Scaffold apps/desktop as a Tauri v2 project. Create src-tauri/Cargo.toml (depends on tauri v2 + tauri-build), src-tauri/src/main.rs (Tauri app entry), and tauri.conf.json. Set frontendDist to the committed static dashboard bundle (T-JDEV’s web-dist/) and leave beforeBuildCommand empty — the SPA is already built and committed, so Tauri only embeds it.
  2. Wire the moon project. Add apps/desktop/moon.yml declaring the rust toolchain and a build task that runs tauri build. This is the load-bearing polyglot step: moon now drives a Rust project alongside the TypeScript dashboard, both under one workspace.
  3. Choose the data transport — OPEN DECISION, recommend the sidecar. Two options: (a) Sidecar (recommended for v1): bundle the existing Bun/Hono server as a Tauri sidecar binary, spawn it from main.rs on startup, and let the embedded SPA hit its relative /api base unchanged — zero data-layer rework, since the SPA already speaks HTTP to that server. (b) Tauri invoke: reimplement the GET /api/state / POST /api/refresh data layer as Rust invoke commands and swap the SPA’s transport. Larger, duplicates the data layer in Rust. Recommendation: ship (a) for v1. Implement the sidecar path; capture (b) as a follow-up.
  4. Implement main.rs for the sidecar path. On startup, spawn the dashboard server sidecar (bound to localhost), wait for it to be ready, then load the embedded SPA pointed at its /api base. Tear the sidecar down on window close.
  5. Verify the polyglot build end-to-end. Run tauri build to produce a desktop binary with the SPA embedded; launch it and confirm the desktop dashboard renders the same data as the web SPA; confirm moon builds both apps/dashboard (TypeScript) and apps/desktop (Rust) — the polyglot proof.
LocationKindChange
apps/desktop/tauri.conf.jsonnewTauri v2 config; frontendDist → committed dashboard SPA bundle; product/window settings
apps/desktop/src-tauri/Cargo.tomlnewRust crate manifest: tauri v2 + tauri-build dependencies
apps/desktop/src-tauri/src/main.rsnewTauri entry point; spawns the Bun/Hono dashboard server as a sidecar (v1)
apps/desktop/moon.ymlnewmoon project: declares the rust toolchain; build task runs tauri build
  • AC-1: tauri build (driven via moon run desktop:build) produces a runnable desktop binary with the static dashboard SPA embedded — no separate web server needed to view the UI shell.
  • AC-2: Launching the desktop binary shows the dashboard rendering the same data the web SPA shows (task/milestone/lease/working state via the /api/state source).
  • AC-3: moon builds both apps/dashboard (TypeScript) and apps/desktop (Rust) from the one workspace — proving the workspace is polyglot (n ≥ 2 ecosystems under moon).
  • AC-4: apps/desktop/src-tauri/Cargo.toml and apps/desktop/moon.yml exist and the Rust crate compiles under moon’s rust toolchain (moon run desktop:build exits 0).
  • AC-5: apps/desktop/tauri.conf.json’s frontendDist resolves to the committed SPA bundle (T-JDEV’s web-dist/) — the desktop app embeds the same static bundle the web server serves, with no second copy of the frontend source.
  • Scheduling — this task could be its own later milestone. It is the polyglot capstone, gated on the dashboard shipping and on a system Rust + Tauri build environment; defer it out of the initial monorepo+dashboard milestone if convenient.
  • The Tauri invoke data layer. v1 ships the sidecar; reimplementing the data layer as Rust invoke commands is a deliberate follow-up (see Approach step 3, option b).
  • New dashboard features. The desktop app shows exactly what the web SPA shows — no desktop-only views, no extra data sources beyond what T-UUMK ships for the web.
  • Code signing, notarization, auto-update, and multi-OS release packaging — a hardening concern for a release milestone, not this validating-case task.
  • The Rust toolchain itself — declared by T-RVMG; this task consumes it, it does not add it.
  • T-JDEV (hard, in depends_on:): the committed static SPA bundle (web-dist/) is what Tauri’s frontendDist embeds — without it there is nothing to wrap.
  • T-RVMG (prose): provides the apps/ tree and the moon rust toolchain this Rust project builds under. Not in depends_on: to avoid a redundant edge — T-JDEV already transitively sequences after the workspace exists — but apps/desktop cannot build without the rust toolchain.

T-JDEV


← Back to Tasks