Building a Cross-Platform Desktop Notification Application with Electron
Introducing Electron
Node.js is an open source cross-platform runtime environment for developing server-side web applications using JavaScript. It uses Google’s V8 engine to interpret JavaScript. Nowadays, it’s very commonly used for tooling purposes on a normal software development cycle. For example, most of the client-side JavaScript frameworks use Node.js to automate various development processes such as build, minify JavaScript, compile source code, and so on. But most people have a false impression that node is all about web applications and for command-line utilities. But the truth is we can use Node.js for building most of the functionality same as other programming languages and platforms.
This article is about using Node.js to build desktop applications that run on all major operating systems. You may be wondering right now “Wait i can use JavaScript to create desktop applications?”. The answer is “YES” you may already be using this type of application in your daily life. Have you ever used Slack? Or GitHub Atom editor or Microsoft Visual Studio Code? Then you have used a Node.js based desktop application. Those are some of the classic examples of Node.js based desktop applications.
There are several choices when it comes to frameworks but this article is about Electron. so what is Electron? It is a runtime that allows you to develop desktop applications using HTML, CSS, and JavaScript. It is an open source framework developed by GitHub. Basically, it works by combining the chromium content framework and Node.js together in a single framework. You could see it as a variant of Node.js runtime that is focused on desktop application instead of web servers. This does not mean that Electron is a JavaScript binding for native platform API and GUI libraries. Your application will run in a minimum chromium browser, which is controlled by Node.js runtime and JavaScript.
The interesting part is that you can have the full power of both chromium and Node.js together in the same application. Usually, web browsers use sandboxed security models that block web pages from accessing operating system components. You are very limited with web applications in terms of native-operating system API access. On the other hand, Node.js provides native-operating, system-level access, but it does not provide a way to create graphical user interfaces for your application.
What we will build
This is an application for those of us that have sedimentary jobs. To demonstrate how electron works we will build a small desktop application that will sit in the system tray and notify the user to get up and move around at intervals that the user sets. The application will be cross platform so it will not matter if you are using Windows, Linux or Mac.
The requirement's for it are:
- Cross platform (It will basically behave the same regardless of the users OS)
- User should be able to select between predefined intervals for notifications.
- The notifications should look “Native”.
- The notifications should behave like “Native” notifications.
Initial project structure
Lets start by creating and setting up the basic project structure. First that you have to do is create a project folder. My os of choice for my workstation is Windows 10 so the screenshots and commands will be from it.
Open a new Powershell/CMD window and execute the commands below to setup the initial project structure:
- Cd to a path of your choice.
- Create a new folder.
- Cd into the newly created folder and run following commands
- npm init
- npm install --save-dev electron
- npm install node-notifier - Create a new file index.js in the root of the project folder, this file will contain all our code since this is a very small application.
- Start your editor and change package.json in the project folder. There is a “scripts” property in the file and change that one to look like the one below.
Lets start coding
All the code we are going to write will go into the index.js file that we created. And when we run the “npm run start” command electron will start and load the index.js file.
Start by adding the code below to index.js
So what does the code above do actually? Simply put it is the bare minimum starter for our application. After this point you can run “npm run start” and you would see a new application in the system tray which you can right click and it will show only 1 menu option “Exit” which exits the application.
Please note the code example above assumes that there is a icon.png in the project folder. So before you run the application add a icon.png to the project folder. Which is the application icon that will be shown in the system tray.
Next step is adding a single notification and the option to show it to the user. How is this done well actually quite easily. What we need to do is:
- Create a function for displaying notifications.
- Add an variable to hold the status if the notifications are enabled/disabled.
- Add 2 new menu options in the getContextMenu() function.
The code below contains the updated index.js.
Running the application now we should be able to have some notifications show up when enabled variable is set to true and a time interval is set.
Extending the functionality we have
Currently the application has the following functionality
- It displays an application icon in the system tray
- It has a menu that is displayed when user right clicks on the system tray icon
- It can show a basic test notification
- It can show a basic test notification on 10 minute intervals.
- The notifications it shows look and act like “Native” notifications.
So to reach our goal what is missing is
- Add more notification interval options
- Re-factor parts of the code since certain values are static and there is some repetition of code.
One example of how the re-factored and expanded code might look is below.
There are several changes in the code above, some are big and some are small. I wont go into detail but i will say the biggest visible change after refactoring is that we have an array of notification strings which the notification function picks strings from at random. Now if we run “npm run start” and try out the notifications we should se something like below showing up. :)
Whats next?
Well that is up to you, you could do several other things such as
- Add a way for the user to enter a user defined time interval
- Expand the look of the notifications by adding content such as maybe clips to meditation YouTube videos or something similar.
- Find a way to integrate it with wearables so it can notify that user needs a break only if the wearable says that the user has been sitting still for a certain time period.
All the code and the complete project is available on my GitHub account in a public repository. Feel free to clone or fork as you see fit :)
If you have any suggestion’s of other improvements that would be cool, please write them in the comments below.