Skip to content

feat: Add Electron wrapper for desktop app - #1964

Merged
Calcium-Ion merged 18 commits into
QuantumNous:mainfrom
bubblepipe:electron
Oct 5, 2025
Merged

feat: Add Electron wrapper for desktop app#1964
Calcium-Ion merged 18 commits into
QuantumNous:mainfrom
bubblepipe:electron

Conversation

@bubblepipe

@bubblepipe bubblepipe commented Oct 3, 2025

Copy link
Copy Markdown
Contributor

Add Electron wrapper for desktop app

Summary by CodeRabbit

  • New Features

    • Desktop app: tray controls, minimize‑to‑tray, automatic local server startup with health checks, user‑facing error dialogs and log export, secure preload exposing platform/version/data directory, and Electron-aware database warning showing local data path.
  • Documentation

    • Added Electron README with setup, development, and production build instructions.
  • Chores

    • CI workflow and packaging for Windows desktop releases, scripted multi‑step builds, icon generation, entitlements, and updated ignore rules; build artifacts now include versioned binary names and automated GitHub release creation.

@coderabbitai

coderabbitai Bot commented Oct 3, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

Adds an Electron desktop app (main, preload, packaging, icons, entitlements, build scripts, README), a Windows-focused GitHub Actions workflow for building and releasing the Electron app, updates CI backend release workflows to embed versioned binary names, .gitignore updates, and a web UI change to show Electron-aware database messaging.

Changes

Cohort / File(s) Summary
CI: Electron build workflow
.github/workflows/electron-build.yml
New GitHub Actions workflow to build a Windows Electron app (trigger on tags/manual). Sets up Bun/Node/Go, builds web frontend, builds versioned Go backend, updates Electron version from tag, installs deps, builds Windows package, uploads artifacts, and creates a GitHub Release.
CI: Versioned backend releases
.github/workflows/linux-release.yml, .github/workflows/macos-release.yml, .github/workflows/windows-release.yml
Backend builds now compute VERSION via git describe --tags, embed it with -ldflags into the Go binary, output binaries named with version suffixes (e.g., new-api-<VERSION>), and release steps reference versioned artifacts (wildcards).
Repo hygiene
.gitignore
Added new-api, electron/node_modules, electron/dist, electron/package-lock.json ignores; minor .eslintcache newline change.
Electron: Core runtime & packaging
electron/main.js, electron/preload.js, electron/package.json
New Electron main process to spawn/monitor local Go server (health probe, rolling logs, error analysis, dialogs), manage BrowserWindow and tray lifecycle, graceful shutdown; preload exposes window.electron including dataDir; package.json contains electron-builder config and platform build scripts.
Electron: Build tooling & assets
electron/build.sh, electron/create-tray-icon.js, electron/entitlements.mac.plist
Cross-platform build.sh to build web/Go/Electron; tray icon generator using canvas with fallback minimal PNG; macOS entitlements plist added.
Electron: Docs
electron/README.md
New README describing prerequisites, dev workflow, how to use or build the Go binary, platform-specific production build commands and artifact locations, and default ports/data paths.
Web UI: Electron-aware messaging
web/src/components/setup/components/steps/DatabaseStep.jsx
Detects Electron environment and shows an Electron-specific local data storage/info banner (displays window.electron.dataDir when available) while preserving non-Electron warning content.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant App as Electron Main
  participant Server as Local Server (Go)
  participant Probe as Health Probe
  participant UI as BrowserWindow
  participant Tray as System Tray
  participant Pre as Preload (dataDir)

  User->>App: Launch app
  App->>Server: Spawn binary (PORT, SQLITE_PATH, env, version)
  loop probe
    App->>Probe: GET /health on localhost:PORT
    Probe-->>App: 200 / error
  end
  alt Server ready
    App->>Pre: expose dataDir via preload
    App->>Tray: Create tray + menu (Show, Quit)
    App->>UI: Create window -> load http://localhost:PORT
  else Startup error
    App->>User: Show error dialog (logs, save, guidance)
    App->>Server: Terminate if running
    App-->>User: Exit or keep in tray based on choice
  end
Loading
sequenceDiagram
  autonumber
  participant Dev as Tag Push / Manual Dispatch
  participant GHA as GitHub Actions
  participant Windows as Windows Runner

  Dev->>GHA: Trigger workflow (tag/manual)
  GHA->>Windows: Checkout, setup Bun/Node/Go
  Windows->>Windows: Build web (bun), build Go binary (ldflags VERSION), bump Electron version, npm install, build Windows package
  Windows-->>GHA: Upload artifacts (windows-build)
  GHA->>GHA: Release job downloads artifacts and creates GitHub Release (includes artifacts)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

I hopped through code and stitched a tray,
I coaxed a tiny server to run all day.
DMGs and EXEs in tidy rows,
Icons that glow where the menu shows.
Carrots compiled — release bells ring, away! 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the main change—adding an Electron wrapper for a desktop app—matching the extensive additions of Electron configuration, scripts, and workflows in the pull request. It is specific, concise, and clearly conveys the purpose of the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 414be64 and 7074ea2.

📒 Files selected for processing (4)
  • .github/workflows/electron-build.yml (1 hunks)
  • .github/workflows/linux-release.yml (1 hunks)
  • .github/workflows/macos-release.yml (1 hunks)
  • .github/workflows/windows-release.yml (1 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (5)
.github/workflows/electron-build.yml (2)

54-60: Consider implementing macOS code signing for production releases.

Setting CSC_IDENTITY_AUTO_DISCOVERY=false skips code signing, which will trigger Gatekeeper warnings on macOS ("App cannot be opened because it is from an unidentified developer"). For production releases, obtain an Apple Developer ID certificate and configure signing to improve user experience.

Store the certificate in GitHub Secrets and enable signing:

env:
  CSC_LINK: ${{ secrets.MAC_CERT_P12_BASE64 }}
  CSC_KEY_PASSWORD: ${{ secrets.MAC_CERT_PASSWORD }}

26-29: Upgrade Go version to 1.25.1 in the workflow. This brings GC (“Green Tea”), JSON v2, deterministic testing, runtime and compiler improvements, and enhanced tooling—verify project compatibility.

electron/README.md (2)

10-10: Use heading syntax for option labels.

Using bold emphasis (**Option A:**) for section labels reduces document structure clarity. Use heading syntax for better navigation and accessibility.

As per static analysis hints.

-**Option A: Use existing binary (without Go installed)**
+#### Option A: Use existing binary (without Go installed)

Apply the same change to "Option B" on line 16.


16-17: Address the TODO for building from source.

The documentation is incomplete for users who want to build the Go binary from source. This is a key workflow for contributors and users without pre-built binaries.

Do you want me to generate the build instructions or open a new issue to track this task?

electron/build.sh (1)

15-39: Improve build script robustness.

Consider these improvements for better reliability:

  1. Validate outputs exist: After building the Go binary, verify the file exists before proceeding to Electron build.
  2. Use consistent platform detection: $OSTYPE is shell-dependent and fragile. Consider using uname or Go's build constraints.
  3. Add cleanup step: Remove old build artifacts before starting to ensure clean builds.

Example validation:

# After building Go binary
if [[ ! -f "new-api" ]]; then
  echo "Error: Go binary build failed"
  exit 1
fi
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c9abe1d and b39885b.

⛔ Files ignored due to path filters (4)
  • electron/icon.png is excluded by !**/*.png
  • electron/tray-icon-windows.png is excluded by !**/*.png
  • electron/tray-iconTemplate.png is excluded by !**/*.png
  • electron/tray-iconTemplate@2x.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • .github/workflows/electron-build.yml (1 hunks)
  • .gitignore (1 hunks)
  • electron/README.md (1 hunks)
  • electron/build.sh (1 hunks)
  • electron/create-tray-icon.js (1 hunks)
  • electron/entitlements.mac.plist (1 hunks)
  • electron/main.js (1 hunks)
  • electron/package.json (1 hunks)
  • electron/preload.js (1 hunks)
  • web/package.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
electron/main.js (1)
electron/preload.js (1)
  • require (1-1)
electron/create-tray-icon.js (1)
electron/main.js (3)
  • fs (5-5)
  • require (1-1)
  • require (2-2)
🪛 actionlint (1.7.7)
.github/workflows/electron-build.yml

95-95: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🪛 markdownlint-cli2 (0.18.1)
electron/README.md

10-10: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🔇 Additional comments (5)
.gitignore (1)

14-18: LGTM! Appropriate ignore patterns for Electron artifacts.

The additions correctly exclude Electron build outputs, dependencies, and the ESLint cache.

electron/preload.js (1)

1-6: LGTM! Secure preload implementation.

The use of contextBridge.exposeInMainWorld follows Electron security best practices by providing controlled, minimal access to Electron APIs. The exposed metadata (version and platform) is safe for renderer consumption.

electron/create-tray-icon.js (1)

1-60: LGTM! Well-designed tray icon generation with fallback.

The script correctly:

  • Uses 22×22px for macOS tray icon sizing
  • Follows Template naming convention for automatic theme adaptation
  • Provides graceful fallback with clear user guidance when the canvas module is unavailable
  • Generates multiple icon variants for different use cases

The error handling and fallback approach ensures the build process doesn't break in environments lacking the canvas dependency.

web/package.json (1)

13-13: antd ^5.27.4 is up-to-date and has no known security vulnerabilities.

electron/entitlements.mac.plist (1)

5-12: Minimize macOS entitlements and enable hardened runtime.

  • disable-library-validation and allow-dyld-environment-variables bypass library signing and allow code injection—remove unless strictly required.
  • Keep only allow-jit/allow-unsigned-executable-memory if V8 JIT is essential.
  • Enable hardenedRuntime: true and gatekeeperAssess: true in your build config to restore macOS protections.

Can you confirm which of these entitlements are mandatory for your Electron app’s functionality?

Comment thread .github/workflows/electron-build.yml Outdated
Comment on lines +11 to +13
strategy:
matrix:
os: [macos-latest, windows-latest]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add Linux to the build matrix.

The README documents Linux support (.AppImage and .deb), but the workflow only builds for macOS and Windows. Add ubuntu-latest to the matrix to ensure Linux binaries are built and released.

     strategy:
       matrix:
-        os: [macos-latest, windows-latest]
+        os: [macos-latest, windows-latest, ubuntu-latest]

You'll also need to add corresponding build and upload steps for Linux artifacts.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
strategy:
matrix:
os: [macos-latest, windows-latest]
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
🤖 Prompt for AI Agents
.github/workflows/electron-build.yml lines 11-13: the CI matrix currently
targets only macOS and Windows so Linux artifacts are not produced; add
"ubuntu-latest" to the matrix os list and update the workflow to include
Linux-specific build and upload steps: run the electron-builder commands that
produce .AppImage and .deb on ubuntu, ensure any Linux-specific dependencies or
setup (e.g., apt-get install, snapcraft or appimage tooling if used) are
executed in preceding steps, and add artifact upload/publish actions for the
generated .AppImage and .deb files so releases include Linux binaries.

Comment thread .github/workflows/electron-build.yml Outdated
Comment thread .github/workflows/electron-build.yml
Comment thread electron/build.sh
Comment thread electron/build.sh

if [[ "$OSTYPE" == "darwin"* ]]; then
echo "Building for macOS..."
CGO_ENABLED=1 go build -ldflags="-s -w" -o new-api

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

❓ Verification inconclusive

Verify CGO is required before enabling it.

Setting CGO_ENABLED=1 increases build complexity, requires C toolchain dependencies, and reduces binary portability. Many Go applications do not require CGO.

If CGO is not required, remove CGO_ENABLED=1 to simplify builds and improve portability.


🏁 Script executed:

#!/bin/bash
# Check if the codebase uses CGO

# Search for CGO-specific imports
rg -n -C2 'import\s+"C"' --type=go

# Search for CGO build tags
rg -n -C2 '//\s*go:build.*cgo' --type=go

# Search for .c, .cpp, .h files (C/C++ sources)
fd -e c -e cpp -e h -e cc

Length of output: 0


Remove CGO_ENABLED=1 from electron/build.sh
No CGO imports, build tags, or C/C++ sources detected—omit CGO for simpler, portable builds.

🤖 Prompt for AI Agents
In electron/build.sh around line 17, the go build invocation prefixes the
command with CGO_ENABLED=1 even though there are no CGO imports or C/C++
sources; remove the CGO_ENABLED=1 prefix (or set it to 0) so the build runs
without enabling cgo, leaving the rest of the build flags and output name
unchanged and committing that change.

Comment thread electron/main.js
Comment on lines +10 to +11
const PORT = 3000;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Make the embedded server port collision-resistant.

Hard-coding the local API to port 3000 means the desktop app simply refuses to launch whenever that port is already occupied (very common on developer machines). The child process exits, waitForServer never succeeds, and the user only sees the fatal dialog. Please probe for a free port (e.g., via get-port) or honor a configurable PORT override, then update the spawn env and loadURL to use the negotiated value.

🤖 Prompt for AI Agents
In electron/main.js around lines 10-11 the embedded server port is hard-coded to
3000 which causes startup failures when that port is in use; change this to
first check for a user override (process.env.PORT or CLI flag) and if absent
negotiate a free port (use an existing library like get-port or net.createServer
probe) before spawning the child. After obtaining the port, set it into the
child process env and use the negotiated value when building the URL passed to
loadURL and when waitForServer polls; ensure waitForServer uses the same
host:port pair and surface the chosen port in logs/errors.

Comment thread electron/package.json Outdated
Comment thread electron/package.json Outdated
@Calcium-Ion
Calcium-Ion self-requested a review October 5, 2025 06:17

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
electron/main.js (1)

11-12: Avoid hard-coding port 3000.

The app still binds the bundled server to a fixed 3000, so startup fails outright whenever that port is in use—a very common case on developer machines. Please negotiate a free port (e.g., honor process.env.PORT or probe with get-port) and propagate the chosen value to the child process, health check, and loadURL.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8026e51 and 3da7ceb.

📒 Files selected for processing (4)
  • .gitignore (1 hunks)
  • electron/main.js (1 hunks)
  • electron/package.json (1 hunks)
  • electron/preload.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • electron/package.json
🧰 Additional context used
🧬 Code graph analysis (1)
electron/main.js (1)
electron/preload.js (1)
  • require (1-1)

Comment thread .gitignore Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
electron/main.js (1)

11-12: Please negotiate a free backend port before spawning the server.

We’re still pinning the embedded API to port 3000, so the app dies whenever anything else is listening there—a very common scenario on dev boxes and even on end-user machines. That’s the same collision issue flagged earlier: the Go binary exits with “address already in use”, waitForServer never succeeds, and the user gets the fatal dialog.

Replace the constant with logic that:

  1. Honors a user override (process.env.PORT or CLI flag) when present.
  2. Otherwise probes for an available port (e.g., via net.createServer() or a helper such as get-port).
  3. Propagates the negotiated value into the child env, every checkServerAvailability call, the BrowserWindow loadURL, and any user-facing diagnostics.

Without this change the desktop app is still non-functional on machines where 3000 is occupied, so we need to address it before shipping.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3da7ceb and ff77ba1.

📒 Files selected for processing (4)
  • electron/main.js (1 hunks)
  • electron/package.json (1 hunks)
  • electron/preload.js (1 hunks)
  • web/src/components/setup/components/steps/DatabaseStep.jsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • electron/package.json
🧰 Additional context used
🧬 Code graph analysis (3)
electron/main.js (1)
electron/preload.js (2)
  • require (1-1)
  • platform (6-6)
web/src/components/setup/components/steps/DatabaseStep.jsx (1)
web/src/components/setup/SetupWizard.jsx (1)
  • setupStatus (34-38)
electron/preload.js (1)
electron/main.js (3)
  • require (1-1)
  • require (2-2)
  • platform (152-152)
🪛 Biome (2.1.2)
electron/preload.js

[error] 13-16: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

Comment thread electron/preload.js Outdated
Calcium-Ion
Calcium-Ion previously approved these changes Oct 5, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
.github/workflows/electron-build.yml (1)

117-124: Upgrade softprops/action-gh-release to @v2

softprops/action-gh-release@v1 runs on the old Node.js 12 runtime, which GitHub Actions no longer supports. This step will fail, blocking releases. Move to @v2 to restore compatibility.

-      - name: Create Release
-        uses: softprops/action-gh-release@v1
+      - name: Create Release
+        uses: softprops/action-gh-release@v2
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff77ba1 and 414be64.

⛔ Files ignored due to path filters (1)
  • electron/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • .github/workflows/electron-build.yml (1 hunks)
  • .github/workflows/linux-release.yml (1 hunks)
  • .github/workflows/macos-release.yml (1 hunks)
  • .github/workflows/windows-release.yml (1 hunks)
  • .gitignore (1 hunks)
  • electron/preload.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • electron/preload.js
  • .gitignore
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/linux-release.yml

52-52: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

.github/workflows/windows-release.yml

47-47: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

.github/workflows/electron-build.yml

117-117: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

.github/workflows/macos-release.yml

45-45: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

Comment thread .github/workflows/linux-release.yml Outdated
Comment thread .github/workflows/macos-release.yml Outdated
Comment thread .github/workflows/windows-release.yml Outdated
@Calcium-Ion
Calcium-Ion merged commit 42861bc into QuantumNous:main Oct 5, 2025
1 check was pending
@coderabbitai coderabbitai Bot mentioned this pull request Oct 11, 2025
x22x22 pushed a commit to x22x22/new-api that referenced this pull request Apr 24, 2026
feat: Add Electron wrapper for desktop app
@coderabbitai coderabbitai Bot mentioned this pull request Apr 29, 2026
11 tasks
@coderabbitai coderabbitai Bot mentioned this pull request Apr 29, 2026
11 tasks
@coderabbitai coderabbitai Bot mentioned this pull request Jun 30, 2026
11 tasks
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.

2 participants