Create lightweight desktop application that can open custom protocol links
(similar to iTunes
itmss:// or Slack
slack:// application links).
Note that it is simple to register an Electron application to handle internal custom protocol links which are in the page an Electron application is rendering. It is harder to register an Electron application to handle custom protocol links clicked in other applications. For this we will need to create an installer.
If you want to try the application, clone the repository, install its dependencies and run the start script
git clone [email protected]:bahmutov/todomvc-electron-test.git
Here is a screenshot of the application in action.
Note that the loaded Electron application has almost NO logic. Instead it loads https://todomvc-express.bahmutov.com/, which is server side rendering TODO MVC application (available at bahmutov/todomvc-express).
For the demo purposes, the application opens the DevTools panel on startup. I also added a small log function that sends the messages to the panel. This comes very handy when the application will be packaged to run without terminal and need to debug the events.
// prints given message both in the terminal console and in the DevTools
The external website bahmutov/todomvc-express includes two links with custom protocol.
<p>custom todo protocol link <a href="todo2://active">active</a>,
When this page is opened in our Electron application, and the user clicks
on a link
<a href="todo2://completed">completed</a>, we want
to catch this click and open the actual page
https://todomvc-express.bahmutov.com/completed. We can achieve this by
registering custom protocol handler inside the Electron
after the main window has been created
const electron = require('electron')
You can see the results right away by clicking on
links which lead to same pages as
In order to register our new Electron application as the handler for custom
protocol links, we need to make an installer that would register it.
I will use the project electron-builder
to package the Electron app. First, let us create "DMG" installer. The
settings will be in the "build" config object inside the
Notice the "protocols" object that registers both "todo2://" and "todos2://" custom protocols. While unnecessary, this shows how to register multiple custom protocols for one application.
Create the "DMG" file using
npm run dist command. This creates
todo-<version>.dmg file, that you can execute. Once you drag the application
into "Applications" folder, it will become the handler for the custom protocol.
Opening the custom link
todo2://, either by clicking inside a browser,
or by simply
open todo2://... from the terminal opens the Todo application.
Clicking on the custom link the browser brings a dialog prompting the user to "Launch the application".
Making a Windows installer
To build a Windows installer, let us add a new script command "win" and
Windows build settings. In order to install custom protocols, I had to use
NSIS installer with
perMachine: true option.
I also added protocol registration as a separate installer script
Running the command downloads the Windows Electron application, but complains
because Wine is not found. Install Wine
and open the Wine terminal. Then run
npm run win command again and it built
Making installers on CI
I tried making installers on CI using GitLab docker build. Here my sample
.gitlab-ci.yml file. First it runs the tests (mostly just a JS linter),
then it tries to build an installer. There are some dependencies that
need to be installed for Linux environment, see
Instead of installing dependencies in each test job, I recommend using
a special Docker image with all necessary dependencies pre-installed.
Unfortunately building signed DMG installer for Mac OS requires a Mac machine according to this.
- If you get "spawn icns2png ENOENT" ... - install Linux dependencies
- If you get "spawn gtar ENOENT" on Mac, you will need to install
brew install gnu-tar
- If you get "missing WINE" error, open WINE shell and run the build command.
- If you see Error: spawn mono ENOENT
then you need to install Mono,
for example using
brew install mono