Skip to content

New Desktop App - #21

Open
princebaretto99 wants to merge 1 commit into
mainfrom
desktopAppUpdate
Open

New Desktop App#21
princebaretto99 wants to merge 1 commit into
mainfrom
desktopAppUpdate

Conversation

@princebaretto99

Copy link
Copy Markdown

Summary

Replaces the Electron-based Percy Desktop App with a lightweight, native Node.js desktop app (desktop-app/) — no Electron, no Chromium runtime bundled into the installer. It keeps the same job (start/stop a local Percy server for the Chrome extension) but ships as a proper double-clickable app with a real menu bar icon, and fixes several extension-side bugs surfaced while getting the new app working end-to-end with current @percy/cli.

What's new: desktop-app/

  • Native menu bar UI, not Electron. On macOS the tray icon is a ~100-line Swift helper (native/tray.swift), compiled as a universal arm64+Intel binary and driven by the Node process over stdin/stdout JSON. Windows/Linux use the small systray2 native helper. Menu shows live "Percy server: running/stopped" status, "Stop Percy server", and "Quit".
  • Packaged with @yao-pkg/pkg, not Electron — Node is bundled into the executable, so end users don't need Node/npm installed. npm run build:mac produces a proper .app bundle (LSUIElement, no Dock icon, ad-hoc signed); build:win / build:linux produce standalone executables.
  • Same HTTP contract the extension already expects on localhost:3778:
    • POST /percy/start — starts the local Percy server (spawns the standalone Percy CLI, downloaded once from the official percy/cli GitHub releases into ~/.percy-desktop-app/bin)
    • POST /percy/snapshot — proxies a snapshot upload to the Percy server (see "Why a proxy" below)
    • POST /percy/stop — stops the Percy server
    • GET /healthcheck — app + Percy server status
  • Prefers the user's installed Chrome/Chromium/Edge over downloading Percy's own Chromium, via PERCY_BROWSER_EXECUTABLE — faster startup, no ~150MB browser download, and avoids an Apple Silicon/Rosetta browser-launch timeout Percy's bundled x86_64 Chromium hit in testing.
  • Security hardening on the local HTTP server: validates the Host header (defends against DNS rebinding) and rejects state-changing requests (/percy/start, /percy/snapshot, /percy/stop) from non-extension web origins, since any webpage can otherwise reach localhost.
  • Logs to ~/.percy-desktop-app/app.log (a double-clicked app has no terminal).

See desktop-app/README.md for build/run instructions and full API docs.

Extension-side fixes (utils/percy-utils.ts)

Getting a real end-to-end build working against current @percy/cli surfaced a few bugs, unrelated to Electron vs. Node but blocking either desktop app:

  1. MV3 service worker was dying mid-finalize. Percy.finalise() can legitimately run for 30–60s+ (Percy server startup + snapshot uploads), but a pending fetch doesn't reset Chrome's ~30s service worker idle timer — only extension API calls do. Added a chrome.runtime.getPlatformInfo() keepalive ping for the duration of finalise().
  2. stopPercy() used GET; Percy CLI's /percy/stop only accepts POST. Was silently 404ing and leaving builds stuck in "Receiving".
  3. Percy CLI rejects cross-origin requests to /percy/snapshot and /percy/stop (loopback-origin-only check, added for CSRF hardening in newer CLI versions — the extension's chrome-extension:// origin fails it). Routed both calls through the desktop app's proxy endpoints instead of hitting Percy directly; the desktop app forwards them origin-less, server-to-server.
  4. Removed a stray import { it } from "node:test" accidentally left in the file.

Testing

  • Verified the local HTTP server's origin/host checks (web-origin requests get 403, spoofed Host gets 403, extension-origin requests pass).

Manual pass (capture snapshot → finalize → desktop app starts Percy → snapshots upload → build appears on Percy dashboard with received snapshots → server stops) against the packaged app, per OS:

  • macOS
  • Windows
  • Linux

Not done / follow-ups

  • macOS build is ad-hoc signed; for public distribution this needs a Developer ID signature + notarization.
  • Windows build (@yao-pkg/pkg executable) opens a console window alongside the tray icon — a pkg limitation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant