Electron Node.js version support
Electron upgrades its main branch to even-number versions of Node.js when they enter Active LTS. Stable release lines receive minor and patch bumps of Node.js after they are released. Patch bumps to Node.js appear in Electron patch releases, while minor bumps to Node.js result in Electron minor releases. Security-only branches receive only security-related changes from Node.js.
Electron Chromium version targeting
Electron targets even-number versions of Chromium and releases every 8 weeks in concert with Chromium's 4-week release schedule. For example, Electron 26 uses Chromium 116, while Electron 27 uses Chromium 118.
Electron version support policy
Electron supports the latest three stable major versions. Only the latest minor release within each supported major version series receives updates. The latest stable release receives all fixes from main, the previous version receives the vast majority of fixes, and the oldest supported version receives only security fixes.
Electron release phase stability notes
Alpha releases are generally less stable than beta releases. The cutoff between alpha and beta corresponds to when the underlying Chromium version enters Chrome's Beta channel. Solid release dates are the -alpha.1, -beta.1, and stable dates. Weekly alpha and beta releases are aimed for but more frequent releases often occur. All dates are goals but the stable deadline may be adjusted for reasons such as security bugs.
Electron breaking API change support window
When an API is changed or removed in a breaking way, the previous functionality is supported for a minimum of two major versions before removal when possible. For example, if a function parameter is reduced in major version 10, the old version continues working until at minimum major version 12. Beyond two versions, Electron maintainers may continue backward compatibility support depending on maintenance burden.
Electron major version release cadence
Electron releases major versions on an 8-week cadence, releasing every other Chromium major version. Before each major version reaches stable, it goes through a 4-week alpha phase followed by a 4-week beta phase, for a total of 8 weeks from alpha start to stable release.
Initiate purchase with purchaseProduct
Call inAppPurchase.purchaseProduct(productIdentifier, quantity) to initiate a purchase. This method takes a product identifier string and quantity number, returning a promise that resolves to a boolean indicating whether the product is valid.
Get receipt URL from inAppPurchase.getReceiptURL
After a successful purchase, retrieve the receipt URL by calling inAppPurchase.getReceiptURL(). This URL points to the receipt file that should be submitted to your server for validation according to Apple's receipt validation guidelines.
In-app purchase workflow example
The following is a complete example of in-app purchases in Electron:
```js
// Main process
const { inAppPurchase } = require('electron')
const PRODUCT_IDS = ['id1', 'id2']
// Listen for transactions as soon as possible.
inAppPurchase.on('transactions-updated', (event, transactions) => {
if (!Array.isArray(transactions)) {
return
}
// Check each transaction.
for (const transaction of transactions) {
const payment = transaction.payment
switch (transaction.transactionState) {
case 'purchasing':
console.log(`Purchasing ${payment.productIdentifier}...`)
break
case 'purchased': {
console.log(`${payment.productIdentifier} purchased.`)
// Get the receipt url.
const receiptURL = inAppPurchase.getReceiptURL()
console.log(`Receipt URL: ${receiptURL}`)
// Submit the receipt file to the server and check if it is valid.
// @see https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html
// ...
// If the receipt is valid, the product is purchased
// ...
// Finish the transaction.
inAppPurchase.finishTransactionByDate(transaction.transactionDate)
break
}
case 'failed':
console.log(`Failed to purchase ${payment.productIdentifier}.`)
// Finish the transaction.
inAppPurchase.finishTransactionByDate(transaction.transactionDate)
break
case 'restored':
console.log(`The purchase of ${payment.productIdentifier} has been restored.`)
break
case 'deferred':
console.log(`The purchase of ${payment.productIdentifier} has been deferred.`)
break
default:
break
}
}
})
// Check if the user is allowed to make in-app purchase.
if (!inAppPurchase.canMakePayments()) {
console.log('The user is not allowed to make in-app purchase.')
}
// Retrieve and display the product descriptions.
inAppPurchase.getProducts(PRODUCT_IDS).then(products => {
// Check the parameters.
if (!Array.isArray(products) || products.length <= 0) {
console.log('Unable to retrieve the product information.')
return
}
// Display the name and price of each product.
for (const product of products) {
console.log(`The price of ${product.localizedTitle} is ${product.formattedPrice}.`)
}
// Ask the user which product they want to purchase.
const selectedProduct = products[0]
const selectedQuantity = 1
// Purchase the selected product.
inAppPurchase.purchaseProduct(selectedProduct.productIdentifier, selectedQuantity).then(isProductValid => {
if (!isProductValid) {
console.log('The product is not valid.')
return
}
console.log('The payment has been added to the payment queue.')
})
})
```
CFBundleIdentifier must be changed for In-App Purchase testing
To test In-App Purchase in development with Electron, you must change the CFBundleIdentifier in node_modules/electron/dist/Electron.app/Contents/Info.plist. Replace com.github.electron with the bundle identifier of the application you created with iTunes Connect. The CFBundleIdentifier key should point to your application's bundle identifier, such as com.example.app.
Listen for transactions-updated event as soon as possible
The transactions-updated event must be listened to as soon as possible in your Electron app. This event is emitted when in-app purchase transactions are updated and provides an array of transaction objects to process.
Transaction states in in-app purchases
In-app purchase transactions can have the following states: purchasing (transaction is being processed), purchased (transaction completed successfully), failed (transaction failed), restored (purchase has been restored), and deferred (purchase has been deferred).
finishTransactionByDate must be called after purchase completion
After processing a purchased or failed transaction, call inAppPurchase.finishTransactionByDate(transaction.transactionDate) to finish the transaction. This must be done for both successful purchases and failed attempts.
Check user payment capability with canMakePayments
Before attempting to process in-app purchases, check if the user is allowed to make payments by calling inAppPurchase.canMakePayments(). This returns a boolean indicating whether the user can make in-app purchases.
Retrieve product information with getProducts
Call inAppPurchase.getProducts(productIds) to retrieve product information. This method takes an array of product identifier strings and returns a promise that resolves with an array of product objects containing properties like localizedTitle and formattedPrice.
Submit app for review after uploading
After uploading your app to App Store Connect with Apple Transporter, you should submit your app for review.
Check for private API usage if upload fails
If you see errors about private API usage when uploading to Mac App Store, check that the app is using the MAS build of Electron.
Upload to Mac App Store using Apple Transporter
After signing the app with the Apple Distribution certificate, use Apple Transporter to upload the signed app to App Store Connect for processing. Make sure you have created a record before uploading.
Custom update server requirement for private repositories
If using an alternate repository host (GitLab or Bitbucket) or if the code repository needs to be kept private, deploy your own Electron update server and configure the autoUpdater module yourself instead of using update.electronjs.org.
update.electronjs.org free auto-update service requirements
The Electron maintainers provide a free auto-updating service for open-source apps at https://update.electronjs.org. Requirements are: the app runs on macOS or Windows, the app has a public GitHub repository, builds are published to GitHub releases, and builds are code signed (macOS only).
GitHub Publisher plugin installation
Electron Forge's GitHub Publisher is a plugin that needs to be installed in a project's devDependencies with the command: npm install --save-dev @electron-forge/publisher-github
GitHub Publisher configuration in forge.config.js
The GitHub Publisher is configured in forge.config.js under the publishers array. The configuration object has a name field set to '@electron-forge/publisher-github' and a config field containing repository (with owner and name fields), prerelease (boolean), and draft (boolean) settings. Example: { name: '@electron-forge/publisher-github', config: { repository: { owner: 'github-user-name', name: 'github-repo-name' }, prerelease: false, draft: true } }
GitHub Publisher authentication token setup
The GitHub Publisher requires a personal access token (PAT) with the 'public_repo' scope to authenticate with GitHub. By default, the publisher uses the value stored in the GITHUB_TOKEN environment variable. The PAT should be kept secret.
Publishing releases as drafts before distributing
Setting the draft property to true in the GitHub Publisher config will publish the release as a draft. This allows viewing the release with generated artifacts without publishing to end users, enabling manual review and verification of distributables via GitHub before publishing.
electron-forge publish command in npm scripts
Add 'publish': 'electron-forge publish' to the scripts object in package.json. Running npm run publish will run configured makers and publish the output distributables to a new GitHub release.
Publishing for different architectures with --arch flag
By default, electron-forge publish only publishes a single distributable for the host operating system and architecture. Publishing for different architectures requires passing the --arch flag to Forge commands.
GitHub release name corresponds to package.json version
The name of a GitHub release created by electron-forge publish corresponds to the version field in the project's package.json file.
update.electronjs.org update check endpoint format
The update.electronjs.org service provides an updater-compatible feed. The endpoint URL format is https://update.electronjs.org/{owner}/{repo}/{platform}/{version}. For example, Electron Fiddle v0.28.0 checks https://update.electronjs.org/electron/fiddle/darwin/v0.28.0 to see if a newer GitHub release is available.
update-electron-app repository field detection
The update-electron-app module will search for the update.electronjs.org feed that matches the project's package.json 'repository' field automatically.
update-electron-app module for autoUpdater setup
The Electron team maintains the update-electron-app module, which sets up the autoUpdater boilerplate for update.electronjs.org in one function call with no configuration required. Install with: npm install update-electron-app. Import and call it immediately in the main process with: require('update-electron-app')()
Publishing releases with GitHub Actions for cross-platform builds
Publishing locally is limited because distributables can only be created for the host operating system. GitHub Actions can run tasks in the cloud on Ubuntu, macOS, and Windows, allowing publishing Windows .exe files from macOS or Linux and other cross-platform build scenarios.
Custom Squirrel-compatible update server
For advanced deployment needs, you can roll out your own Squirrel-compatible update server. This allows percentage-based rollouts, separate release channels, or putting the update server behind authentication checks.
Check for packaged environment before auto-update
Ensure autoUpdater code only executes in the packaged app, not in development. Use the app.isPackaged API to check the environment before setting up update checking.
autoUpdater module for update distribution
Electron's autoUpdater module is the officially supported way to provide automatic updates to Electron applications. It works with the Squirrel framework.
Cloud object storage serverless updates
Electron's autoUpdater can check for updates by pointing to a static storage URL containing latest release metadata. A new release's metadata must be published to cloud storage alongside the release itself.
macOS release metadata format
On macOS, Squirrel.Mac receives updates by reading a releases.json file. The file contains a currentRelease field with the latest version string, and a releases array where each object has a version field and an updateTo object. The updateTo object must contain: version (string), pub_date (ISO 8601 timestamp), notes (string), name (string), and url (string pointing to the release package).
Windows release metadata format
On Windows, Squirrel.Windows receives updates by reading from a RELEASES file generated during the build process. The RELEASES file is plaintext where each line contains: a SHA1 hash, a URL to the .nupkg delta package, and the package size in bytes, separated by spaces.
Release metadata directory structure
Release metadata files should be organized in a folder structure that is aware of the app's platform and architecture. For example: my-app-updates/darwin/x64/, my-app-updates/darwin/arm64/, and my-app-updates/win32/x64/. Each platform/arch directory contains the release packages and a RELEASES or RELEASES.json metadata file.
update-electron-app module drop-in setup
update-electron-app is a Node.js module that sets up autoUpdater and prompts the user with a native dialog for updates. For static storage updates, pass the updateSource.baseUrl parameter pointing to the directory containing release metadata files.
Static storage update configuration example
To use static storage updates with update-electron-app, configure it with: updateElectronApp({ updateSource: { type: UpdateSourceType.StaticStorage, baseUrl: `https://my-bucket.s3.amazonaws.com/my-app-updates/${process.platform}/${process.arch}` } })
update.electronjs.org free service
The Electron team maintains update.electronjs.org, a free and open-source webservice for Electron app self-updates. The service is designed for apps that: run on macOS or Windows, have a public GitHub repository, publish builds to GitHub Releases, and are code-signed (macOS only).
update-electron-app default behavior
When installed and invoked as require('update-electron-app')(), the module checks for updates at app startup, then every ten minutes. When an update is found, it automatically downloads in the background. When the download completes, a dialog displays allowing the user to restart the app.
Custom update server setup
For private Electron applications or those not publishing to GitHub Releases, you can run your own update server. Available open-source options include: Hazel (free deployment on Vercel, pulls from GitHub Releases), Nuts (uses GitHub Releases with caching), electron-release-server (dashboard for releases, no GitHub requirement), and Nucleus (maintained by Atlassian, supports multiple apps and channels).
Custom update server feed URL construction
When using a custom update server, construct the feed URL as: const url = `${server}/update/${process.platform}/${app.getVersion()}`. Then pass it to autoUpdater.setFeedURL({ url }).
autoUpdater update checking interval
To check for updates periodically, use setInterval(() => { autoUpdater.checkForUpdates() }, 60000) to check every minute, or adjust the interval as needed.
Handle update-downloaded event
Listen to the autoUpdater 'update-downloaded' event to notify users when an update is ready. The event provides releaseNotes and releaseName parameters. Call autoUpdater.quitAndInstall() when the user confirms the restart.
Update downloaded notification example
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => { const dialogOpts = { type: 'info', buttons: ['Restart', 'Later'], title: 'Application Update', message: process.platform === 'win32' ? releaseNotes : releaseName, detail: 'A new version has been downloaded. Restart the application to apply the updates.' }; dialog.showMessageBox(dialogOpts).then((returnValue) => { if (returnValue.response === 0) autoUpdater.quitAndInstall() }) })
Handle autoUpdater errors
Listen to the autoUpdater 'error' event to handle update failures. Log errors to stderr or your logging system.
Manual update loading from local directory
The autoUpdater url field supports the file:// protocol, allowing you to load updates from a local directory. This bypasses server communication for situations where the update server is behind authentication or difficult to handle.
Windows Squirrel.Windows RELEASES endpoint
A Squirrel.Windows client expects the update server to return the RELEASES artifact at the /RELEASES subpath of the feed URL endpoint. For example, if the feed URL is https://your-deployment-url.com/update/win32/1.2.3, then https://your-deployment-url.com/update/win32/1.2.3/RELEASES should return the contents of the latest RELEASES file. The server should return a response even when no update is available.
Windows RELEASES response format example
A RELEASES response should be formatted as: B0892F3C7AC91D72A6271FF36905FEF8FE993520 https://your-static.storage/your-app-1.2.3-full.nupkg 103298365, where the first field is the SHA1 hash, the second is the full URL to the .nupkg package, and the third is the package size in bytes.
macOS Squirrel.Mac JSON response format
When an update is available, Squirrel.Mac expects a JSON response at the feed URL endpoint. The object must have a mandatory url property (string) pointing to a ZIP archive of the app update. Optional properties are: name (string), notes (string), and pub_date (ISO 8601 timestamp).
macOS Squirrel.Mac response example
A macOS update response should be formatted as: { "url": "https://your-static.storage/your-app-1.2.3-darwin.zip", "name": "1.2.3", "notes": "These are some release notes innit", "pub_date": "2024-09-18T12:29:53+01:00" }
macOS no update available response
When no update is available for macOS, the Squirrel.Mac server should return a 204 No Content HTTP response.
Electron Forge auto-update configuration for S3
Electron Forge can set up static file storage updates by configuring: macUpdateManifestBaseUrl in the ZIP Maker (macOS) and remoteReleases in the Squirrel.Windows Maker (Windows). Forge provides an Auto updating from S3 guide for end-to-end examples.
Windows Store AppX manual verification requirement
Packaged Electron apps in AppX format currently require manual verification before Windows Store submission. Developers can apply for verification through the Centennial Campaigns program. During the verification process, users can still install the package manually by double-clicking it, making Store submission optional if easier installation methods are the goal.