Electron+Angular2: Getting Started

Electron+Angular2: A cross platform IRC client


I’ve been looking to work my way through a full electron application, as well as learning the ins and outs of Angular 2. So why not do both! As for why make an IRC client? I have found that there are no good cross platform clients for IRC, and I am a dirty Twitch viewer who hates having the chat log take up precious screen real estate. So now you know.

Getting Started

First things first, I decided to make my life easier using the angular-cli tool. Install it using that oh so simple one liner npm install -g angular-cli (well I used yarn as in yarn global add angular-cli). Then make your new angular app using ng new [app-name]. Finally, pop into the directory that was created (cd [app-name]) and explore your newly created angular goodness.

The structure of the application

The first place you want to look is at the src folder – that’s where the actual application lives and breathes (well metaphorically speaking). You should have a single component in that folder all contained under the app directory. That component will be your root component that handles pulling the app together. You also have an assets folder for any static assets you may have, as well as an environments folder that defines different environment variables (prod vs dev vs whatever). At the top level of the src folder you will see your base index.html file that gets loaded by the app, the main.ts (more on typescript later) file that handles bootstrapping the application as well as a few other less important files (well less important for now).

Restructuring things for Electron

As it stands this app will run fine in a browser, but we want to be cool and run this in Electron! So first things first, rename that pesky src directory to renderer-src. This directory is going to contain all of the code one taht is rendered inside the app frame. We’ll be working here primarily for the fancy front end stuff we’ll be doing. Since we changed that we need to open up angular-cli.json and make some changes. First things first locate the first (and from what I can tell only viable) element of the apps array. You will see a root key. Change that key from src to renderer-src. While we’re here go ahead and change the outDir from dist to dist/renderere so we can use that dist folder for both the renderer code and main code.

Next let’s get set up for the main process. Go ahead and create the main-src directory in the root of your project and create a nice new main.ts file in there. That main.ts file is going to be the actual entry point for electron and will do all of the bootstrapping. The basic default main.ts file looks something like this:

import * as electron from 'electron';
let app = electron.app;
let BrowserWindow = electron.BrowserWindow;

// Global reference to the main window, so the garbage collector doesn't close it.
let mainWindow : Electron.BrowserWindow;

// Opens the main window, with a native menu bar.
let createWindow = () => {
    // Create the browser window.
    mainWindow = new BrowserWindow({
        minWidth: 800,
        minHeight: 600,
        width: 1024,
        height: 768,
        frame: true

    // and load the index.html of the app.

    // Open the DevTools.
    // mainWindow.webContents.openDevTools();

    // Emitted when the window is closed.
    mainWindow.on("closed", () => {
        // Dereference the window object, usually you would store windows
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        mainWindow = null;

// Call 'createWindow()' on startup.
app.on("ready", () => {

// On OS X it is common for applications and their menu bar to stay active until the user quits explicitly
// with Cmd + Q.
//TODO consider if I want to change this behaviour or not?
app.on("window-all-closed", () => {
    if (process.platform !== "darwin") {

// On OS X it's common to re-create a window in the app when the dock icon is clicked and there are no other
// windows open.
app.on("activate", () => {
    if (mainWindow === null) {

However as it stands this file won’t work for one reason – that pesky file://${__dirname}/../renderer/index.html. That is intentional, but I wanted to warn you before you got all trigger happy and tried to run it.

Build Scripts

I’m as lazy as the next developer and hate the idea of having to remember long commands and all the options I need so we’re going to make life easier and set up some npm scripts. Since I started by using the angular-cli tool ng we’ll stick to using that for building the renderer code. For the main code we turn to typings to compile our typescript to javascript. tsc can be made much easier if you go ahead and use a tsconfig.json file to manage your settings, to avoid munging ng we’re going to name our config file tsconfig-main.json and call it with the -p option. The tsconfig-main.json file I end up with looks like this:

    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "moduleResolution": "node",
        "sourceMap": false,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "removeComments": false,
        "noImplicitAny": false,
        "outDir": "dist/main"
    "include": [

This file will make tsc compile everything in the main-src directory and output it to the dist/main directory for us to use. Most of the other options should be self-explanatory, if not take a glance at the tsconfig.json documentation.

When developing we don’t want to have to re-run a command every time we make a change (yes I’m looking at you, don’t do this, it’s annoying and a waste of time), so let’s set up our npm scripts to build, run and watch for us. Here is the scripts block of my package.json

"scripts": {
    "ng": "ng",
    "clean": "rm -rf dist/",
    "ng:watch": "ng build -w",
    "ng:build": "ng build",
    "tsc:watch": "tsc -w -p tsconfig-main.json",
    "tsc:build": "tsc -p tsconfig-main.json",
    "electron:start": "electron dist/main/main.js",
    "start": "npm-run-all clean ng:build tsc:build --parallel electron:start ng:watch tsc:watch",
    "lint": "tslint \"renderer-src/**/*.ts\" \"main-src/**/*.ts\"",
    "test": "ng test",
    "pree2e": "webdriver-manager update --standalone false --gecko false",
    "e2e": "protractor"

So let me run through these in order. The first just makes it easier to call the angular-cli command ng without having to prefix each call with node_modules/.bin (though is npm run ng that much easier?). The next, clean, removes the built files to prevent any messiness, probably unnecessary, but not harmful certainly. Now things get interesting, we have ng:build and ng:watch that call ng and build the angular part of the app (the -w option means ng keeps running and will rebuild if a file changes, useful for development). Next we have our tsc parts that build the main process code. Again, the -w option leaves the compiler running to rebuild on changes. electron:start is pretty simple it launches our electron app by loading the compiled entry file. Now the big boy – start – this does a whole lot in one line so bear with me. npm-run-all (https://www.npmjs.com/package/npm-run-all) is a useful little tool that allows for composition of tasks in serial or parallel. The first group will run in serial as we didn’t prefix it with the --parallel option, it will clean any old compiled code, then build first the renderer process code, then the main process code using the scripts I talked about earlier. Next it runs three other commands in parallel – it starts the electron app itself, and then starts the watchers for both the renderer and main process code so any changes we make are automatically built, and we just have to reload the electron window.

Running the App

So I’ve talked about some core concepts, the structure, and the build scripts needed to make all this work, so let’s finally get to it. Pop open a terminal window and cd into your project directory. Now run npm start and watch as the terminal starts blowing up with information. Once all of the compilation is done the app should launch and boy howdy…nothing happens. There is one gotcha with mixing Anular with Electron – open up the file renderer-src/index.html and look for the base tag. Notice how its value is / well that is going to screw up all sorts of things when working with a filesystem, not URLs. Change that value to ./, save index.html and reload the Electron app (cmd+r or ctrl+r depending on your platform). Now look at that – we’ve got ourself an Angular app running inside Electron. Let me make one last tweak to show you how all of the watchers work. Pop open renderer-src/app/app.component.ts and locate the title attribute inside the AppComponent class. Change that to something more fun. I went with mp-irc Works! (not very fun I know). Now save that file, and watch as the compiler updates. Once you think that’s good to go jump into your Electron app and reload again to see your changes live.

That’s all for now – but this is only part 1. Next post will start digging into the nitty gritty of getting the renderer and main processses to talk to each other, plus maybe a little work on getting the IRC connections running.

Source Code

Check out the source for this part of the article on github

Worpdress on Dokku

I recently found Dokku when digging around the interwebs and decided it would be a really nice way to manage my sites/apps instead of installing environments willy-nilly on a server. So I set out to figure out how to get a basic blog up and running under Dokku. Turns out getting WordPress running isn’t terribly difficult. So here are the steps to follow to get things working:

  1. Install Dokku (obvious, but just in case you were wondering)
  2. Set up your local app
  3. Set up the remote app
    1. Set up databases
    2. Set up persistent storage
  4. Profit! (Sorry I had to)

  5. Install Dokku

I could walk you through all of the install steps, but really you should just go to Dokku’s documentation and follow the instructions there.

Note: I will admit that I cheated a bit here, and just used Digital Ocean’s prebuilt Dokku image. If you choose to go down that route, and use the smallest size of DO server you’ll want to take a look at how to add swap space (or [here] (https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04)) to your server.


2. Set up your local app

This is pretty boring, go and download wordpress to your machine. Pick somewhere one your machine to buld this project, I use ~/projects/blog. Within that folder, you will want to unpack the archive you downloaded before to a new directory, something like public. Install composer if you haven’t already, take a look at the composer documentation for that. Add a file in your project directory with the name composer.json and add the following as content (replacing the values in []):

    "name": "[your_blog_name]",
    "description": "[Some description]",
    "authors": [
            "name": "[Your Name]",
    "minimum-stability": "stable",
    "require": {
        "php": ">=5.6"

Open up a terminal and navigate to your project directory and run composer install to create the lock file.

3. Set up the remote app

Now on your remote server ssh in and create the app in dokku – dokku apps:create [app-name or domain]. Next we need to handle the database and persistent storage. First, let me set up the database. WordPress works most easily with mysql/mariadb so I need to install the dokku plugin for one of those two. I prefer mariadb as I like to avoid Oracle wherever possible, but use what you prefer. To install the mariadb plugin just run sudo dokku plugin:install https://github.com/dokku/dokku-mariadb.git mariadb and it will do all of the heavy lifting for you. Now that the plugin is installed, we need to create and link the database. First run dokku mariadb:create [db-name] to create the database container, then run dokku mariadb:link [db-name] [app-name] to add an environment variable to the remote app and allow access. You might want to copy the url that is shown as you will need it in the next section.

4. Update the local app config

Jump into wp-config-sample.php to make the needed changes. First things first look at the DSN that we grabbed before (that’s the connection URL that looks something like mysql://mariadb:[password@[hostname]:3306/[database]). You need the user, password, host and database name to proceed. Once you have those look for define(DB_NAME, ''), define(DB_USER, ''), define(DB_PASSWORD, '') and define(DB_HOST, '') and enter the values from the DSN where appropriate. The only other thing we should need to do in the config before saving it is add some salts. Go to WordPress secret-key service and replace the values in your config file with the ones generated by that webpage.

5. Add a persistent volume

Back on the server we need to create a persistent volume to store file uploads and any tweaks we make to the theme or plugins. So run dokku storage:mount [app-name] [host-path]:/app/public/wp-content which will create a permanent mount from the host to the container. For the host path the documentation recommends using /var/lib/dokku/data/storage, but to allow for multiple apps I append the app name to the end – /var/lib/dokku/data/storage/[app-name].

6. Commit and run

If you haven’t done so already hop into a terminal on your local machine and initialize a git repository with git init. Then you need to add the dokku remote with git remote add dokku dokku@[your-ip-or-hostname]:[app-name]. Commit your changes and the push to dokku with git push dokku master. If everything is hunky dory (and I haven’t accidentally left out a step…) you should see a bunch of output from dokku on your server and once that’s done your workdpress install will be up. Once that is done hit [app-name].hostname.tldd to start the actual WordPress install.

I hope this helps someone (or future me) to get started with dokku.