Creating a desktop app with JavaScript, HTML, CSS and the old faithful Electron

Camilo Herrera
winkhosting
Published in
13 min readAug 31, 2023
  • You are a web developer and were asked for a desktop application?
  • Did you try to learn specific languages to create desktop applications and failed?
  • Did you notice that you are going to stop sleeping and waste quality time with your family and/or pet trying to create desktop applications?

Say Hell To Da Naw! and learn from our dear friend and her wise words:

And let’s enter together the magical world of Electron framework to create applications with web-oriented languages.

Electron, what is it?

Electron is a framework and a set of tools that allows you to be a lazy software developer who doesn’t want to learn…, sorry, it allows you to use HTML, CSS and JavaScript to create desktop applications, it achieves this by embedding nodejs and chromium in a single executable file.

Impressive, right? Electron is a project that has been operating for years and is very stable. Other alternatives have been created over the years, but I’m old and tired and I’m not going to change it. Here are some alternatives in case you are curious and are thinking about the use of resources such as RAM or disk space (Electron is not known for being the best at this) or if you want to publish your application in the App Store of a certain brand that uses a fruit logo:

Preparing our development environment

Warning: Let’s be clear about something before continuing, I use Windows, because of this, the guide will focus on this operating system. If you use a different one I recommend consulting the specific or equivalent steps for the one you use.

We are going to start by creating a directory somewhere on our PC in which we will save the files of our project, in my case it will be (remember that it is according to your configuration and preference):

D:\electron

Next we will install two requirements to use Electron, they are Node.js and npm.

You can download Node.js+npm by clicking here and install it following the instructions and running the executable file.

The installer already includes npm, you don’t have to follow additional steps to install it, then start a command prompt and run the following instructions to determine if the requirements are active:

PS C:\Users\xxxxx>node -v
v18.16.0

PS C:\Users\xxxxx>npm -v
9.5.1

If everything goes well, the version of Node.js and npm installed on your PC will be displayed, otherwise I recommend you perform the process again or determine if an error occurred during the installation (or there is some restriction on your computer).

For those of you who were successful in this step, stay with me and don’t get too far behind.

Now, having everything ready, we are going to start our project and install the Electron tools in it.

We are going to open a command terminal in Windows (powershell terminal if we are more precise), and enter D:\electron then create a new directory for our specific project like this:

PS C:\Users\xx> cd D:\electron\
PS D:\electron> mkdir testapp
PS D:\electron> ls
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 30/08/2023 2:30 p. m. testapp

PS D:\electron> cd .\testapp\
PS D:\electron\testapp>

Inside the new testapp directory we create the initial structure of our application with the following command:

PS D:\electron\testapp> npm init

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (testapp) TestApp
Sorry, name can no longer contain capital letters.
package name: (testapp)
version: (1.0.0)
description: My Electron Test App
entry point: (index.js)
test command:
git repository:
keywords:
author: Camilo Herrera
license: (ISC)
About to write to D:\electron\testapp\package.json:

{
"name": "testapp",
"version": "1.0.0",
"description": "My Electron Test App",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Camilo Herrera",
"license": "ISC"
}


Is this OK? (yes) yes

During the process the basic data of your application will be requested, you can leave the default values for most, but the description and the author are mandatory.

Now we are ready to include the Electron functionalities, inside the directory execute the following command:

PS D:\electron\testapp> npm install --save-dev electron

To run the application using Electron, an additional step is necessary. In the directory a file named package.json was created, open the file in a text editor and add an entry in “scripts” with the value “start”:”electron.” like this:

{
"name": "testapp",
"version": "1.0.0",
"description": "My Electron Test App",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "electron ."
},
"author": "Camilo Herrera",
"license": "ISC",
"devDependencies": {
"electron": "^26.1.0"
}
}

Don’t forget the comma at the end of the previous line. Save the content of the file to finish.

Creating our application

Up to this point your basic configuration is ready, now it is necessary to create the files to display the main window of your application, to accomplish this we are going to create two files:

  • index.js
  • index.html

index.js is the entry point of your application, as set in the package.json file.

The content of the file is shown below:

index.js

//This is the way to include modules with Node.js, in this case the 
//Electron module.
//You can learn more about importing modules by searching
//information about "CommonJS" modules on the internet
const { app, BrowserWindow } = require('electron')

//Create our main windows, here you can set the initial size.
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})
//The HTML file that will be shown, we will create this file in the next section.
win.loadFile('index.html')
}

//This is our starting event, once "Ready", create our main window.
app.whenReady().then(() => {
createWindow()
})

As an additional step, we are going to add my beloved bulma CSS library, you can download it from its official site bulma.io and save the bulma folder (that’s inside the downloaded .zip) in your testapp application directory, the folder structure will look like this:

D:\electron
\testapp
\bulma
- index.html
- index.js
- package.json
- package-lock.json
\node_modules

Now our index.html file, this file will contain the HTML code to be displayed, just like a website… but in your desktop application, do you understand the concept? It’s easy.

You smart Electron!

index.html

<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<!-- CSP is a PITA ;). Disabled, don't try this at home!-->
<meta http-equiv="Content-Security-Policy" content="">
<!-- include bulma css -->
<link rel="stylesheet" href="bulma/css/bulma.min.css">
<title>My Test App</title>
<script>
window.addEventListener('load', (event) => {
document.querySelector(".hello").textContent = "Hello from Electron with bulma css!";
});
</script>
</head>

<body>
<section class="section">
<div class="container">
<div class="notification is-warning has-text-centered hello">

</div>
</div>
</section>
</body>

</html>

This HTML code loads the bulma css library and creates a notification with a message that is show at the end of the DOM loading process.

At this point you can also start modifying or adding sections, you can navigate relatively between .html files or use JavaScript libraries just like on a website with script tags like this:

<script defer src="/ruta relativa a mi archivo .js"></script>

Now you can start the application for the first time, from the same command console execute the following instruction:

PS D:\electron\testapp> npm start

The result will be something like this:

My first Electron App!

If you don’t want to show the default window menu (nobody wants that in production, for debugging it can be useful as it allows you to show the developer tools inside the same window.), you can disable it by editing your index.js file and adding the following line:

win.setMenuBarVisibility(false)

index.js without window menu

//This is the way to include modules with Node.js, in this case the 
//Electron module.
//You can learn more about importing modules by searching
//information about "CommonJS" modules on the internet
const { app, BrowserWindow } = require('electron')

//Create our main windows, here you can set the initial size.
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})

//disable menu bar
win.setMenuBarVisibility(false)
//The HTML file that will be shown, we will create this file in the next section.
win.loadFile('index.html')
}

//This is our starting event, once "Ready", create our main window.
app.whenReady().then(() => {
createWindow()
})

Packaging our application

Now we are going to compile the application into an executable and attach an icon to it.

Create or download a Windows icon (.ico format) and save it in a directory with an appropriate name inside testapp, for example we will call the directory icons, the directory structure will look like this:

D:\electron
\testapp
\icons
- app.ico
\bulma
\node_modules
- index.html
- index.js
- package.json
- package-lock.json

Next we go to the index.js file and add the path of the icon like this:

icon: 'icons/app.ico'

index.js with icon path

//This is the way to include modules with Node.js, in this case the 
//Electron module.
//You can learn more about importing modules by searching
//information about "CommonJS" modules on the internet
const { app, BrowserWindow } = require('electron')

//Create our main windows, here you can set the initial size.
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
icon: 'icons/app.ico'
})

//disable menu bar
win.setMenuBarVisibility(false)
//The HTML file that will be shown, we will create this file in the next section.
win.loadFile('index.html')
}

//This is our starting event, once "Ready", create our main window.
app.whenReady().then(() => {
createWindow()
})

Now run the application, the icon should be displayed on the taskbar and at the top left of the window.

To package the application and generate an executable we will have to install Electron Forge, this is the most common solution to carry out this process.

Inside the testapp directory run the following commands:

PS D:\electron\testapp> npm install --save-dev @electron-forge/cli
PS D:\electron\testapp> npx electron-forge import

The result of the commands and a final thank you message for using Electron Forge will be displayed.

Run the application again with the initial command, you will notice that now the one in charge of the process is Electron Forge and not Electron directly, the process will take a few more seconds but the result will be the same.

To create an executable that can be distributed, run the following command in the same console:

PS D:\electron\testapp> npm run make

It is important to me to show you the output of the command in the console, you should see something like this:

> testapp@1.0.0 make
> electron-forge make

✔ Checking your system
✔ Loading configuration
✔ Resolving make targets
› Making for the following targets: squirrel
✔ Running package command
✔ Preparing to package application
✔ Running packaging hooks
✔ Running generateAssets hook
✔ Running prePackage hook
✔ Packaging application
✔ Packaging for x64 on win32 [4s]
✔ Running postPackage hook
✔ Running preMake hook
✔ Making distributables
✔ Making a squirrel distributable for win32/x64 [33s]
✔ Running postMake hook
› Artifacts available at: D:\electron\testapp\out\make

Now you can enter the path (in my case) D:\electron\testapp\out and there you will find two directories named make and testapp-win32-x64, inside testapp-win32-x64 are the files you want to use to distribute your application.

You will notice that the executable file named testapp.exe does not have the icon that we initially defined, this is expected, we are going to fix it by editing a new file that was created by Electron Forge in testapp, the file has the name forge.config.js, edit the file and add in the “packagerConfig” section a line with the following content:

icon: 'icons/app' // file type is not required

The complete file will look like this (remember that it is JSON format and you must write a comma separating each item:

forge.config.js with icon setting

module.exports = {
packagerConfig: {
asar: true,
icon: 'icons/app' // no se requiere la extensión del archivo .ico
},
rebuildConfig: {},
makers: [
{
name: '@electron-forge/maker-squirrel',
config: {},
},
{
name: '@electron-forge/maker-zip',
platforms: ['darwin'],
},
{
name: '@electron-forge/maker-deb',
config: {},
},
{
name: '@electron-forge/maker-rpm',
config: {},
},
],
plugins: [
{
name: '@electron-forge/plugin-auto-unpack-natives',
config: {},
},
],
};

Save the file and run the command again to create the files to distribute:

PS D:\electron\testapp> npm run make

Once the process is finished, enter the testapp-win32-x64 directory and run testapp.exe, you will see the icon used in the taskbar and in the window.

Up to this point your files would be ready for distribution, except for the signing of the application if you plan to distribute it in the Microsoft store, it is an animal completely outside the scope of this guide, if you need to do it check the Microsoft documentation to carry out the process.

Creating an installer with Inno Setup for Windows

Now that we’ve got everything ready, we can’t just be vulgar software developers distributing our app inside a .zip right?

Inside a .zip? I’ve never done it! (yeah right)

Inno Setup is a great tool for creating installers on Windows, you can download it from here. Install it on your PC and we will proceed with the creation of our installer.

Run Inno Setup, at startup a welcome window will be displayed with some options, select “Create a new script file using the Script Wizard” and click the “OK” button, in the new window displayed click “Next”, it will be displayed a form, enter the data as shown below:

Inno Setup Script Wizard basic info

Click “Next” to continue, some data will be shown by default, do not change it unless you know what you are doing:

Install directory settings

Click “Next” again and the files to be packaged in the installer will be requested, in “Application main executable file:” select the file testapp.exe created in the directory D:\electron\testapp\out\testapp-win32-x64.

In the “Other application files” section, click the “Add folder” button and select the “D:\electron\testapp\out\testapp-win32-x64” directory, this will include all the dependencies and additional files used by our application.

Files to be included in the installer

Click the “Next” button and in the next step uncheck the “Associate a file type to the main executable” option as it is not necessary.

Associate file type to app

Again click on “Next” and options for creating shortcuts in Windows will be shown, leave the default options, do not change them.

Application Shortcuts

Clicking on “Next” will show options to include licenses and information before and after the installation, for now we do not need them, leave the default values.

Installer documentation

Click “Next” and the installer execution permission options will be displayed, this allows the user to decide whether to install for everyone or just for their session. Leave the default values.

Install mode

Clicking on “Next” will show the language selector for the installer, by default we will leave “English”.

Setup Languages

Click “Next”, options for the installer compiler will be shown, in the field “Custom compiler output folder” we will set the path D:\electron\testapp\out\installer (create the installer directory inside the out directory, you can creat it from the directory selector).

In the “Compiler output base file name” field write “testapp” and in the “Custom Setup icon file” field use the icon of our application in the path D:\electron\testapp\icons\app.ico (or the path where you saved the ico file on your PC).

Do not type password for the installer, it is not necessary.

Compiler Settings

Click “Next”, then an option to create the installer compiler script will be shown (you don’t have to understand it but in general, what it indicates is that the script that Inno Setup will use to generate the installer will be more or less user friendly to be edited manually). Leave the default value and don’t ask further questions!

Inno Setup Preprocessor

Click “Next” and the final message will be displayed, then click “Finish” to start the installer creation.

Final step

Clicking the “Finish” button will show the script to be used to generate the installer and a message will appear asking if you want to carry out the process. Click “Yes”.

Installer creation script

Now Inno Setup will ask you if you want to save the script to edit it in the future, click “yes” and save in a path of your choice.

The installer creation process will start and the progress will be displayed at the bottom of the Inno Setup window. Once finished, go to the D:\electron\testapp\out\installer directory and you will find the installer file, run it and follow the steps on screen.

The result will be your application installed in Windows, just like any pro top tier software developer can!.

You made it!

And that’s it, as always, remember that Winkhosting.co is much more than web hosting!

--

--