Skip to content

feat(aspire): first-party deno desktop app support in the generator (native window as a dev-stack resource) #375

Description

@rickylabs

Formal "lift to NetScript" request from the eis-chat POC (rickylabs/eis-chat #118). eis-chat runs a deno desktop (Deno 2.9.0) native window as an Aspire executable resource via a HAND-EDITED register-apps.mts block. It now renders fully — but only after we discovered several non-obvious requirements. NetScript should make this a first-class generator primitive (mirrors the AddTauriApp shape in the private netscript-start .NET AppHost: a task-backed app with service-discovery injection and NO HTTP endpoint).

Proposal

A first-class deno desktop app type in the Aspire generator — e.g. Apps.<name>.Type: "desktop" (or auto-detect a desktop:* TaskName) — that registers the window as a task-backed addExecutable with:

  1. Build-ordering baked in. deno desktop framework-detects Fresh via the built _fresh/ output; if it's absent it falls back to Vite/dist/ and errors. So the launch task MUST build first: deno task build && deno desktop …. The generator should emit/gate this (a predev-style task or a build step / waitFor), not leave it to a hand-edit.
  2. CEF backend selection. See findings — the default WebView2 backend is broken on Windows; CEF must be selected via the --backend cef CLI flag. The generator's desktop tasks should carry it (or expose a backend option).
  3. Service-discovery injection, NO HTTP endpoint. Same services__<name>__http__0 env wiring as a normal app so the window reaches its backends over 127.0.0.1, but no withHttpEndpoint — the window binds its own internal Deno.serve port.
  4. Opt-in gating (Enabled) so headless/CI aspire start is unaffected, and the desktop coexists with the web dashboard app (the desktop uses its own random internal port — no port collision with the dashboard's :8010).

Findings from the eis-chat POC (Windows bare metal, Deno 2.9.0, laufey webview 0.4.0)

These are the load-bearing, non-obvious facts a first-party integration should encode or document:

  • Default WebView2 backend is broken here. Failed to create WebView2 environment — reproduces standalone (deno task desktop:dev) AND under Aspire (detached or not). It aborts BEFORE touching any user-data folder, so the classic workarounds are all no-ops (verified each): WEBVIEW2_USER_DATA_FOLDER, WEBVIEW2_BROWSER_EXECUTABLE_FOLDER, WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--no-sandbox. The WebView2 Runtime is installed + healthy (v149.0.4022.98). The window frame opens but the surface stays blank.
  • CEF is the working backenddeno desktop --backend cef … renders the real UI cleanly, including fully detached (no interactive aspire run needed). (Underlying WebView2 breakage is a Deno/deno desktop bug — worth NetScript tracking/reporting upstream, but the practical answer is CEF.)
  • deno.json desktop.backend field is IGNORED by this Deno build. Setting desktop.backend: "cef" alone STILL launched WebView2 and failed — only the --backend cef CLI flag actually selects CEF. (Likely a Deno bug; a first-party integration must use the flag, not the config field, until fixed.)
  • The internal Fresh server auto-binds a random 127.0.0.1 port via DENO_SERVE_ADDRESS; PORT only affects the startup log banner, never the webview's real port. So there is no port-collision risk with a co-running web dashboard on :8010.
  • CEF's first launch downloads ~150 MB (cached thereafter, ~379 MB under …/deno/laufey/0.4.0/cef).

Reference

  • Working eis-chat hand-edit (the prototype for this primitive): merged in rickylabs/eis-chat fix(cli): make prod CLI plugin path usable + prod-local e2e suite (alpha.5) #136aspire/.helpers/register-apps.mts desktop block (['task','desktop:predev']), apps/dashboard/deno.json (--backend cef, desktop:predev), render evidence in resources/desktop-evidence/. Original proposal: aspire/PROPOSED-desktop-resource.md (docs(root-readme): meta-framework landing README (PR3) #118).
  • Pattern to generalize: the private netscript-start .NET AppHost AddTauriApp — a task-backed app with .WithConfiguredHttpReferences(...) but no bound HTTP endpoint. deno desktop is the same shape.
  • Docs mirror consulted: Deno deno desktop reference (backends, distribution, hmr, devtools).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions