Building HTML5 kiosk applications with Vue.js and Electron
This guide assumes you already have at least basic knowledge about Vue.js and want to learn how to package your Apps with Electron. If you’re looking to get started with Vue.js I highly recommend the guide on their website as starting point.
If you have ever developed and deployed a browser based kiosk application you are probably familiar with some of the usual annoyances:
- Browsers will display update reminders which is especially annoying for offline applications.
- Improper shutdown of the browser (or operating system) will result in popup messages like “Chrome didn’t shutdown properly” on the next start.
- Users will (intentionally or not) close the application window, rendering your kiosk useless — or even exposing data that should not be accessible.
- Some well-meaning person updates the browser on your kiosk system causing the application to behave all weird.
Note: Don’t get me wrong — I perfectly understand these are all important browser security mechanisms. Just for kiosk applications they are usually not necessary and rather annoying.
“No matter how hard you try, your browser (and your users!) will try even harder to ruin your application and user experience.”
In a perfect (kiosk) world we’d have the ability to lock down our application to a point that users are restricted to the actions that we want them to perform. Also the browser would merely act as our canvas with exactly defined capabilities and doesn’t get into our way.
And this is why you want to use Electron!
Electron to the rescue
Electron is a framework to package your HTML5 / JavaScript based applications into a standalone desktop application for multiple platforms (Windows / MacOS / Linux).
It is however much more than just “WebPack for executables” but has a number of unique features which make it a great choice for kiosk applications (or any kind of desktop application that is):
- Electron applications package Chromium as rendering engine, eliminating all of the issues described above. You deliver your application package with the browser engine included.
- Due to the included browser engine you also eliminate all kinds of JavaScript / CSS cross-browser issues as you develop for an exactly defined browser environment. No more “breaks in production”!
- Electron also natively integrates with NodeJS modules, providing you with useful libraries for networking or file system access — or anything else you have previously used NodeJS for.
- You have direct access not only to the Chromium rendering engine but also to the Application itself. This will allow you to establish some additional lockdown measures or deal with unintended application shutdown.
Let’s look at how to install and use it:
Getting your environment ready
The easiest way to create a new Vue.js application is using the vue-cli tool. Go ahead and install it via:
npm install -g @vue/cli
You can now create your new application by typing:
vue create my-app
The installer will ask you which modules you wish to include with your new application. For your first app I recommend the following settings:
- Choose “Manually select features”
- Enable “Babel” (it should be selected by default)
- Enable “Router”
- Enable “CSS Pre-processors”
- Enable “Linter / Formatter”
On the next screens choose:
- Sass / SCSS (with node-sass)
- ESLint with error prevention only
- Lint on save
- In dedicated config files
You are of course free to make any other selections — it will not have any effect on how your App integrates with Electron later on.
Once the installer has finished you can run your App with the following commands:
cd my-app
npm run serve
Open your web browser and you will be greeted with Vue.js “Hello World” page:
A note here: While the Browser developer tools usually work totally fine for debugging UI related issues, I strongly recommend you additionally install the “Vue Devtools” extension for your browser. You can find plugins / extensions for all common browsers here.
Adding Electron to your Vue.js App
There are multiple methods to add Electron to your App but we found that using the Vue CLI Plugin Electron Builder is by far the quickest and easiest method to get started.
Inside your project directory type:
vue add electron-builder
This will install Electron with all necessary dependencies and also configure the entire build process for your development and release packages. If you open the package.json
file in your application folder, you will find that NPM scripts electron:serve
and electron:build
have been added. You can use serve
for development and build
for creating the executable packages for different operating systems.
Now go ahead and try running npm run electron:serve
If you see the above application opening — Congratulations! You have just successfully created your first Vue.js / Electron App. You can also try a production build with npm run electron:build
and you should end up with an executable for your current platform inside the dist_electron
folder which is ready for shipping.
You’re now basically all set and ready to start coding. Before you go ahead let’s have a more in-depth look into Electron and I will share some useful best practices with you.
Best practices for Electron Kiosk Apps
When you set up a fresh Electron App, your directory structure will look like this:
As mentioned before the dist_electron
directory is simply the location where your executables will be created when you build your App. The much more interesting file is background.js
which we’re going to have a closer look at.
An important note here:
While it is tempting to usebackground.js
for background tasks like Websocket servers or other long-running jobs, Do NOT do this! Keeping the background process busy will cause the UI of your App to become unresponsive. There are better methods for running background tasks in an Electron App which I will describe in another article.
The main application window
Open up background.js
in your IDE and around line 17 you will find the function called createWindow
which is responsible for opening the main window of your application. By default it is configured to create an 800x600px sized window and enable the NodeJS integration but there are (literally) a hundred additional options you can set. Here are some commonly used options for kiosk applications:
win = new BrowserWindow({
width: 800,
height: 600,
fullscreen: true,
frame: false,
autoHideMenuBar: true,
kiosk: true,
webPreferences: {
nodeIntegration: true
}
});
These settings will ensure your App runs in full screen mode without any window frame or menu bars. However just running your App in full screen mode is NOT enough and you should enable “kiosk” for some additional lockdown features such as:
- Disable the F11 key to exit full screen
- Disable keyboard shortcuts for navigating or creating new tabs / windows
- Prevents other programs from popping up on your screen
Global application shortcuts
If you want to define your own key (or key combination) to exit the App, you can register a so-called “globalShortcut”. To enable global shortcuts, first import the function by adding it to the existing import like this:
import { app, protocol, globalShortcut, BrowserWindow } from 'electron'
Next find the line which registers the app.on('ready')
event handler (around line 58) and insert the following code below createWindow()
:
globalShortcut.register('Escape', () => {
app.quit();
})
This will enable the ESC
key to quit your App. You can of course also use different keys or key combinations.
Building and Packaging
You already learned that building and packaging your application is as easy as running npm run electron:build
in your application directory. Still you might wonder how you can configure certain properties of your App package, such as the bundle name, the App icon or how to build for multiple platforms.
Let’s start by setting our bundle name and icons. As we use Electron as a plugin for Vue.js, we need to add this configuration to a file called vue.config.js
. If this file doesn’t exist yet you can create it as a new blank file in your application root directory.
The file itself should look like this:
module.exports = {
[... any other Vue.js configuration...]
pluginOptions: {
electronBuilder: {
builderOptions: {
productName: "My great App",
appId: "com.acme.mygreatapp"
mac: {
icon: 'src/assets/app.icns'
},
win: {
icon: 'src/assets/app.ico',
target: [
{
target: 'portable',
arch: ['x64']
}
]
}
}
}
}
}
The above file should be pretty self-explaining. You’re configuring the Electron Builder to use “My great App” as the application name and using “app.icns” and “app.ico” as icons for the macOS and Windows bundles. In addition the builder should create a portable 64bit executable for Windows.
Note that you CAN build Windows executables on macOS but you CAN NOT build macOS executables on Windows.
There are quite a lot of other options available if you need to build for different platforms or architectures. In my case I usually want to build a macOS executable to distribute to a group of testers and a portable (EXE file without installer) Windows 64 bit version for production. You can refer to the documentation here and here for additional configuration options.
What about Linux builds? Linux supports many different architectures (x86, arm, …) and does not have a single package format like DMG or EXE. Instead there are many options like AppImage, Snap, Deb etc, so you need to configure a build target that matches your requirements. For example if building for a Raspberry Pi 3 you will need to configure a linux build for “armv7l” architecture and use the “snap” target.
Going into lockdown
Electron Apps in kiosk mode already provide a decent amount of lockdown. If you want to further minimize the chance of the user closing the App and messing with the underlying operating system, here are some (Windows-only) measures we’ve used before:
Do not launch the Windows desktop at all
Use these regedit modifications to directly load your App on boot instead of the Windows Desktop (explorer.exe). In case your App crashes or gets otherwise terminated there will just be a blank screen:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]
"Shell"="D:\\path\\to\\your\\appFile.bat"
To revert:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]
"Shell"="explorer.exe"
Prevent the Alt+F4 keyboard shortcut
Capture the “beforeunload” event on your main application window using the following code:
window.onbeforeunload = (e) => {
console.log('I do not want to be closed');
e.returnValue = false;
}
Conclusion
I hope this tutorial could help you understand what Electron is and how to use it in practice to build HTML5 based kiosk applications. There is of course still lots more to discover and I will share some more in-depth tutorials with you soon!
If you have any comments, questions or suggestions feel free to start a conversation in the comments.