PRD: macOS Desktop Client (Electron, Intel x64 v1)
Status: Draft — publish to GitHub Issues with label ready-for-agent
ADR: docs/adr/0001-electron-desktop-client.md
Glossary: CONTEXT.md
Problem Statement
HTML Anything today requires a developer-style workflow: clone the repository, install dependencies with pnpm, run a local development server, and open a browser. That is acceptable for contributors but blocks non-technical users and anyone who wants a first-class Desktop Client on macOS — especially on Intel MacBook hardware where a native x64 build matters for performance and reliability.
Users who already rely on HTML Anything in the browser at a local server URL get the full product: Coding Agent selection, Skill templates, streaming Editor Sessions, Deliverable preview, export targets, marketplace Skill installation, and deploy configuration. They should not lose any of that when switching to a distributable desktop application. The gap is not missing features in the editor itself — it is missing a packaged runtime that bundles the application server and presents it in a native window without manual setup.
Solution
Ship a Desktop Client for macOS as a new workspace package that:
- Bundles a production Node runtime and a standalone build of the existing Next application.
- Starts that local server on launch, opens it in an Electron window, and tears the server down on quit.
- Injects the user's login-shell environment (especially
PATH) so externally installed Coding Agents remain discoverable — matching Capability Parity with the browser experience.
- Produces an unsigned x64
.dmg for v1 internal distribution; Apple Silicon users may run via Rosetta until a later arm64/universal release.
The existing editor UI and server routes are reused with minimal changes to the Next application (standalone output configuration and packaging hooks only). No second product surface, no fork of generation logic.
User Stories
Discovery & install
- As a macOS user on an Intel MacBook, I want to download a single
.dmg and drag the app to Applications, so that I can use HTML Anything without installing Node or pnpm.
- As a first-time Desktop Client user, I want the app to open to the same entry view as the browser version, so that I recognize the product immediately.
- As a macOS user, I want a Dock icon and standard About / Quit menu items, so that the app feels like a native desktop application.
- As an internal tester receiving an unsigned build, I want clear documentation on how to bypass Gatekeeper once, so that I can run the app without confusion.
Capability Parity — core Editor Session
- As an editor user, I want the top bar to list Coding Agents detected on my machine, so that I can pick the same CLI I use in the browser.
- As an editor user, I want to browse and search all Skill templates, so that I can choose the same Deliverable shapes as in the browser.
- As an editor user, I want to paste or upload Markdown, CSV, JSON, SQL, and plain text, so that format auto-detection works as today.
- As an editor user, I want streaming preview while a Coding Agent generates HTML, so that I see the Deliverable form in real time during an Editor Session.
- As an editor user, I want to interrupt an in-progress generation, so that I am not forced to wait for unwanted output.
- As an editor user, I want sandboxed iframe preview, so that generated HTML cannot poison the host shell.
- As an editor user, I want diff-edit runs when I change content after a prior Deliverable exists, so that token-efficient edits behave as in the browser.
Capability Parity — export & clipboard
- As an editor user, I want one-click export to WeChat-compatible inlined HTML, so that paste into WeChat MP works without reformatting.
- As an editor user, I want PNG export and clipboard image copy, so that I can post to X, Weibo, or Xiaohongshu.
- As an editor user, I want Zhihu-compatible LaTeX placeholder export, so that equations survive platform constraints.
- As an editor user, I want standalone
.html and high-DPI .png downloads, so that I can share Deliverables anywhere.
- As an editor user, I want deck navigation and PDF export in deck Skills, so that presentation mode is unchanged.
Capability Parity — settings & agents
- As a user whose Coding Agent lives outside default PATH, I want the Desktop Client to inherit my login-shell PATH, so that agents in
~/.local/bin, Homebrew, nvm, fnm, etc. are found without manual setup.
- As a power user, I want to override individual agent binary paths in Settings, so that I can fix edge cases the automatic PATH injection misses.
- As an editor user, I want to switch models per agent when the CLI supports it, so that model picker parity is preserved.
- As an editor user, I want task history autosaved in the browser store (IndexedDB), so that reload survival matches the web app.
Capability Parity — marketplace & deploy
- As an editor user, I want to browse and install marketplace Skill packages, so that I can extend the Skill library from the Desktop Client.
- As an editor user, I want to uninstall marketplace packages, so that I can manage installed Skills.
- As an editor user, I want to configure Vercel deploy credentials, so that deploy-from-app flows remain available.
- As an editor user, I want to trigger deploy and copy the resulting URL, so that shipping a static export works as in the browser.
Capability Parity — security
- As a security-conscious user, I want API routes to remain gated on allowed Host headers, so that DNS rebinding cannot drive agent spawn from a malicious page.
- As a local-first user, I want generation to invoke only my installed Coding Agents on my machine, so that no HTML Anything API key is required for core editing.
Desktop Client lifecycle
- As a Desktop Client user, I want the embedded server to start automatically on app launch, so that I never manually pick a port or run a terminal command.
- As a Desktop Client user, I want the server process terminated when I quit the app, so that no orphan Node processes remain.
- As a Desktop Client user, I want the window to load the local server over loopback, so that traffic never leaves my machine for the editor UI.
- As a Desktop Client user quitting with an active Editor Session, I want in-flight agent processes aborted cleanly, so that background CLIs do not keep running.
Build, distribution & updates (v1)
- As a release engineer, I want a repeatable script to produce an x64
.dmg, so that Intel Mac builds are reproducible in CI.
- As a release engineer, I want the build to bundle Node and the standalone Next artifact, so that end users have zero Node prerequisite.
- As an internal user, I want to install a newer
.dmg manually when releases ship, so that I can update without an auto-updater in v1.
- As a contributor, I want a development mode that runs Electron against a local standalone or dev server, so that I can iterate without packaging every change.
Platform & prerequisites
- As an Intel MacBook user, I want native x64 performance without Rosetta overhead, so that streaming preview and export stay responsive.
- As a user on Apple Silicon, I want to run the x64 build via Rosetta until an arm64 build exists, so that I am not blocked in v1.
- As a Coding Agent subscriber, I understand I must install and authenticate my own agent CLIs separately, so that my existing subscriptions continue to work.
- As a user generating Deliverables that fetch CDN assets in preview, I understand network is still required for those assets, so that expectations match Local-First Operation limits.
Contributor & upstream
- As a repository maintainer, I want the Desktop Client isolated in its own workspace package with minimal Next changes, so that upstream merge risk stays low.
- As a repository maintainer, I want a GitHub Discussion opened before merge, so that the long-running-process policy in contributing guidelines is respected.
Accessibility & UX (minimal v1)
- As a macOS user, I want standard window close behavior, so that clicking the red button quits or hides per platform convention (document chosen behavior in release notes).
- As a macOS user, I want keyboard shortcuts such as ⌘+Enter for generation to work in the embedded web view, so that power-user flows match the browser.
Implementation Decisions
Packaging & workspace
- Add a new Desktop Client workspace package alongside the existing Next application and e2e packages. Root workspace metadata and guard scripts must admit the new package without proxying app commands through root
package.json.
- Configure the Next application for standalone production output so a single Node process can serve the built app from packaged resources.
- Bundle a pinned Node 20 runtime for macOS x64 inside the Desktop Client resources; do not require system Node or pnpm for end users.
Process architecture
- Electron main process owns: window creation, server lifecycle, port selection, PATH enrichment, and graceful shutdown (including killing spawned Coding Agent children owned by active Editor Sessions where feasible).
- Renderer loads only
http://127.0.0.1:<dynamic-port> (or localhost); no file:// loading of the Next app.
- Server start sequence: enrich environment → pick free port → spawn bundled Node with standalone entry → health-check HTTP readiness → open BrowserWindow.
- Quit sequence: signal abort to in-flight conversions → stop Next server → exit Electron.
PATH and Coding Agent discovery
- Before spawning the Next server, resolve environment variables from the user's login shell (same effective PATH a terminal session would have on macOS).
- Preserve existing server-side agent scanning heuristics and Settings binary override fields; PATH injection is additive, not a replacement.
- Document known limitations (e.g. agents only installed in non-login interactive shells) in Further Notes.
Capability Parity boundary
- In scope: All user-facing flows available when visiting the local server in a desktop browser today — agents, skills, convert/SSE, preview, export, marketplace, deploy config, host validation middleware behavior.
- Explicitly not bundled: Coding Agent CLIs, their auth sessions, or vendor API credentials.
Native shell (v1 minimal)
- macOS application menu with About and Quit.
- Application icon and bundle identifier.
- No menu-bar tray icon, no custom URL protocol handler, no file-type associations in v1.
Build artifacts
- v1 ships macOS x64 only (
.dmg + .app).
- Unsigned; notarized distribution deferred.
- Application size budget communicated to testers (~200–400 MB acceptable for v1).
Next application changes (minimal)
- Enable standalone output in Next config.
- Ensure static assets, Skill template files, and server routes required at runtime are included in the standalone trace / copy step used by the Desktop Client packager.
- No change to editor UI routes or convert API contracts for v1.
CI
- Add a workflow job (or documented local script) that builds standalone + Electron x64 artifact on
macos-13 or equivalent Intel runner.
- Artifact uploaded as CI output for internal QA; App Store / Sparkle not in v1.
Testing Decisions
What makes a good test
- Assert observable behavior at the highest stable seam: HTTP responses, UI flows, process lifecycle, and agent list contents — not Electron internal module graphs.
- Prefer reusing existing browser-level tests over duplicating them inside Electron harnesses.
- Desktop-specific tests stay thin: only what the browser suite cannot cover.
Primary seam (Capability Parity) — reuse e2e
Seam: The standalone production server (the same artifact bundled inside the Desktop Client) exposes a healthy editor at a loopback URL.
- Run existing Playwright e2e tests (
host-validation, export-menu, deploy-control, etc.) with webServer starting standalone next start (production build) instead of dev mode where applicable.
- This single seam validates that packaging does not break Deliverable export, deploy UI, or API host gating — without launching Electron in CI for every test.
Expectation: This seam should match user expectation that "if e2e passes on standalone, the in-window browser experience in Desktop Client is the same product."
Secondary seam (Desktop Client supervisor)
Seam: Desktop Client process supervisor module — start server, return base URL, stop server.
- Integration tests (Node, no UI): server becomes ready within timeout; loopback
/api/agents returns 200; after stop, port is released; no surviving child Node process.
- PATH smoke test on macOS CI: with a fake binary placed in a login-shell-visible directory,
/api/agents includes it when launched through the supervisor with shell env injection.
Manual acceptance (Intel hardware required)
- Full Editor Session with at least one real Coding Agent (e.g. Claude Code or Cursor Agent) on Intel MacBook x64.
- Marketplace install + uninstall round trip.
- Vercel deploy config save/load (need not deploy to production).
- Quit during active SSE stream → no orphan
claude / cursor-agent processes.
Prior art
- e2e Playwright config already uses
next build + next start on a fixed loopback port — extend this pattern for standalone.
- Next unit tests (Vitest) for host validation middleware — unchanged; still apply when server runs under Desktop Client.
- Agent detection unit coverage in Next package — PATH dirs; supervisor tests complement, do not duplicate.
Out of Scope
- Windows or Linux Desktop Client builds.
- macOS arm64 or universal binaries in v1.
- Apple code signing, notarization, or App Store distribution.
- Automatic updates (
electron-updater) in v1.
- Menu-bar agent, custom URL schemes, "Open With" file associations.
- Bundling Coding Agent CLIs or managing their login flows inside the app.
- Offline marketplace or offline deploy (network required as today).
- Tauri or non-Electron desktop stack.
- Rewriting editor UI in native Swift.
- Changing convert API contracts or Skill registry format.
- Replacing the browser/local-dev workflow for contributors.
Further Notes
- Upstream policy: Contributing guidelines state the project is a normal Next app without a daemon or Electron shell; open a GitHub Discussion before merging to align maintainers.
- Gatekeeper: Unsigned v1 requires right-click Open or
xattr instructions in release docs.
- Rosetta: Apple Silicon users run x64 build until v2; document expected performance delta.
- Port collisions: Dynamic port selection avoids conflict with a developer's existing
3000 server; e2e should continue using a dedicated test port env var.
- Future v2 candidates: arm64/universal builds, signing + notarization, auto-update, deeper native menus (Open File), GitHub Discussion outcome may influence whether Desktop Client lives in main repo or fork.
Publish command
When gh is available:
gh issue create \
--title "PRD: macOS Desktop Client (Electron, Intel x64 v1)" \
--label "ready-for-agent" \
--body-file .scratch/electron-desktop-client/prd.md
If label ready-for-agent does not exist:
gh label create "ready-for-agent" --description "Fully specified, ready for an AFK agent" --color "0E8A16"
PRD: macOS Desktop Client (Electron, Intel x64 v1)
Problem Statement
HTML Anything today requires a developer-style workflow: clone the repository, install dependencies with pnpm, run a local development server, and open a browser. That is acceptable for contributors but blocks non-technical users and anyone who wants a first-class Desktop Client on macOS — especially on Intel MacBook hardware where a native x64 build matters for performance and reliability.
Users who already rely on HTML Anything in the browser at a local server URL get the full product: Coding Agent selection, Skill templates, streaming Editor Sessions, Deliverable preview, export targets, marketplace Skill installation, and deploy configuration. They should not lose any of that when switching to a distributable desktop application. The gap is not missing features in the editor itself — it is missing a packaged runtime that bundles the application server and presents it in a native window without manual setup.
Solution
Ship a Desktop Client for macOS as a new workspace package that:
PATH) so externally installed Coding Agents remain discoverable — matching Capability Parity with the browser experience..dmgfor v1 internal distribution; Apple Silicon users may run via Rosetta until a later arm64/universal release.The existing editor UI and server routes are reused with minimal changes to the Next application (standalone output configuration and packaging hooks only). No second product surface, no fork of generation logic.
User Stories
Discovery & install
.dmgand drag the app to Applications, so that I can use HTML Anything without installing Node or pnpm.Capability Parity — core Editor Session
Capability Parity — export & clipboard
.htmland high-DPI.pngdownloads, so that I can share Deliverables anywhere.Capability Parity — settings & agents
~/.local/bin, Homebrew, nvm, fnm, etc. are found without manual setup.Capability Parity — marketplace & deploy
Capability Parity — security
Desktop Client lifecycle
Build, distribution & updates (v1)
.dmg, so that Intel Mac builds are reproducible in CI..dmgmanually when releases ship, so that I can update without an auto-updater in v1.Platform & prerequisites
Contributor & upstream
Accessibility & UX (minimal v1)
Implementation Decisions
Packaging & workspace
package.json.Process architecture
http://127.0.0.1:<dynamic-port>(orlocalhost); nofile://loading of the Next app.PATH and Coding Agent discovery
Capability Parity boundary
Native shell (v1 minimal)
Build artifacts
.dmg+.app).Next application changes (minimal)
CI
macos-13or equivalent Intel runner.Testing Decisions
What makes a good test
Primary seam (Capability Parity) — reuse e2e
Seam: The standalone production server (the same artifact bundled inside the Desktop Client) exposes a healthy editor at a loopback URL.
host-validation,export-menu,deploy-control, etc.) withwebServerstarting standalonenext start(production build) instead of dev mode where applicable.Expectation: This seam should match user expectation that "if e2e passes on standalone, the in-window browser experience in Desktop Client is the same product."
Secondary seam (Desktop Client supervisor)
Seam: Desktop Client process supervisor module — start server, return base URL, stop server.
/api/agentsreturns 200; after stop, port is released; no surviving child Node process./api/agentsincludes it when launched through the supervisor with shell env injection.Manual acceptance (Intel hardware required)
claude/cursor-agentprocesses.Prior art
next build+next starton a fixed loopback port — extend this pattern for standalone.Out of Scope
electron-updater) in v1.Further Notes
xattrinstructions in release docs.3000server; e2e should continue using a dedicated test port env var.Publish command
When
ghis available:If label
ready-for-agentdoes not exist: