How To Build Your First App With Electron
It is possible with Electron.
This article is a step-by-step guide that will help you understand some core concepts of Electron.
By the end of this post, you’ll know the process of creating cross-platform desktop apps with Electron, HTML, and CSS.
Before we get started you can check out in advance the app we’re going to build in this tutorial.
Hear Me Type, as I named it, will have a simple but straightforward functionality: for every keyboard key pressed play a specific sound related to that key.
So if I press the “A” button, the app will play the sound of the letter A.
- Hear Me Type Tutorial app GitHub repository
- Hear Me Type GitHub repository (a more advanced version of the app. Recommended for more experienced Electron users)
The apps’ code will change once in a while as I’m adding new features and enhancements so be sure to check out the commits to see what’s new.
Without further ado, let’s find out more about Electron and create our first app!
What is Electron?
Your newly created app will be compatible with Mac, Windows, and Linux operating systems.
Other in-built features are:
- Automatic updates – enable apps to automatically update themselves
- Native menus and notifications – creates native application menus and context menus
- App crash reporting – you can submit crash reports to a remote server
- Debugging and profiling – it uses Chromium’s content module for finding performance bottlenecks and slow operations. You can also use your favorite Chrome Developer Tools within your app if you’d like
- Windows installer – you can create install packages. Fast and simple.
If you’re happy with what Electron offers, let’s dive deeper and create a simple Electron app.
Before we get our hands dirty, make sure you have the dependencies like Node.js installed (you can download it from here) and also a GitHub account where you can store your app and make changes to it.
Now that Node.js is installed and a GitHub account, open your Bash or Terminal and follow the instructions below to clone the Electron Quick Start Git repository to your computer. We’re gonna build our software upon this useful but minimal app:
When you have completed the steps above you should see that our app opens up in a window that looks like a browser’s window. And it is indeed a browser window!
The app’s window style changes depending on the Operating System’s default or customized window style. I chose to use the classic look of Windows. Groovy!
Like I was saying earlier, you can use Chrome’s Developer Tools inside your app. What you can do on your browser’s Developer Tools, can also be done inside the app. Outstanding!
Let’s have a look at the source code and the file structure of our app. Open up the project into your favorite text editor or IDE. I’m going to use Atom which is built on… you guessed it… Electron!
We have a basic file structure:
The file structure is similar to the one we use when creating web pages.
index.htmlwhich is simply an HTML5 web page and it serves one big purpose: our canvas
main.jscreates windows and handles system events
package.jsonsimilar to Node.js’ modules, is the startup script of our app, which will run in the main process and contains information about our app
render.jsis responsible for hosting the app’s render processes
You may have a few questions up until now, and one of them might be regarding the main process and render process thingies. What the heck are those little bastards and how can I get along with them?
What is a process?
When you say process you think of an operating system level process which is in fact just an instance of a computer program that is being executed.
If I start my Electron app and check the Windows Task Manager/Activity Monitor for macOS, I can see how many processes are associated with my app.
Each of these processes runs concurrently with each other but the memory and resources are isolated.
Let’s say I want to create a specific
for loop that increments something in one of my render processes.
The above incrementation is available only in the render process, it doesn’t affect the main process at all, thus the ‘This is a for loop’ message will appear only on the rendered module.
The main process controls the life of the application. It has the full Node.js API built in and it is responsible for opening dialogs and other operating system interactions, creating render processes, and starting and quitting the app.
This process is commonly a file named
main.js, like in our case, but it can have whatever name you’d like.
You can also change the main process file by modifying it in
Just for testing purpose, change:
See if your app still works.
Bear in mind that there can be only one main process.
The render process is a browser window in your app. Unlike the main process, there can be multiple render processes and each is independent. Every render process is a separate process, meaning a crash in one won’t affect another. This is thanks to Chromium’s multi-process architecture.
These browser windows can also be hidden and of course, customized because they’re like typical HTML files, but in Electron we’ve also got the full Node.js API in here which means that we can open dialogs and other operating system interactions.
Think of it like this:
One question remains now. Can they both be linked somehow?
While these processes run concurrently and independently from each other, they still need to communicate somehow since they’re both responsible for different tasks.
For this, there’s an interprocess communication system or IPC. You can use IPC to pass messages between main and render processes.
This pretty much sums up the minimum knowledge about main process and render process you have to know before starting building an Electron application.
Now let’s get back to our code!
Make It Personal
Let’s give our app’s folder a proper name.
Change the folder name from
Reopen the folder with your favorite text editor or IDE and let’s further customize our app’s identity by opening up the
package.json contains vital information about our app like its name, version, main file, author, license and so much more.
Let’s get a little bit of pride and put yourself as the author of the app.
"author" parameter and change its value to your name. It should look like this:
"author": "Carol Pelu",
We also need to change the rest of the parameters. Modify the “name” and “description” for now. I find the following name and description appropriate for our app:
Awesome! Now our app has a new name and a short but straight to the point description.
Remember, you can always run
npm start in your bash to execute the app and see the changes you’ve made.
Let’s move forward and add the expected functionality of our app. We want to play a specific sound for every keyboard key that we press.
Oh, the Fun-ctionalitee!
What is an app without fun-ctionality? Nothing much…
Now we must take care of it and give our app the functionality it desires.
To make the app react to our input, we must first define an element to hook upon and then trigger the desired action.
In order to do that we will create an
audio element with specific
id s for the keyboard keys that we want. Then we will create a
switch statement to find out which keyboard key has been pressed, then play a specific sound of that key.
If this sounds a little complex to you now, have no fear. I will guide you through every step.
Download this archive containing all the sound files we’ll be using. We’ll soon make use of them!
Open up the
index.html file and let’s create the
<audio> elements in order to embed the sound content in our app.
<body> element, create a
div element with the “audio”
Then inside the newly created
div element, create an
<audio> element with an
id of “A”, the
source tag of “sounds/A.mp3” and with a
preload attribute of “auto”.
preload="auto" to tell the app that it should load the entire audio file when the page loads.
index.html being the main file of the app, all of our sound files will be fully loaded when the app executes.
The code should look like this:
<audio> is pointing to an unknown source file. Let’s create a folder called
sounds and unzip all the sound files inside the folder.
Create a new file called
functions.js and let’s require it within the
index.html file so that the JS code is ready for use when the app is running.
Following the example of
require(./renderer.js') , right under it add this line of code:
Your project should look like this:
Outstanding! Now that we have everything stitched up, it’s time for the moment of truth!
Open up the
The code should look like this:
Open your bash in your project’s folder and type
npm start to run the app.
Tune-up the volume of your speakers and press the A button on your keyboard.
The JS code is pretty simple and straightforward.
We use the
onkeydown event on the
document object to find out which HTML element is being accessed within the
document object which is in fact our app’s main window.
Within the anonymous function, we use a
switch statement whose purpose is to identify the Unicode value of the pressed keyboard key.
If the Unicode value of the pressed keyboard key is correct, the sound is played, otherwise, throw a “not found” message into the console.
Whfiu! What a ride!
Maybe you’ve noticed that we have sound files to cover A-Z and 0-9 keys. Let’s use them too so they don’t feel the bitter taste of loneliness.
Head over to
index.html and create an
<audio> element for every key that we have a sound file for.
The code should look like this:
Yeah, of course, you can copy-paste:
Awesome! Now let’s do the same thing for the JS code within
You can find the char codes (keycodes) on this website.
But yeah, you can copy-paste this too:
Our app is now complete! Congrats!
The main functionality of the app is done, but there is still work to be done!
Polska ja! (Polish me!)
Even though the app is functional it still lacks some things here and there.
For example, within the
index.html file, you can change the app’s title and the content that you want to be shown in the main window.
Moreover, the app has no design, no beautiful colors, no pictures with either cats or dogs.
Give freedom to your imagination and find out ways you can improve the app’s design!
The code isn’t perfect either. We have lots of identical code which can be optimized and improved in fewer lines of code and less painful for the eyes. Code duplication is bad practice!
Test It! Just Test It!
Good software must be thoroughly tested.
I’d suggest beginning with pressing every keyboard key to see what’s happening.
The best scenario is you will hear the audio for every keyboard key you have specified in the code, but who knows what will happen when you press multiple keys in a row as fast as you can or keys that are not even supposed to be pressed like the Home and NumLock buttons.
What happens when you minimize the app and try to press a key? Do you hear a sound? But what happens when you don’t have the app window selected and you press a keyboard key, do you still hear any sounds?
The answer is unfortunately a no.
This behavior is because of the architecture upon which Electron was built. It does allow you to get global keys like you can do with the C# language, but you can’t register individual keystrokes. This is outside of the realm of normal use-cases for an electron application. I don’t know the real reason behind this caveat but I guess it has something to do with keyloggers and user’s privacy.
I want you to grab the code line by line and break it to see what is happening and what kind of errors is Electron throwing out. This exercise will help you become better at debugging. If you know the flaws of your app you then know how to fix them and make the app better.
Once you find it I would like you to think about how you can replace this deprecated event without changing the functionality of the app.
Using deprecated code is bad practice and can lead to serious bugs you might not even know exist. It’s recommended to read again the documentation of the language to see what has changed and stayed up to date.
First of all, I would like to thank and congratulate you for reaching this point!
You now have the knowledge to create a simple cross-platform Electron app.
Feel free to clone, fork, star, and contribute to any of my public projects.
Last but not least, I’d suggest you come back and read again this article from time to time as I will constantly update it according to what changes Electron will suffer over time.
If you find this article helpful, please share it with others and subscribe to the blog to support me, and receive a bi-monthly-ish e-mail notification on my latest articles.