Skip to content

feat: macOS desktop app (Electron) + iOS build fixes - #1

Merged
OrihaWeave merged 2 commits into
mainfrom
devin/1792458629-macos-ios-build
Oct 21, 2026
Merged

OrihaWeave merged 2 commits into
mainfrom
devin/1792458629-macos-ios-build

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Summary

Adds a macOS desktop app and fixes iOS build issues found while verifying both on a real Mac (macOS 26.6 / Xcode 26.6, iPhone 17 sim on iOS 26.5).

apps/desktop — new Electron shell. The main process starts the QuireNote server in-process on a free port, waits for /api/health, then opens a BrowserWindow on the bundled web app. Data lives in ~/Library/Application Support/QuireNote/data. pnpm dist produces release/QuireNote-<ver>-arm64-mac.zip via electron-builder (unsigned).

Key mechanism: the server is bundled by esbuild into a single dist/server.mjs with natives marked external; native/bin/ carries only better_sqlite3.node (rebuilt for the Electron ABI via @electron/rebuild) and vec0.dylib. The server resolves them through two new env hooks in sqlite.ts:

const binding = process.env.QUIRENOTE_SQLITE3_BINDING?.trim();
new Database(path, binding ? { nativeBinding: binding } : undefined);
// sqlite-vec: db.loadExtension(process.env.QUIRENOTE_SQLITE_VEC_EXT) ?? sqliteVec.load(db)

Normal server deployments are untouched — without the env vars, behavior is identical.

iOS fixes verified on the simulator:

  • api.ts: in the native shell before a server is configured, requests hit the Capacitor asset server and resolve to index.html as a Blob — the persisted query cache then crashed the home screen (data?.find is not a function). request() now fails fast when isNativePlatform() && !localStorage["quirenote.server"], so the server-onboarding sheet shows instead.
  • Info.plist: NSAllowsArbitraryLoads so the app can reach http:// self-hosted servers (LAN installs).
  • Committed SPM Package.resolved; local simulator build instructions added to docs/mobile.md.

macOS UX polish: hardcoded Ctrl in UI text now renders as ⌘ on Mac via the existing Shortcut/modKey helpers (sidebar, settings, embed dialog, paste-blocked toast, user manual).

Docs: docs/desktop.md (build + architecture), updated docs/mobile.md and README platform badge (web · macOS · iOS · Android).

Verified: QuireNote.app launches and renders seeded data; iOS app connects to a live server at 127.0.0.1:8787 and shows the same notebooks. pnpm typecheck and pnpm lint clean.

Link to Devin session: https://app.devin.ai/sessions/38b13a08ac3248aeb2d431674d589430
Open in Devin Desktop: https://app.devin.ai/desktop/session/38b13a08ac3248aeb2d431674d589430?variant=devin
Requested by: @Mar7thLover

- apps/desktop: Electron shell that runs the QuireNote server in-process
  (free port + /api/health wait), serves the built web app; esbuild bundles
  the server, @electron/rebuild compiles better-sqlite3 for the Electron ABI,
  sqlite-vec ships as vec0.dylib; electron-builder produces unsigned macOS zip
- server: QUIRENOTE_SQLITE3_BINDING / QUIREENOTE_SQLITE_VEC_EXT let the
  packaged app point at raw native binaries (normal path unchanged)
- web: show ⌘ instead of Ctrl on macOS (sidebar, settings, manual, i18n
  strings via modKey); server address hint consistent
- web fix: in the native shell with no server configured, API calls now fail
  fast instead of resolving to the local index.html blob (crashed the home
  screen via persisted query cache)
- iOS: NSAllowsArbitraryLoads so the app can reach http self-hosted servers;
  SPM Package.resolved committed; docs for local simulator builds
- docs: desktop.md (Electron build) + mobile.md local iOS build steps;
  README platforms badge adds macOS

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

- server: index.html and SPA fallback served with Cache-Control: no-cache
  so app upgrades never run a stale entry point referencing deleted hashed
  chunks (Electron webview cache crashed with 'Failed to fetch dynamically
  imported module'); /assets/* 404 instead of index.html when a chunk is gone
- manual: apply the Ctrl->⌘ transform to section summaries, not just bodies

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

✅ End-to-end tested: macOS Electron app + iOS simulator

Drove the packaged app (release/mac-arm64/QuireNote.app) and the iOS app in the iPhone 17 simulator against a live server. Two issues were found during testing and both are fixed in cff3a44:

  1. Manual summary leaked "Ctrl K" on macOS — the Ctrl →⌘ replacement applied to the section body but not current.summary. Now applies to both.
  2. Stale-cache crash on first run after rebuild — index.html was served without Cache-Control while hashed assets are immutable; a cached entry point could reference deleted chunks → Failed to fetch dynamically imported module blank screen. index.html/SPA fallback now serve no-cache, and missing /assets/* files return 404 instead of index.html.
Passing checks
  • Sidebar search hint ⌘ K, shortcuts dialog ⌘/ ⌘⌥N ⌘⇧O…, Settings → About — all ⌘, no Ctrl
    sidebar ⌘K
  • HTML block hint "HTML (⌘ + Enter to finish)"; ⌘+Enter exits editing
    HTML ⌘+Enter
  • "Open web page" in source context menu opens system Chrome via shell.openExternal
  • iOS: home → notebook → note renders with server data (102 words seeded)
    iOS note
  • iOS first-launch regression: fresh install shows "Connect to your QuireNote server" sheet (no crash); entering http://127.0.0.1:8787 + Connect loads server data
    iOS onboarding

@OrihaWeave
OrihaWeave merged commit e7e5c0c into main Oct 21, 2026
2 checks passed
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