{"_id":"@capawesome/capacitor-electron","_rev":"3-bb5abba6457d004b8b6d432484c81d3b","name":"@capawesome/capacitor-electron","dist-tags":{"latest":"0.1.1"},"versions":{"0.0.1":{"name":"@capawesome/capacitor-electron","version":"0.0.1","keywords":["capacitor","capacitor-platform","electron","desktop"],"author":{"name":"Robin Genz","email":"mail@robingenz.dev"},"license":"MIT","_id":"@capawesome/capacitor-electron@0.0.1","maintainers":[{"name":"robingenz","email":"mail@robingenz.dev"}],"homepage":"https://capawesome.io/","bugs":{"url":"https://github.com/capawesome-team/capacitor-electron/issues"},"bin":{"capacitor-electron":"dist/cli/index.js"},"dist":{"shasum":"3b6e56bbf1d575574071841e79458c64be386d8b","tarball":"https://registry.npmjs.org/@capawesome/capacitor-electron/-/capacitor-electron-0.0.1.tgz","fileCount":39,"integrity":"sha512-BYx/DiemOuvN3QlcYAI5+9soTNmmCAxZMZ6n5I9zwasdnX1x4QodyjpF0Q0EndIhhKJ1S7vln+VpD13XXbtPCg==","signatures":[{"sig":"MEYCIQDP04pgXN31TPsHTZ+kpFyAeaZWWEshFLN92YTTeUApUgIhAMIJO4PNAsPyu2sdW4YTjRH0Ocjja/qajajx1Tv8+4ce","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":101607},"main":"dist/runtime/index.js","types":"dist/types/runtime/index.d.ts","exports":{".":{"types":"./dist/types/runtime/index.d.ts","default":"./dist/runtime/index.js"},"./config":{"types":"./dist/types/config/index.d.ts","default":"./dist/config/index.js"},"./plugin":{"types":"./dist/types/plugin/index.d.ts","default":"./dist/plugin/index.js"},"./preload":{"default":"./dist/preload/index.js"},"./package.json":"./package.json"},"funding":[{"url":"https://github.com/sponsors/capawesome-team/","type":"github"},{"url":"https://opencollective.com/capawesome","type":"opencollective"}],"gitHead":"bff8bc7d27ea2cc8bb29a7a672e6f6c340eadf78","scripts":{"fmt":"npm run eslint -- --fix && npm run prettier -- --write","lint":"npm run eslint && npm run prettier -- --check","test":"vitest run","build":"npm run clean && tsc --project tsconfig.build.json && tsc --project tsconfig.types.json && rollup -c rollup.config.mjs","clean":"rimraf ./dist ./build","watch":"tsc --watch","eslint":"eslint . --ext ts","verify":"npm run build && npm run test","prepare":"husky","prettier":"prettier \"**/*.{css,html,ts,js}\"","capacitor:add":"node ./dist/cli/index.js add","capacitor:run":"node ./dist/cli/index.js run","capacitor:copy":"node ./dist/cli/index.js copy","capacitor:open":"node ./dist/cli/index.js open","prepublishOnly":"npm run build","capacitor:update":"node ./dist/cli/index.js update"},"_npmUser":{"name":"robingenz","email":"mail@robingenz.dev"},"repository":{"url":"git+https://github.com/capawesome-team/capacitor-electron.git","type":"git"},"_npmVersion":"11.13.0","description":"Capacitor platform for building desktop apps with Electron.","directories":{},"lint-staged":{"**/*.{css,html,ts,js,json}":"prettier --write"},"_nodeVersion":"24.16.0","eslintConfig":{"extends":"@ionic/eslint-config/recommended"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"husky":"9.1.7","eslint":"8.57.0","rimraf":"6.1.2","rollup":"4.53.3","vitest":"4.1.10","electron":"43.1.0","prettier":"3.4.2","typescript":"5.9.3","@types/node":"24.13.3","lint-staged":"17.0.5","@capacitor/core":"8.0.0","@ionic/eslint-config":"0.4.0"},"peerDependencies":{"electron":">=28.0.0"},"peerDependenciesMeta":{"electron":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/capacitor-electron_0.0.1_1783848489038_0.5704840449717923","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@capawesome/capacitor-electron","version":"0.1.0","keywords":["capacitor","capacitor-platform","electron","desktop"],"author":{"name":"Robin Genz","email":"mail@robingenz.dev"},"license":"MIT","_id":"@capawesome/capacitor-electron@0.1.0","maintainers":[{"name":"robingenz","email":"mail@robingenz.dev"}],"homepage":"https://capawesome.io/docs/sdks/capacitor/electron/","bugs":{"url":"https://github.com/capawesome-team/capacitor-electron/issues"},"bin":{"capacitor-electron":"dist/cli/index.js"},"dist":{"shasum":"8d68da836ef901eb8c6ae13086002f1f341cd94d","tarball":"https://registry.npmjs.org/@capawesome/capacitor-electron/-/capacitor-electron-0.1.0.tgz","fileCount":39,"integrity":"sha512-l4vAithAM8sPUVru0fJKQok+OrbZik3r8O7/OPR80ioEbJ4ukD9436O19wxDvE9L33IxzL52JxRYKmfSQOpe5w==","signatures":[{"sig":"MEUCIQCkRevOToN7NPAj3UA6iBdE5XKGkTMbjB3CiQzyl6vmSwIgQwCJkqkVMsCc+Jf7Or02x/enNG/l8iKfb0GFz2C8Zo8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@capawesome%2fcapacitor-electron@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":103399},"main":"dist/runtime/index.js","types":"dist/types/runtime/index.d.ts","exports":{".":{"types":"./dist/types/runtime/index.d.ts","default":"./dist/runtime/index.js"},"./config":{"types":"./dist/types/config/index.d.ts","default":"./dist/config/index.js"},"./plugin":{"types":"./dist/types/plugin/index.d.ts","default":"./dist/plugin/index.js"},"./preload":{"default":"./dist/preload/index.js"},"./package.json":"./package.json"},"funding":[{"url":"https://github.com/sponsors/capawesome-team/","type":"github"},{"url":"https://opencollective.com/capawesome","type":"opencollective"}],"gitHead":"7dca08c0b6c243135579238a291eb09c7ad1042e","scripts":{"fmt":"npm run eslint -- --fix && npm run prettier -- --write","lint":"npm run eslint && npm run prettier -- --check","test":"vitest run","build":"npm run clean && tsc --project tsconfig.build.json && tsc --project tsconfig.types.json && rollup -c rollup.config.mjs","clean":"rimraf ./dist ./build","watch":"tsc --watch","eslint":"eslint . --ext ts","verify":"npm run build && npm run test","prepare":"husky","prettier":"prettier \"**/*.{css,html,ts,js}\"","capacitor:add":"node ./dist/cli/index.js add","capacitor:run":"node ./dist/cli/index.js run","capacitor:copy":"node ./dist/cli/index.js copy","capacitor:open":"node ./dist/cli/index.js open","prepublishOnly":"npm run build","capacitor:update":"node ./dist/cli/index.js update"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c23f95b4-23a9-46dc-94d3-967c4491c0ba"}},"repository":{"url":"git+https://github.com/capawesome-team/capacitor-electron.git","type":"git"},"_npmVersion":"12.0.1","description":"Capacitor platform for building desktop apps with Electron.","directories":{},"lint-staged":{"**/*.{css,html,ts,js,json}":"prettier --write"},"_nodeVersion":"24.18.0","eslintConfig":{"extends":"@ionic/eslint-config/recommended"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"husky":"9.1.7","eslint":"8.57.0","rimraf":"6.1.2","rollup":"4.53.3","vitest":"4.1.10","electron":"43.1.0","prettier":"3.4.2","typescript":"5.9.3","@types/node":"24.13.3","lint-staged":"17.0.5","@capacitor/core":"8.0.0","@ionic/eslint-config":"0.4.0"},"peerDependencies":{"electron":">=28.0.0","@capacitor/core":">=6.0.0"},"peerDependenciesMeta":{"electron":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/capacitor-electron_0.1.0_1783953147771_0.03313061610977197","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@capawesome/capacitor-electron","version":"0.1.1","description":"Capacitor platform for building desktop apps with Electron.","main":"dist/runtime/index.js","types":"dist/types/runtime/index.d.ts","exports":{".":{"types":"./dist/types/runtime/index.d.ts","default":"./dist/runtime/index.js"},"./preload":{"default":"./dist/preload/index.js"},"./config":{"types":"./dist/types/config/index.d.ts","default":"./dist/config/index.js"},"./plugin":{"types":"./dist/types/plugin/index.d.ts","default":"./dist/plugin/index.js"},"./package.json":"./package.json"},"bin":{"capacitor-electron":"dist/cli/index.js"},"author":{"name":"Robin Genz","email":"mail@robingenz.dev"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/capawesome-team/capacitor-electron.git"},"bugs":{"url":"https://github.com/capawesome-team/capacitor-electron/issues"},"homepage":"https://capawesome.io/docs/sdks/capacitor/electron/","funding":[{"type":"github","url":"https://github.com/sponsors/capawesome-team/"},{"type":"opencollective","url":"https://opencollective.com/capawesome"}],"keywords":["capacitor","capacitor-platform","electron","desktop"],"scripts":{"capacitor:add":"node ./dist/cli/index.js add","capacitor:copy":"node ./dist/cli/index.js copy","capacitor:update":"node ./dist/cli/index.js update","capacitor:open":"node ./dist/cli/index.js open","capacitor:run":"node ./dist/cli/index.js run","verify":"npm run build && npm run test","lint":"npm run eslint && npm run prettier -- --check","fmt":"npm run eslint -- --fix && npm run prettier -- --write","eslint":"eslint . --ext ts","prettier":"prettier \"**/*.{css,html,ts,js}\"","build":"npm run clean && tsc --project tsconfig.build.json && tsc --project tsconfig.types.json && rollup -c rollup.config.mjs","clean":"rimraf ./dist ./build","test":"vitest run","watch":"tsc --watch","prepare":"husky","prepublishOnly":"npm run build"},"lint-staged":{"**/*.{css,html,ts,js,json}":"prettier --write"},"devDependencies":{"@capacitor/core":"8.0.0","@ionic/eslint-config":"0.4.0","@types/node":"24.13.3","electron":"43.1.0","eslint":"8.57.0","husky":"9.1.7","lint-staged":"17.0.5","prettier":"3.4.2","rimraf":"6.1.2","rollup":"4.53.3","typescript":"5.9.3","vitest":"4.1.10"},"peerDependencies":{"@capacitor/core":">=6.0.0","electron":">=28.0.0"},"peerDependenciesMeta":{"electron":{"optional":true}},"eslintConfig":{"extends":"@ionic/eslint-config/recommended"},"publishConfig":{"access":"public"},"gitHead":"12fe3417565554a9f71c53dc017a6a3c02562f65","_id":"@capawesome/capacitor-electron@0.1.1","_nodeVersion":"24.19.0","_npmVersion":"12.0.2","dist":{"integrity":"sha512-ALzLTcdcWEfYQCQ/hPper2Nwhk9Hes/s9yusKGXggxOzDL0Rt/r1BF6HcQq2CshG1oB5i2UY4CQ/cRS9JdD2PA==","shasum":"9a654275c48261a5ac6b350b768f28ce668cd6e5","tarball":"https://registry.npmjs.org/@capawesome/capacitor-electron/-/capacitor-electron-0.1.1.tgz","fileCount":42,"unpackedSize":142342,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@capawesome%2fcapacitor-electron@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCYZkQOAVI7UEw9uxrRMckgo/l81+b0I5SvQz66dNDNUQIgK4GHZoVQH+SyLpvjgtjzTH0Dr4GyRugXyDgE3tikHcg="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c23f95b4-23a9-46dc-94d3-967c4491c0ba"}},"directories":{},"maintainers":[{"name":"robingenz","email":"mail@robingenz.dev"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/capacitor-electron_0.1.1_1788156388918_0.8932566001728581"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-12T09:28:08.923Z","modified":"2026-08-31T06:06:29.493Z","0.0.1":"2026-07-12T09:28:09.170Z","0.1.0":"2026-07-13T14:32:27.904Z","0.1.1":"2026-08-31T06:06:29.039Z"},"bugs":{"url":"https://github.com/capawesome-team/capacitor-electron/issues"},"author":{"name":"Robin Genz","email":"mail@robingenz.dev"},"license":"MIT","homepage":"https://capawesome.io/docs/sdks/capacitor/electron/","keywords":["capacitor","capacitor-platform","electron","desktop"],"repository":{"type":"git","url":"git+https://github.com/capawesome-team/capacitor-electron.git"},"description":"Capacitor platform for building desktop apps with Electron.","maintainers":[{"name":"robingenz","email":"mail@robingenz.dev"}],"readme":"# Capacitor Electron Platform\n\nCapacitor platform to build, run, and package desktop apps for macOS, Windows, and Linux with Electron.[^1]\n\n<div class=\"capawesome-z29o10a\">\n  <a href=\"https://capawesome.io/\" target=\"_blank\">\n    <img alt=\"Deliver Live Updates to your Capacitor app with Capawesome Cloud\" src=\"https://capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.png?t=1\" />\n  </a>\n</div>\n\n## Features\n\nThe Capacitor Electron platform brings your web app and your Capacitor plugins to the desktop. Here are some of the key features:\n\n- 🖥️ **Cross-platform**: Build desktop apps for macOS, Windows, and Linux from one codebase.\n- ⚡ **Familiar workflow**: `cap add`, `cap sync`, `cap run` — the same commands as iOS and Android.\n- 🔌 **Plugin support**: Capacitor plugins with an Electron implementation work out of the box; plugins with a web implementation work automatically via fallback.\n- 🔒 **Security-first**: Sandboxed renderer, context isolation, strict Content-Security-Policy, and validated IPC — enabled by default and not configurable.\n- 🔗 **Deep links**: Custom URL schemes delivered through the standard `@capacitor/app` plugin's `appUrlOpen` event.\n- 📱 **App lifecycle**: `appStateChange`, `pause`, and `resume` events, exactly like on mobile.\n- ♻️ **Live reload**: Develop against your web dev server with full HMR.\n- 📦 **Packaging**: Create installers with electron-builder, including automatic dependency vendoring.\n- 🪟 **Window management**: Typed window options, state persistence, and hooks for trays and menus.\n- 🧩 **Minimal scaffold**: You own a handful of small, stable files; all platform logic ships in the package and updates via `npm update`.\n- 🔁 **Up-to-date**: Always supports the latest Capacitor and Electron versions.\n- ⭐️ **Support**: Priority support from the Capawesome Team.\n- ✨ **Handcrafted**: Built from the ground up with care and expertise, not forked or AI-generated.\n\nMissing a feature? Just [open an issue](https://github.com/capawesome-team/capacitor-electron/issues) and we'll take a look!\n\n## Use Cases\n\nThe Electron platform is typically used to bring an existing Capacitor app to the desktop, for example:\n\n- **Desktop companion apps**: Ship your mobile app's functionality to macOS, Windows, and Linux without a rewrite.\n- **Offline-first desktop tools**: Combine the platform with plugins like [SQLite](https://capawesome.io/docs/sdks/capacitor/sqlite/) for fully offline desktop applications.\n- **Internal business tools**: Distribute apps directly to your team without app stores.\n- **Kiosk and point-of-sale apps**: Run your web app full screen on dedicated desktop hardware.\n- **Deep-link driven workflows**: Handle custom URL schemes on the desktop exactly like on mobile.\n\n## Compatibility\n\n| Platform Version | Capacitor Version | Electron Version | Status         |\n| ---------------- | ----------------- | ---------------- | -------------- |\n| 0.x              | >=6.x.x           | >=28.x.x         | Active support |\n\n> [!NOTE]\n> On Capacitor 6 and 7, the Capacitor CLI ignores the exit code of platform hooks, so a failing `npx cap sync` still reports success — check the log output for `[capacitor-electron]` errors. Capacitor 8 fails the command properly.\n\n## Guides\n\n- [Capacitor Electron Platform: Build Desktop Apps](https://capawesome.io/blog/announcing-the-capacitor-electron-platform/)\n\n## Supported Plugins\n\nPlugins integrate with the Electron platform in one of three ways:\n\n| Plugin | Support |\n| --- | --- |\n| [`@capacitor/app`](https://capacitorjs.com/docs/apis/app) | ✅ Built into the platform (`appUrlOpen`, `appStateChange`, `pause`, `resume`, `getInfo`, `getState`, `getLaunchUrl`, `exitApp`, `minimizeApp`) |\n| [`@capawesome-team/capacitor-sqlite`](https://capawesome.io/docs/sdks/capacitor/sqlite/) | ✅ Native Electron implementation via `node:sqlite` |\n| Plugins with a web implementation | ✅ Automatic web fallback |\n\nPlugins that require native functionality beyond their web implementation need a dedicated Electron implementation (see [Plugin Development](#plugin-development)). Is your favorite plugin missing? Just [open an issue](https://github.com/capawesome-team/capacitor-electron/issues) and we'll take a look!\n\n## Installation\n\nYou can use our **AI-Assisted Setup** to add the platform.\nAdd the [Capawesome Skills](https://github.com/capawesome-team/skills) to your AI tool using the following command:\n\n```bash\nnpx skills add capawesome-team/skills --skill capacitor-platforms\n```\n\nThen use the following prompt:\n\n```\nUse the `capacitor-platforms` skill from `capawesome-team/skills` to add the `@capawesome/capacitor-electron` platform to my project.\n```\n\nIf you prefer **Manual Setup**, add the platform by running the following commands:\n\n```bash\nnpm install @capawesome/capacitor-electron\nnpx cap add @capawesome/capacitor-electron\ncd electron && npm install && cd ..\n```\n\nWe recommend adding a `postinstall` script to your root `package.json` so the Electron dependencies are always installed together with your app dependencies:\n\n```json\n{\n  \"scripts\": {\n    \"postinstall\": \"cd electron && npm ci && cd ..\"\n  }\n}\n```\n\nThe initial `cd electron && npm install` generates `electron/package-lock.json` — commit it so that `npm ci` works for every future install.\n\n> [!NOTE]\n> Always use the full package name with Capacitor CLI commands (e.g. `npx cap sync @capawesome/capacitor-electron`). A bare `npx cap sync electron` resolves to the `electron` npm package and silently does nothing.\n\nThe scaffolded `electron/` project contains only files you own:\n\n| File | Purpose |\n| --- | --- |\n| `main.ts` | ~5 lines: imports the runtime and starts the app |\n| `capacitor.electron.config.ts` | Typed platform options (window, CSP, deep links, hooks) |\n| `electron-builder.config.js` | Packaging configuration |\n| `assets/` | App icons |\n\nEverything with logic lives in the versioned npm package and updates via `npm update` — your platform project never rots.\n\n## Configuration\n\nPlatform options are configured in `electron/capacitor.electron.config.ts` with full type safety:\n\n```typescript\nimport { defineConfig } from '@capawesome/capacitor-electron/config';\n\nexport default defineConfig({\n  window: {\n    width: 1200,\n    height: 800,\n    minWidth: 800,\n    minHeight: 600,\n  },\n  deepLinks: {\n    scheme: 'myapp',\n  },\n});\n```\n\nExtension happens through typed options and hooks (`windowFactory`, `beforeReady`, `onWindowCreated`, CSP overrides) — never by owning runtime code.\n\n### Plugin Configuration\n\nSome plugins support platform-specific configuration on Android and iOS — for example, the Capacitor Live Update plugin reads a default channel from an Android string resource or an iOS `Info.plist` key so the build system can inject a value derived from the app version. The `plugins` section of `electron/capacitor.electron.config.ts` fills that role on Electron — generically, for every plugin. Because the file is executable TypeScript evaluated in the main process, values can be computed in code — no template syntax required.\n\nIt is merged over the `plugins` section of the Capacitor config **shallowly, per plugin key, and this section wins**: for each plugin, its keys override the matching keys in the Capacitor config while unmentioned keys survive; plugins present in only one of the two configs pass through unchanged. Everything outside `plugins` is untouched. The merge runs once at startup, before plugins receive their config.\n\n```typescript\nimport { defineConfig } from '@capawesome/capacitor-electron/config';\nimport packageJson from './package.json';\n\nexport default defineConfig({\n  plugins: {\n    LiveUpdate: {\n      defaultChannel: `production-${packageJson.version}`,\n    },\n  },\n});\n```\n\n> Importing `./package.json` requires `resolveJsonModule` in `electron/tsconfig.json` (already enabled in the scaffold).\n\n## Demo\n\nA working example can be found here: [capawesome-team/capacitor-electron](https://github.com/capawesome-team/capacitor-electron/tree/main/example)\n\n## Usage\n\n```bash\n# Copy web assets + regenerate the plugin manifest\nnpx cap sync @capawesome/capacitor-electron\n\n# Run the app (uses server.url for live reload when configured)\nnpx cap run @capawesome/capacitor-electron\n\n# Open the built app\nnpx cap open @capawesome/capacitor-electron\n```\n\n### Live Reload\n\nSet `server.url` in your Capacitor config to your dev server and run the app — the window loads the dev server with full HMR, and the plugin bridge works exactly as in production:\n\n```typescript\n// capacitor.config.ts\nconst config: CapacitorConfig = {\n  // ...\n  server: {\n    url: 'http://localhost:5173',\n  },\n};\n```\n\n```bash\nnpx vite &                                       # your web dev server\nnpx cap run @capawesome/capacitor-electron       # dev mode\n```\n\nIn dev mode a documented, dev-only CSP relaxation is applied (inline scripts, eval, websockets — required by HMR runtimes), and the window automatically reconnects when the dev server restarts. Remove `server.url` (or use a production config) to serve the built web assets from the app bundle again.\n\n### Deep Links\n\nDeclare the custom URL scheme in the platform configuration (see [Configuration](#configuration)) and listen to the standard `@capacitor/app` event:\n\n```typescript\nimport { App } from '@capacitor/app';\n\nawait App.addListener('appUrlOpen', ({ url }) => {\n  console.log('App opened with URL:', url);\n});\n```\n\nDeep links opened while the app is running are routed to the running instance (single instance is enforced by default); the URL that launched the app is available via `App.getLaunchUrl()`.\n\n### Splash Screen\n\nBooting a desktop app is not instant: the platform runs every plugin's `load()` lifecycle hook (e.g. the [Live Update](https://capawesome.io/plugins/live-update/) plugin verifying and activating a bundle) _before_ the main window is shown. A splash screen covers that gap so the app never appears frozen or blank.\n\nA splash screen is shown automatically when a splash file exists in the electron app directory — no configuration required. Two files are looked up, in order:\n\n1. `electron/assets/splash.html`\n2. `electron/assets/splash.png`\n\nThe scaffold ships a neutral, theme-aware `assets/splash.html` by default. Migrating from [`@capacitor-community/electron`](https://github.com/capacitor-community/electron)? Its `assets/splash.png` is picked up unchanged.\n\nConfigure the splash screen in `electron/capacitor.electron.config.ts`:\n\n```typescript\nimport { defineConfig } from '@capawesome/capacitor-electron/config';\n\nexport default defineConfig({\n  splashScreen: {\n    // Custom file, relative to the electron app directory. Either an `.html`\n    // file or an image (`.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`, `.webp`).\n    path: 'assets/splash.html',\n    width: 400,\n    height: 300,\n    backgroundColor: '#ffffff',\n    // Keep the splash visible for at least this long, even on fast startups.\n    minimumDurationMs: 0,\n  },\n});\n```\n\n| Option              | Type      | Default                                   | Description                                                                              |\n| ------------------- | --------- | ----------------------------------------- | ---------------------------------------------------------------------------------------- |\n| `enabled`           | `boolean` | shown when a splash file exists            | Set `false` to disable. Set `true` to require a splash file — boot fails if none is found. |\n| `path`              | `string`  | `assets/splash.html`, `assets/splash.png` | Splash file relative to the electron app directory.                                       |\n| `width`             | `number`  | `400`                                     | Window width in pixels.                                                                   |\n| `height`            | `number`  | `300`                                     | Window height in pixels.                                                                  |\n| `backgroundColor`   | `string`  | `'#ffffff'`                               | Window background and the canvas behind an image splash.                                  |\n| `minimumDurationMs` | `number`  | `0`                                       | Minimum time the splash stays visible.                                                    |\n\n**HTML vs. image:** an `.html` file is loaded directly, so you get full control over layout, fonts, and animation. An image is centered (`object-fit: contain`) on a `backgroundColor` canvas — convenient for a logo, but static.\n\nThe splash window is deliberately kept outside the plugin bridge: it is frameless, sandboxed, has no preload and no access to the app scheme, and navigation is blocked.\n\n> **Packaging note:** the splash files live under `assets/`, which is also the electron-builder `buildResources` directory. The scaffolded `electron-builder.config.js` includes `assets/**/*` in `files` so the splash ships inside the packaged app (`app.asar`). If you replace the config, keep that entry — otherwise the splash works in development but silently disappears from packaged binaries.\n\n### Debugging\n\nThe platform keeps Electron's default application menu, so the Chromium DevTools can be opened at any time via _View → Toggle Developer Tools_ or the keyboard shortcut:\n\n| Operating System | Shortcut                                          |\n| ---------------- | ------------------------------------------------- |\n| macOS            | <kbd>Cmd</kbd> + <kbd>Option</kbd> + <kbd>I</kbd> |\n| Windows          | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>I</kbd> |\n| Linux            | <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>I</kbd> |\n\nTo open the DevTools automatically on launch (e.g. to catch logs from early app startup), use the `onWindowCreated` hook in `electron/capacitor.electron.config.ts`:\n\n```typescript\nimport { defineConfig } from '@capawesome/capacitor-electron/config';\n\nexport default defineConfig({\n  // ...\n  hooks: {\n    onWindowCreated: window => {\n      window.webContents.openDevTools();\n    },\n  },\n});\n```\n\n### Tray Icon\n\nUse the `onWindowCreated` hook together with Electron's [`Tray`](https://www.electronjs.org/docs/latest/api/tray) and [`Menu`](https://www.electronjs.org/docs/latest/api/menu) APIs to add a tray icon and context menu:\n\n```typescript\nimport { defineConfig } from '@capawesome/capacitor-electron/config';\nimport { app, Menu, Tray } from 'electron';\nimport { join } from 'path';\n\nexport default defineConfig({\n  // ...\n  hooks: {\n    onWindowCreated: window => {\n      const tray = new Tray(join(app.getAppPath(), 'assets', 'tray-icon.png'));\n      tray.setContextMenu(\n        Menu.buildFromTemplate([\n          { label: 'Show', click: () => window.show() },\n          { label: 'Hide', click: () => window.hide() },\n          { type: 'separator' },\n          { label: 'Quit', click: () => app.quit() },\n        ]),\n      );\n    },\n  },\n});\n```\n\nPlace the tray icon under `electron/assets/`, which already ships inside the packaged app (see the [Splash Screen](#splash-screen) packaging note). To start the app minimized to the tray, set [`window.showOnLaunch: false`](#configuration) so the main window is created hidden until the user picks _Show_.\n\n> **Migrating from [`@capacitor-community/electron`](https://github.com/capacitor-community/electron)?** This recipe replaces its `trayIconAndMenuEnabled` and `hideMainWindowOnLaunch` options — build the tray via the hook above and use `window.showOnLaunch: false` for start-in-tray behavior.\n\n## Migration\n\nYou can use our **AI-Assisted Migration** to migrate from [`@capacitor-community/electron`](https://github.com/capacitor-community/electron).\nAdd the [Capawesome Skills](https://github.com/capawesome-team/skills) to your AI tool using the following command:\n\n```bash\nnpx skills add capawesome-team/skills --skill capacitor-platforms\n```\n\nThen use the following prompt:\n\n```\nUse the `capacitor-platforms` skill from `capawesome-team/skills` to migrate my project from `@capacitor-community/electron` to `@capawesome/capacitor-electron`.\n```\n\nIf you prefer **Manual Migration**, perform the following steps:\n\n1. Back up anything you customized in your existing `electron/` directory (icons, electron-builder configuration, and any code you added to the generated runtime files).\n2. Remove the old platform and its `electron/` directory:\n   ```bash\n   npm uninstall @capacitor-community/electron\n   rm -rf electron\n   ```\n3. Add this platform:\n   ```bash\n   npm install @capawesome/capacitor-electron\n   npx cap add @capawesome/capacitor-electron\n   cd electron && npm install && cd ..\n   ```\n4. Re-apply your customizations through the typed options in `electron/capacitor.electron.config.ts` (window options, deep-link scheme, CSP overrides, tray/menu via hooks) instead of editing runtime code, and restore your icons to `electron/assets/` and your electron-builder settings in `electron/electron-builder.config.js`.\n5. Sync and run (always with the full package name):\n   ```bash\n   npx cap sync @capawesome/capacitor-electron\n   npx cap run @capawesome/capacitor-electron\n   ```\n\nNotes:\n\n- Deep links no longer require hand-written runtime code — declare the scheme in the platform config and listen to `@capacitor/app`'s `appUrlOpen` event.\n- Splash screens are picked up automatically from `electron/assets/`. Keep `assets/splash.png` and it just works; if you used a custom `splashScreenImageName: 'x.gif'`, either rename it to `assets/splash.png` or point the config at it via `splashScreen: { path: 'assets/x.gif' }` (see [Splash Screen](#splash-screen)).\n- Plugins must provide an electron implementation for this platform's contract (see [Plugin Development](#plugin-development)); implementations written for the old platform are not loaded. Plugins whose web implementation is sufficient continue to work unchanged via the automatic fallback.\n\n## Plugin Development\n\nPlugins declare their electron implementation via `package.json`:\n\n```json\n{\n  \"capacitor\": {\n    \"electron\": { \"src\": \"electron\" }\n  }\n}\n```\n\nThe implementation is an ES module at `<src>/dist/plugin.mjs` exporting plugin classes. A plugin class declares its Capacitor registration name and its public API via static metadata — the static property is the contract, so a build-time dependency on this package is not required.\n\n### Recommended: extend `ElectronPlugin`\n\nMirroring how Android/iOS plugins extend Capacitor's `Plugin` and override `load()`, the recommended path is to extend the `ElectronPlugin` base class. Add `@capawesome/capacitor-electron` as a **devDependency** (for the types) and an **optional peerDependency** (for the runtime value), then:\n\n```ts\nimport { ElectronPlugin, defineElectronPlugin } from '@capawesome/capacitor-electron/plugin';\n\nclass SqliteImpl extends ElectronPlugin {\n  // `this.context` (config, services, notifyListeners) is stored by the base constructor.\n\n  // Optional lifecycle hook. Awaited by the platform before the first window loads.\n  async load() { ... }\n\n  async open(options) { ... }\n  async query(options) { ... }\n\n  // Not declared below, therefore never bridged.\n  resolvePath(path) { ... }\n}\n\nexport const Sqlite = defineElectronPlugin(\n  { name: 'Sqlite', methods: ['open', 'query'] },\n  SqliteImpl,\n);\n```\n\n### Zero-dependency: marker-only\n\nThe base class is optional sugar — the discovery contract is the static `__capacitorElectronPlugin` metadata, and the lifecycle hook is detected structurally (never via `instanceof`, which would break across duplicated copies of this package). So a plugin can ship with **no dependency on this package at all**, implementing a structural `load()` if it needs the hook:\n\n```ts\nclass SqliteImpl {\n  constructor({ config, services, notifyListeners }) { ... }\n\n  // Optional. Structural lifecycle hook, detected by name.\n  async load() { ... }\n\n  async open(options) { ... }\n  async query(options) { ... }\n\n  // Not declared below, therefore never bridged.\n  resolvePath(path) { ... }\n}\n\n// Equivalent to defineElectronPlugin, without importing this package.\nSqliteImpl.__capacitorElectronPlugin = {\n  name: 'Sqlite',\n  methods: ['open', 'query'],\n};\n\nexport { SqliteImpl as Sqlite };\n```\n\nThe declared `methods` array is the plugin's entire bridged surface: anything not listed stays main-process-internal, and a declared method that is missing on the class fails loudly at boot. Each class is instantiated once in the main process (full Node and Electron API access) and exposed under its registration name through Capacitor's native plugin path — `registerPlugin('Sqlite', { web: ... })` just works, with the web implementation as the automatic fallback for platforms the plugin doesn't cover. No `electron` key in the plugin's `registerPlugin` wiring is needed.\n\nThe constructor context (`this.context` on an `ElectronPlugin` subclass, or the constructor argument otherwise) provides:\n\n- `config` — the app's Capacitor configuration.\n- `notifyListeners(eventName, data)` — emits a plugin event, mirroring Capacitor's native `notifyListeners`. Web listeners use the standard `addListener(eventName, callback)` / `PluginListenerHandle` API.\n- `services` — platform primitives (currently `services.bundles`: web-bundle serving, reload, and the failed-boot rollback watchdog).\n\n### The `load()` lifecycle hook\n\n`load()` runs once after the plugin is constructed and is **awaited before the first application window loads**, so async setup — including repointing the active bundle via `services.bundles.setActiveBundle()` — takes effect on first paint (no default-bundle flash). It is a lifecycle hook, **not** a bridged method: `load` is reserved and is never bridged to the renderer. It must **not** be listed in `methods` — doing so is rejected at boot, because bridging it would let web content invoke the lifecycle hook arbitrarily. A rejected or thrown `load()` fails the app boot loudly, the same way a declared-but-missing method does. On an `ElectronPlugin` subclass the default `load()` is a no-op, so overriding it is optional.\n\nAt sync time the platform statically scans the app's dependencies and generates a plugin manifest — no plugin code runs outside Electron. Results, thrown `Error`s, and their `code` properties cross the bridge with Capacitor semantics.\n\n## Packaging\n\nThe scaffolded `electron/` project packages with electron-builder:\n\n```bash\ncd electron && npm run pack\n```\n\nThe `pack` script runs three steps: compile (`tsc`), **vendor**, and `electron-builder`. The vendor step (`capacitor-electron vendor`) copies the platform runtime, every plugin's electron implementation, and their dependency closure (production, peer, and installed optional dependencies) into `electron/vendor/`, which the scaffolded electron-builder config maps to `node_modules` inside the packaged app — so module resolution works identically in development (from your app root) and in the package, without a second `npm install` and without version drift.\n\nCode signing, notarization, targets (dmg/msi/nsis/AppImage/deb), and icons are standard electron-builder configuration in the user-owned `electron-builder.config.js` — see https://www.electron.build. Electron Forge is a supported alternative: run `capacitor-electron vendor` before packaging and include `vendor/node_modules` as the app's `node_modules`.\n\n### App Updates\n\nTwo independent update layers, matching mobile:\n\n- **Binary updates** (Electron itself, the runtime, native modules): use [electron-updater](https://www.electron.build/auto-update) — the desktop analog of an app-store update. Wire it in your `main.ts`; it operates on the packaged artifacts produced above.\n- **Web-bundle updates**: the platform ships the serving primitive only — `services.bundles` (activate a bundle directory, reload, boot-ready signal, and a failed-boot rollback watchdog that reverts to the previous bundle if the renderer doesn't confirm startup). The OTA update product on top of it (download, channels, verification) is deliberately not part of the platform.\n\n## Electron Support Policy\n\n- **Floor**: Electron 28 (required for the runtime's serving APIs). No ceiling — the scaffold uses a caret range you control, and the platform releases only when Electron actually breaks an API it uses.\n- **Tested**: CI runs the example app against the latest stable Electron and the floor on every release.\n- Electron ships a new major roughly every 8 weeks. This platform's wide peer range means you can adopt new Electron majors immediately, without waiting for a platform release.\n\n## Limitations\n\nRead this before committing to the platform — these are inherent trade-offs, not bugs:\n\n- **Binary size and memory.** Every app ships its own Chromium and Node: expect roughly 80–150 MB installed and a matching memory footprint. If minimal footprint is the priority, Electron is the wrong tool.\n- **Plugins need an electron implementation.** Only Capacitor plugins that ship an `electron` implementation (or whose web implementation is sufficient — the automatic fallback) work. iOS/Android native code does not translate.\n- **Native Node addons are not rebuilt automatically.** If a plugin's electron implementation depends on native Node modules, `capacitor-electron vendor` detects and reports them, but you must rebuild them against Electron's ABI yourself (e.g. `@electron/rebuild`) before packaging.\n- **No web-bundle OTA product included.** The platform provides the serving primitive (`services.bundles`) only; update delivery, channels, and verification are a separate product layer.\n- **Always pass the platform name to the Capacitor CLI.** A bare `npx cap sync` only processes iOS/Android/web; `npx cap sync electron` resolves to the `electron` npm package and silently does nothing. Use the full package name (see the note under Installation).\n- **Desktop is not mobile.** APIs like geolocation permission prompts, status bars, or app-store review flows have no desktop equivalent; plugins whose web implementation assumes a mobile browser may behave differently on desktop Chromium.\n\n## FAQ\n\n### Can I use any Capacitor plugin with this platform?\n\nPlugins with a dedicated Electron implementation or a sufficient web implementation work (see [Supported Plugins](#supported-plugins)). Plugins that only ship iOS/Android native code do not.\n\n### How do I update Electron in my app?\n\nUpdate the `electron` version in `electron/package.json` and run `npm install` there. The platform supports Electron 28 and later with no upper bound.\n\n### Does `Capacitor.getPlatform()` return `electron`?\n\nYes. `Capacitor.getPlatform()` returns `'electron'` and `Capacitor.isNativePlatform()` returns `true`, so you can branch platform-specific code the same way as on iOS and Android.\n\n## Related Plugins\n\n- [Capacitor SQLite plugin](https://capawesome.io/docs/sdks/capacitor/sqlite/) — local SQL database with a native Electron implementation.\n\n## Newsletter\n\nStay up to date with the latest news and updates about the Capawesome, Capacitor, and Ionic ecosystem by subscribing to our [Capawesome Newsletter](https://capawesome.io/newsletter/).\n\n## Changelog\n\nSee [CHANGELOG.md](https://github.com/capawesome-team/capacitor-electron/blob/main/CHANGELOG.md).\n\n## License\n\nSee [LICENSE](https://github.com/capawesome-team/capacitor-electron/blob/main/LICENSE).\n\n[^1]: This project is not affiliated with, endorsed by, sponsored by, or approved by the OpenJS Foundation or any of its affiliates. `Electron` is a trademark of the OpenJS Foundation.\n","readmeFilename":"README.md"}