Creating Your First Desktop App With HTML, JS and Node-WebKit

Download

These days you can do pretty much anything with JavaScript and HTML. Thanks to Node-WebKit, we can even create desktop applications that feel native, and have full access to every part of the operating system. In this short tutorial, we will show you how to create a simple desktop application using Node-WebKit, which combines jQuery and a few Node.js modules.

Node-WebKit is a combination of Node.js and an embedded WebKit browser. The JavaScript code that you write is executed in a special environment and has access to both standard browser APIs and Node.js. Sounds interesting? Keep reading!

Update (15th Jan 2015) - Just after a week of publishing this tutorial, node-webkit was renamed to NW.js. For now, this tutorial is perfectly compatible with it. In the future we might update it if there are any changes.

Installing Node-WebKit

For developing applications, you will need to download the node-webkit executable, and call it from your terminal when you want to run your code. (Later you can package everything in a single program so your users can only click an icon to start it).

Head over to the project page and download the executable that is built for your operating system. Extract the archive somewhere on your computer. To start it, you need to do this in your terminal:

# If you are on linux/osx

/path/to/node-webkit/nw /your/project/folder

# If you are on windows

C:\path\to\node-webkit\nw.exe C:\your\project\folder

# (the paths are only for illustrative purposes, any folder will do)

This will open a new node-webkit window and print a bunch of debug messages in your terminal.

You can optionally add the extracted node-webkit folder to your PATH, so that it is available as the nw command from your terminal.

Your First Application

There is a Download button near the top of this article. Click it and get a zip with a sample app that we prepared for you. It fetches the most recent articles on Tutorialzine from our RSS feed and turns them into a cool looking 3D carousel using jQuery Flipster.

nw-app-tree.png
Directory Structure

Once you extract it, you will see the files above. From here this looks like a standard static website. However, it won't work if you simply double click index.html - it requires Node.js modules, which is invalid in a web browser. To run it, CD into this folder, and try running the app with this command:

/path/to/node-webkit/nw .

This will show our glorious desktop app.

rsz_node-webkit1.jpg
Our node-webkit app

How it was made

It all starts with the package.json file, which node-webkit looks up when starting. It describes what node-webkit should load and various parameters of the window.

package.json

{
  "name": "nw-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.html",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "window": {
    "toolbar": false,
    "width": 800,
    "height": 500
  },
  "license": "ISC",
  "dependencies": {
    "pretty-bytes": "^1.0.2"
  }
}

The window property in this file tells node-webkit to open a new window 800 by 500px and hide the toolbar. The file pointed to by the main property will be loaded. In our case this is index.html:

index.html

<!DOCTYPE html>
<html>
<head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Tutorialzine Node-Webkit Experiment</title>

    <link rel="stylesheet" href="./css/jquery.flipster.min.css">
    <link rel="stylesheet" href="./css/styles.css">

</head>
<body>

    <div class="flipster">
        <ul>
            <!-- Tutorialzine's latest articles will show here -->
        </ul>
    </div>

    <p class="stats"></p>

    <script src="./js/jquery.min.js"></script>
    <script src="./js/jquery.flipster.min.js"></script>
    <script src="./js/script.js"></script>
</body>
</html>

And finally, here is our JavaScript file. This is where it gets interesting!

js/script.js

// Mixing jQuery and Node.js code in the same file? Yes please!

$(function(){

    // Display some statistic about this computer, using node's os module.

    var os = require('os');
    var prettyBytes = require('pretty-bytes');

    $('.stats').append('Number of cpu cores: <span>' + os.cpus().length + '</span>');
    $('.stats').append('Free memory: <span>' + prettyBytes(os.freemem())+ '</span>');

    // Node webkit's native UI library. We will need it for later
    var gui = require('nw.gui');

    // Fetch the recent posts on Tutorialzine

    var ul = $('.flipster ul');

    // The same-origin security policy doesn't apply to node-webkit, so we can
    // send ajax request to other sites. Let's fetch Tutorialzine's rss feed:

    $.get('http://feeds.feedburner.com/Tutorialzine', function(response){

        var rss = $(response);

        // Find all articles in the RSS feed:

        rss.find('item').each(function(){
            var item = $(this);

            var content = item.find('encoded').html().split('</a></div>')[0]+'</a></div>';
            var urlRegex = /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?/g;

            // Fetch the first image of the article
            var imageSource = content.match(urlRegex)[1];

            // Create a li item for every article, and append it to the unordered list

            var li = $('<li><img /><a target="_blank"></a></li>');

            li.find('a')
                .attr('href', item.find('link').text())
                .text(item.find("title").text());

            li.find('img').attr('src', imageSource);

            li.appendTo(ul);

        });

        // Initialize the flipster plugin

        $('.flipster').flipster({
            style: 'carousel'
        });

        // When an article is clicked, open the page in the system default browser.
        // Otherwise it would open it in the node-webkit window which is not what we want.

        $('.flipster').on('click', 'a', function (e) {

            e.preventDefault();

            // Open URL with default browser.
            gui.Shell.openExternal(e.target.href);

        });

    });

});

Notice that we are accessing Tutorialzine's RSS feed directly with jQuery, even though it is on a different domain. This is not possible in a browser, but Node-WebKit removes this limitation to make development of desktop applications easier.

Here are the node modules we've used:

  • Shell - A node webkit module that provides a collection of APIs that do desktop related jobs.
  • OS - The built-in Node.js OS module, which has a method that returns the amount of free system memory in bytes.
  • Pretty Bytes - Convert bytes to a human readable string: 1337 → 1.34 kB.

Our project also includes jQuery and the jQuery-flipster plugin, and that's pretty much it!

Packaging and Distribution

You most certainly don't want your users to go through the same steps in order to run you application. You wan't to package it in a standalone program, and open it by simply double clicking it.

Packaging node-webkit apps for multiple operating systems takes a lot of work to do manually. But there are libraries that do this for you. We tried this npm module - https://github.com/mllrsohn/node-webkit-builder, and it worked pretty well.

The only disadvantage is that the executable files have a large size (they can easily hit 40-50mb) , because they pack a stripped down webkit browser and node.js together with your code and assets. This makes it rather impractical for small desktop apps (such as ours), but for larger apps it is worth a look.

Conclusion

Node-webkit is a powerful tool that opens a lot of doors to web developers. With it, you can easily create companion apps for your web services and build desktop clients which have full access to the users's computer.

You can read more about node-webkit on their wiki.

Bootstrap Studio

The revolutionary web design tool for creating responsive websites and apps.

Learn more

Related Articles

Martin Angelov

There are a lot of popular apps that use Node-WebKit. Some of them are Wunderlist, Spotify and Popcorn Time.

Also you might want to take a look at Atom Shell, which is a newer project, also attempting to bring node.js and webkit together. It is used in the Atom editor by Github.

Thank you for reading our article! We hope you like it :)

Seghir Nadir

I think that Atom shell is the best one so far, the documentations in has and the community ar great as well

Very well written. JavaScript is now on desktop, client and server. Good Job!

Good work Great job and very helpful article for new developers

andy matthews

Another good way to get up and running with Node Webkit is this Node Webkit generator:

https://github.com/Dica-Developer/generator-node-webkit

Rudrakshya Barman

How to add database functionality or api? like connect to mysql database or sqllite?

Martin Angelov

If you want to connect to a database that is hosted on a server somewhere, you will need to build an API first, and access it from the application. If you wish to use a database locally, you can use WebSQL, which is supported by node-webkit. Alternatively, you may directly install an SQLite library via NPM, but I haven't used that.

Rob Evans

You can also use a JavaScript-based database such as ForerunnerDB which gives you MongoDB-like queries and CRUD in your browser / node.js project without installing MongoDB. (http://www.forerunnerdb.com)

zhangmingxing

The line with code (
var content = item.find('encoded').html().split('</a>')[0]+'</a>';
) return an error "Cannot call method 'split' of undefined "; I changed html() to text() and it worked.

should it be like this? i'm newbie to learn node and javascript and webkit, please help me. i'm not sure this is my IDE's mistake or not. thank you.

This helped run the demo---thank you for providing a workaround.

Thanks so much for publishing this, you just got me started learning Node.js and NW for creating desktop apps.

By the way, for anyone wanting to distribute their apps as binaries (like myapp.exe on Win or myapp.app on Mac), I successfully used Web2Executable (https://github.com/jyapayne/Web2Executable) - still beta, but works very well.

Thank you! :)

Hey,
i want to create a desktop app witch i can distribute, but the link with the tutorial you linked here isn't working anymore.
Greetings from Germany

HI Danny,

I'm triing to run the app on windows and I get the error:

Error Loading Extension
Failed to load extension from: D:\Develop\nwjs_app. Could not load background script 'pretty-bytes.js'.

¿There is a way to run the example on windows?

best regards,

Hello,

I have 2 pages, index html and welcome.html, how can I navigate to welcome.html from index.html using nw.js? please help.

I have one chrome app which we have developed and it has dependent on google(Like chromeApp chrome remote desktop) so i want to move out from google so what i use ? electron or NW

Artem Razin

If someone is interested, here the project to build the nw.js based app into a self-contained exe file (supports native modules).