Electron on the App Store, Ship it.
Tags: electron, javascript, appstore, menubar
Published: 2021-02-09 21:40:51

This article is part of a 5 articles series about the publication of an Electron application into the Mac AppStore, [Fenêtre](https://fenêt.re).

> [Fenêtre,](https://fenêt.re/) `fənɛtʁ`, lets you better multitask on your mac. It enables a [picture-in-picture](https://en.wikipedia.org/wiki/Picture-in-picture) mode for any website/web-app, image, video or flat file.
> You can find the [free version](https://itunes.apple.com/us/app/fen%C3%AAtre-lite/id1288451627)and the [paid version](https://itunes.apple.com/us/app/fen%C3%AAtre/id1286743037) on the Mac App-Store.

---

This is the last mile, and also where I almost lost it. By far the most painful part of the whole project.

Working with Electron, you won't publish, sign or handle entitlements from XCode, and Apple seems to make it even harder for you since you're not using their proprietary software. The documentation is cryptic, to say the least, and the support is yet to be found.

What helped me a lot was the [WebTorrent for desktop repo,](https://github.com/webtorrent/webtorrent-desktop) especially their [packaging script](https://github.com/webtorrent/webtorrent-desktop/blob/master/bin/package.js), so, a **very big thank you** to the team there ❤️, your project saved my sanity, for real 🙏.

Following their great example I've been successfully using [electron-packager](https://github.com/electron-userland/electron-packager) and [electron-osx-sign](https://github.com/electron-userland/electron-osx-sign) which are must-have packages to ship your product to the AppStore without XCode.

# Certificates & stuffs

First of all, you'll need 3 different **certificates** from [your developer account](https://developer.apple.com/account/mac/certificate/).

* **Mac development**, so you can test your signed packaged app before sending it to Apple.
* **Mac AppStore → Mac App Distribution**, so you can sign your app and all executable inside it.
* **Mac AppStore → Mac Installer Distribution**, so you can sign the package of your app, which is the format you'll send to the AppStore.

Simply download them, double-click and they will be installed in your keychain. That's it, you won't have to deal with these anymore until they expire.

Then you'll need to create [an App ID](https://developer.apple.com/account/mac/identifier/bundle) for your app (one for each version, free and pro), and finally, two [provisioning profiles](https://developer.apple.com/account/mac/profile/) each, one for development and one for distribution.

Now you're ready to sign your app.

# Entitlements.plist

Using [plist.js](https://github.com/TooTallNate/plist.js) you can create your two entitlement files needed, `parent.plist` and `child.plist`. I like doing it in the packaging script, so I don't end up with multiple files I'll never edit.

The parent will need `com.apple.security.sand-box` at `true`, because your app _has_to be sand-boxed before being submitted to the AppStore. And `com.apple.application-identifier` and `com.apple.developer.team-identifier` to identify your app.

Add any [other needed entitlements](https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html) depending on what your application does.

As an example, for [Fenêtre](https://fenêt.re) I'm also using:

* `com.apple.security.network.client` since we're connecting to the internet when displaying a website or any URL in Fenêtre.
* `com.apple.security.network.server` for the browser extension, so it can send URLs to open. It's also used when encoding/decoding unsupported video formats.
* `com.apple.security.files.user-selected.read-write` for the user to drag-n drop files into the app.

In the `child.plist` it's quite easier, you just need `com.apple.security.sand-box` and `com.apple.security.inherit` at `true`. That's it, that's all, output those file somewhere temporary, we'll use them later during the signature process.

# Signature

Now to the big tricky part, the signing of the app. Fortunately for us [electron-osx-sign](https://github.com/electron-userland/electron-osx-sign) has done most of the hard part. Here's a snippet of my **production** signature script:

{% gist https://gist.github.com/yoannmoinet/347e43a257fdc6f199ad453759eb1460 %}

> Signature script for production.

The only two arguments needed, `appPath` and `pkgPath` , are the `.app`'s absolute path we've created with [electron-packager](https://github.com/electron-userland/electron-packager) and the absolute path of where we're outputting the `.pkg`.

Note the `PARENT_PLIST_PATH` and `CHILD_PLIST_PATH` that we also created earlier. And the two different identities we're using, one for the application itself, and another one for the `.pkg` we're generating. And the `platform` is `mas` for 'Mac AppStore'.

Now this package won't be testable on your machine, not even the signed app. Instead, you'll have to use another sign script for being able to test your sand-boxed application:

{% gist https://gist.github.com/yoannmoinet/5f9af7813449110bedeec7aaee294773 %}
> Signature script for development.

Note that we don't need the generation of the `.pkg` anymore, since we won't test it. Also, the `type` changes to `development`, and the identity is now the `Mac Developer` one. As well as the `DEV_PROVISIONING_PROFILE`.

# Debug your sandboxed Application

You now have the exact same app as the one that will be shipped to Apple. So you can test the sand-boxing, which is _very_ important and _very_ likely to crash.

Be sure that everything works in this state, or it will be rejected by Apple right away. You can use the very useful [RB App Checker Lite](https://itunes.apple.com/fr/app/rb-app-checker-lite/id519421117?mt=12) as well, to test the entitlements and the signature of your app.

There's still this ' _The profile does NOT match the application's Team ID_' I can't get rid of. But apparently, [this is not a big deal](https://github.com/electron-userland/electron-osx-sign/issues/149) ¯\\_(ツ)_/¯.

If you need to see the output of your main process, get into the package contents of your generated `.app` and open the file located at `MyApp.app/Contents/MacOS/MyApp`, it will open a terminal window with the output of your main process.

To inspect the renderer process, simply spawn the web inspector from your `BrowserWindow`'s options with the help of our global `IS_PRODUCTION`:

{% gist https://gist.github.com/yoannmoinet/3646642a8fe92b5c3aedaf605160da7d %}

---

Now that you're all set, you can use the Application Loader to upload your `Application.pkg` to your [iTunes Connect](https://itunesconnect.apple.com/) account.

It's hidden in `XCode > Open Developer Tool > Application Loader`. Just open it once, and pin it to your dock, so you don't have to launch XCode each time you need to upload your app, which will happen a lot.

Then from iTunes Connect you'll be able to select your latest build for the next release.

Wait for the review to happen... update your app, and back to the start, until it's validated and pushed to the AppStore.

---

Now that we have our package uploaded and published, we're ready to [Go to market](https://dev.to/yoannmoinet/electron-on-the-app-store-go-to-market-3m1k).