Harmonic Part 1 - Turning a Web App into a Desktop App with Electron

electron tutorial

This post is a first in a series of how to use Electron (formerly atom-shell) to turn a Web Application into a Desktop Application. For this tutorial, We’ll be working on a cross-platform desktop client for Google Play Music. This first post will focus on setting up your application, and loading the webpage into the window.

As someone who switched over from Spotify, the only annoyance I’ve had with Google Play Music is the lack of a desktop client. There are already clients out there for Linux and OSX, both of which I use, but nothing for when I’m on my Windows PC.

That’s where Harmonic comes in.

Harmonic is pretty simple really. It loads in the Google Play Music webpage into a window on your desktop, and then registers global keyboard shortcuts to let you control playback without having to focus the window. If you want to skip the tutorial and just look at the code, you can check it out on GitHub.

package.json

The first step is to generate the package.json file. For this, we use NPM.

mkdir electron_tutorial_one
cd electron_tutorial_one
npm init

You can just push ‘enter’ to use the defaults for all of the questions. unless you want to add some more details. This will generate the package.json file, which will look something like the one below.

{
  "name": "electron_tutorial_one",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Now we can add a few extras to this file to make life a bit easier.

First, add the following to the ‘scripts’ section.

"start": "electron ."

This gives you a shortcut for starting the app from the commandline.

Next, use NPM to install Electron into the app.

npm i electron-prebuilt --save-dev

Then, install Electron globally to let you start Electron from the commandline

npm i -g electron-prebuilt

After that, you should end up with a file that looks like this

{
  "name": "electron_tutorial_one",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "electron ."
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "electron-prebuilt": "^0.25.1-1"
  }
}

index.js

The index.js file is the entry point for the app. It’s defined in the package.json file, so if you want to rename it, make sure you update your package.json.

This file controls the main thread of the application. It’s responsible for spawning the other processes, and controlling interactions with the operating system. In the example, we set up the required handlers for starting and stopping the app, as well as spawning a window and loading in the content.

For the window that we will load our content into, we will use the Browser Window library. There’s plenty of options besides the ones that we will use, so make sure you check out the docs.

// Require the libraries used in the app
var app = require('app'),
    BrowserWindow = require('browser-window');

require('crash-reporter').start();

var mainWindow = null;

// Kill the app when all windows are closed
app.on('mainWindow-all-closed', function() {
  if (process.platform != 'darwin')
    app.quit();
});

app.on('ready', function() {
  // Create the main window for the app
  mainWindow = new BrowserWindow({
    "min-width"         : 800,
    "min-height"        : 600,
    fullscreen          : true,
    resizable           : true,
    "use-content-size"  : true
  });

  // Load in our content
  mainWindow.loadUrl('file://' + __dirname + '/index.html');

  // This is required for now due to https://github.com/atom/electron/issues/1117
  mainWindow.openDevTools();
  mainWindow.closeDevTools();

  // Ensure that garbage collection occurs when the window is closed
  mainWindow.on('closed', function() {
    mainWindow = null;
  });
});

Now, there’s just one file left.

index.html

The index.html file is the content that is loaded into our BrowserWindow. It’s a very simple webpage, with only one element, the (webview)[https://github.com/atom/electron/blob/master/docs/api/web-view-tag.md].

<!DOCTYPE html>
<html>
  <head>
    <title>Electron Tutorial One</title>
  </head>
  <body style="overflow: hidden">
    <webview id="gpm-player" src="https://play.google.com/music/" style="height:100%;width:100%;position:absolute;"></webview>
  </body>
</html>

Starting your app

Now that all your files have been built, the only thing left to do is to run it. Open up a terminal, and type

npm start

This will open the app, and load Google Play Music into the browser. You’ll asked to sign in, and from there you can start using it just like you do in the web browser.

Next time

In the next tutorial, we’ll look at how to load in javascript/css, and setup global shortcuts to control the media player.

You can view the code from this tutorial on GitHub