Node Webkit powered Dashboard application

This post is part 2 of 7 in the series Node Webkit Apps
Tweet about this on TwitterShare on LinkedIn0Share on Google+4Share on Reddit0Buffer this pageFlattr the authorEmail this to someonePrint this page

Node Webkit Powered Dashboard app

In this post, we will be building a full fledged desktop application using node webkit and web technologies. We are going to build a dashboard app called myDashboard. The app will show the Weather report, Google Map, Flickr images and a Calendar. The final product would look like

Screen Shot 2014-07-20 at 3.47.12 pmScreen Shot 2014-07-20 at 3.46.14 pmScreen Shot 2014-07-20 at 3.48.13 pmScreen Shot 2014-07-20 at 3.48.33 pmScreen Shot 2014-07-20 at 3.47.55 pmYou can get the complete code here. The final installers are around 200MB, hence did not share the installer.

So, let us see how we can build this app.

Contents

Prerequisites

To build desktop apps, you need to have a general awareness on how web apps need to behave when on a desktop. This includes the menus, toolbars etc. You need to be also aware of the fact that internet is not always present and there might permissions issues to run the application.

You also need to have a good understanding of web technologies (HTML, CSS and JS), REST API, oAuth etc. Node webkit uses the power of Node js and Webkit engine to provide a platform to run Web apps driven by Nodejs on a desktop.

Before you continue, please go through Hello Node and Node Webkit – Build Desktop Apps with Node and Web Technologies.

Getting Started

As mentioned earlier, we are going to build a Dashboard application. The first thing we are going to do is analyse what we are going to show in the dashboard.

So, for this dashboard app, we are going to have a login and a register screen. We will also implement a lock screen for our dashboard app. On the main page, we are going to show a Weather report, a Google map and a few images from Flickr. Apart from these, we will also show a calendar.

We will let the user configure the location for the Weather as well the location where the map will be centered. We will also let the user provide the tags with which the Flickr search is made.

Now, we have an idea what we are going to do. It is up to you, if you want to design your application first or if you are lazy like me you will be searching for a Admin Dashboard template.

After a quick search. I found AdminLTE Dasboard and Control Panel Template which in my opinion is one of the best Free Admin templates out there. Kudos to Abdullah Almsaeed for open sourcing the template.

We will be consuming this template and optimizing a couple of things for desktop apps.

Begin Development

First, create a new folder named myDashboard. Next, create a new folder inside it named template. We will be dumping the template here and pick only the required components.

Download the template into the template folder and unzip it.

Next, inside myDashboard folder, download the node-webkit libs and unzip it. Rename the unzipped folder to nw and get rid of the node-webkit zip file.

Finally, create a new folder named development. This is where we do all the development.

The final folder structure would be Screen Shot 2014-07-20 at 5.57.44 pm

Now, open a new terminal/prompt inside the development folder. We will initialize a new node project. Run

npm init

and fill it up like

Screen Shot 2014-07-20 at 5.20.59 pm

This is the default node specific package.json. Now, we will be adding the dashboard app related configs. The final package.json would look like

Now, inside the development folder, create a new file named index.html. This will be our starter file and fill it up like

Now, we will run the app. We have 2 ways of running the app.

First way is to zip all the contents of development folder and launching it using the nw executable we have downloaded earlier. This is a very very very tedious process when the app starts to grow.

Second way is to configure sublime text to build the app for us (recommended). Check Debugging with Sublime Text 2 and 3 for more info.

Once this is configured, open index.html and navigate to tools and select node-webkit as the build system

Screen Shot 2014-07-20 at 5.31.35 pm

Now, to run the app tools > build or Ctrl + B or Command + B and you should see the app launch and the Hello World  message.

During development you can set  "toolbar": true to access the dev tools.

Continue Development

Now, we have set up the basic project. Let us add the required features. Before we do that, I would highly recommend going through the entire template again. This will give you an idea as what all features are already implemented and available to be directly consumed.

First up, we are going to implement is the registration and login feature. Before that, we will give a structure to the app. Inside development folder, create a new folder named assets. Inside assets create 4 folders named cssjs, img, fonts. 

Since I have already implemented the app, I know what all files we would be needing. So we will directly copy the files needed for the complete project.

JS folder : Copy

  • myDashboard/template/AdminLTE-master/js/bootstrap.min.js to myDashboard/development/assets/js/
  • myDashboard/template/AdminLTE-master/js/jquery-ui-1.10.3.min.js to myDashboard/development/assets/js/
  • myDashboard/template/AdminLTE-master/js/AdminLTE/app.js to myDashboard/development/assets/js/
  • myDashboard/template/AdminLTE-master/js/plugins/fullcalendar/fullcalendar.min.js to myDashboard/development/assets/js/
  • Download a copy of http://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js to myDashboard/development/assets/js/

CSS folder : Copy

  • myDashboard/template/AdminLTE-master/css/AdminLTE.css to myDashboard/development/assets/css/
  • myDashboard/template/AdminLTE-master/css/bootstrap.min.css to myDashboard/development/assets/css/
  • myDashboard/template/AdminLTE-master/css/font-awesome.min.css to myDashboard/development/assets/css/
  • myDashboard/template/AdminLTE-master/css/ionicons.min.css to myDashboard/development/assets/css/
  • myDashboard/template/AdminLTE-master/css/fullcalendar/fullcalendar.css to myDashboard/development/assets/css/

Images folder : Copy

  • myDashboard/template/AdminLTE-master/img/avatar5.png to myDashboard/development/assets/img/
  • myDashboard/template/AdminLTE-master/img/blur-background09.jpg to myDashboard/development/assets/img/

Fonts folder : Copy

  • myDashboard/template/AdminLTE-master/fonts to myDashboard/development/assets/fonts/

Once this tedious task is done, you need not worry about resources any more.

index.html will contain the login screen. You can refer myDashboard/template/AdminLTE-master/pages/examples/login.html for the login page. I have taken then above page, removed a few imports and fields and made it like

Note : We will get to dash.authUser() in a moment.

Save the file and run the app (cmd + b or ctrl + b). And you should see the login screen. Screen Shot 2014-07-20 at 6.13.14 pmThe page also includes simple validations.

Before we get started with the authentication logic, we will build the register screen too. Create a new file at the same level as index.html and name it register.html. Copy the below markup to register.html

Note : We will get to dash.registerUser() in a moment.

Save and run the app, you will see the login screen. At the bottom, click on the ‘Register a new account` and you should see the registration screen

Screen Shot 2014-07-20 at 6.18.11 pm

with some old school jQuery validations.

Now, let us build the authentication logic. To store the user details, we will be using a node module named diskDB. And we will be using bcrypt-nodejs node package to encrypt the passwords while saving and also to compare them.

Back to terminal/prompt run

npm i --save diskdb bcrypt-nodejs

This will pull down the required dependencies.

With the power of node-webkit, you can run node modules inside your browser window. So to create an illusion that the node modules are maintained elsewhere, we will be creating a new folder named controller and then writing our node module related logic here. This may be called as Separation of Concerns when we are developing  a node-webkit app.

So, create a new folder named controller at the root of the development folder. Create another folder name collections at the same level as controller. This folder will hold our JSON files. Next, create a new file named auth.js inside the controller folder. Update auth.js like

There are quite a lot of things going on here. First, refer diskDB and bcrypt-nodejs to understand what they do.

  • Line 7 : We create a register method that takes the user’s name, user id and password as arguments
  • Line 15 : We check if a user with same ID already exists. If yes, we return 0
  • Line 20 : If everything is fine, we will save the user’s details in the database and call the  populateUser()  to create a “session“.
  • Line 28 : We authenticate the user by taking the credentials entered on the login page and we will respond with the appropriate codes.
  • Line 64 : We save the user object in the local storage. If the object exists, it means the user is logged in.
  • Line 53 : We remove the user and settings object. This will clear the session

Back to register.html add the below lines just before the end of head tag.

Save all the files and run the app. Navigate to the register screen and fill up the form and submit. If everything goes well, you should see a blank screen (settings.html).

Terminate the app and relaunch it and you should see the sign in screen again. Now, click on the gear icon next to the URL bar in the app (which will be visible after you have set toolbar to true in package.json) and you should see the dev tools come up. Click on Resources tab then Local Storage and you should see

Screen Shot 2014-07-20 at 6.54.10 pm

This means that our user and session have been successfully created. Alternatively you can navigate to development/collections/users.json and you should see the user and the details

Sweet right?

Now, open index.html, we will integrate the login logic. Just before the head end tag, add the below code

Note : We will uncomment the above line in script once the dashboard.html is ready.

Save all files and relaunch. Login with the registered credentials and you should be able to login. And you will see the same blank screen (settings.html).

Now, we will build the setting.html. This file will store the user specific settings like his locations and the flick search terms. This will help us personalize the dashboard to the user. Since this is a demo app, we will capture only the said two.

At the root of development folder, create a new file named settings.html. Update it like

Save all files, launch the app. If you have not deleted the local storage entries, you should see the Settings page. Else login and you will see the same.

Now we will write the logic to save the user specific settings. Inside controller folder, create a new file named settings.js. Update it like

Save all the files and relaunch the app. On the settings page, fill it up and click on Save Settings. If things go well, you should see a blank page (dashboard.html). Click on the back button on the toolbar and you should see the settings page with the save values and the local storage will look like

Screen Shot 2014-07-20 at 7.11.18 pm

With this, we have completed the registration and login process. Now we will work on the Dashboard page.

At the root of development folder, create a new file named dashboard.html. Update it like

Standard markup and scripts. You will understand as you read the file. Line nos 205, 208 and 211 refer our widgets, which we will create soon. Line 198 registers the Sign Out and calls the method in auth.js.

When you save all the files and run, you should see

Screen Shot 2014-07-20 at 7.20.04 pmAwesome! Our dashboard structure is ready.

Next, we will implement the lock screen. If the user wants to lock the app, he can do so with this feature. The lock screen does not really make sense here, but you can see the kind of options this feature opens up.

Create a new file named lockscreen.html inside the development folder and fill it up like

Next, open index.html and uncomment the line in script tag we have commented earlier.

Save all the files, launch the app, click on Lock Screen on the dashboard page and you should see

Screen Shot 2014-07-20 at 7.26.07 pmNow, enter the password and click on the arrow. If the password is valid, you will see the dashboard again. Or you click on “Sign in as a different user” and the current user will be logged off and you can login again with a different user.

Now, you can start feeling the potential of node webkit. The things which you can do with it! Hey! I was excited too..  

Next, we will create the widgets on the page. Create a new folder named widgets inside the development folder. We will place each widget here to keep things a bit structured.

Create a new file named weather.html. This widget will contact the Yahoo weather service and get the data for the location configured in the settings. If the user has not set any location, we will use ‘New York’.

This widget show cases how you can integrate a node module with a UI. Open weather.html and add the below code

Some styles and markup. The data will be coming from a node module named weather-js. Back to terminal/prompt run

npm i --save weather-js

Next, create a new file named weather.js inside the controller folder and add the below code.

When the widget is injected into the dashboard, the script inside the weather.html will  call the getWeather() and the response will be parsed and a HTML will be built.

Save all the files and run. I have set my location to Hyderabad and this is how my dashboard looks

Screen Shot 2014-07-20 at 7.47.50 pm

Sweet! and it is drizzling outside!

Now, create a new file named maps.html inside the widgets folder. This will consist of the logic to display the map. Update the file like

In this file, we will fetch the location from the localstorage, pass it to geocoder service and get the position. Then we will generated a map based on this position.

Save all the files and run the app. You should see

Screen Shot 2014-07-20 at 7.51.39 pmFinally, we will get a few images from flickr and display it on the dashboard to make it complete. Create a new file named flickr.html inside the widgets folder and update it like

Save all the files and run the app. I have updated my settings to search for clouds and this is how my dashboard looks

Screen Shot 2014-07-20 at 7.54.30 pm

To complete the app, we will add another page like dashboard and show a calendar. This feature will kind of sort of make this app a dashboard-ish desktop app.

At the root of development folder create a new file named calender.html. Open calender.html and update it like

Save all the files and run the app. You should see

Screen Shot 2014-07-20 at 8.00.07 pmThis completes our Desktop dashboard. Simple sweet and awesome!

Distributing the application

Our app is ready to be distributed. You can follow the steps here to build an installer. Do not forget to set  "toolbar": false and clean up the data before publishing.

Hope you got an idea as how to build node webkit apps easily.


Thanks for reading! Do comment.
@arvindr21

Series Navigation<< Node Webkit – Build Desktop Apps with Node and Web TechnologiesNode webkit and Angularjs – A MovieStub App >>
Tweet about this on TwitterShare on LinkedIn0Share on Google+4Share on Reddit0Buffer this pageFlattr the authorEmail this to someonePrint this page
  • Angelo V. Merlo

    first thank you for the great tutorial, I would like to help me, as I do to start the application with the window maximized? Thank you very much!

  • DrZed

    Hey Arvind, thanks a million for doing these great tutorials. Just curious, have you tried (or is it possible) to run a Node WebKit app in docker – using containerisation?

  • Nelson Rodriguez

    Hi and thank a lot for sharing! Thinking in phonegap app what will be my procedure to achieve the même project? When you say wrapping th main template in cordova what do you mens exactly? I saw you other tutorial using framework7 to phonegap but it’s not the same case. Thanks a lot!

  • Pradeep Shnakar

    I have created a nwjs application and I have created the distribution package using nw-builder as sudo nwbuild -p linux -v 0.12.3 -o ~/Documents/output/ /home/path/to/application/files/ and it was created successfully. I used diskdb for data storage by following ur tutorial series.

    The problem is, when i save some data records and close the application and next time when i open the application, previously saved data is unavailable..! When I made toolbar: true in my package.json file i observed that each time the chromium webkit open as a temporary folder with temp link as, file:///tmp/.org.chromium.Chromium.fK2Img/login.html, file:///tmp/.org.chromium.Chromium.dDiSrR/login.html etc. How can I solve the same?

  • Brian Schermerhorn

    How would one interact with the native features of an OS? This mostly just feels like it’s a web app on a desktop. Are there limitations to what you can do with NW?
    Thanks for the tutorial =)

  • Jonathan Willian

    Well, at first, THANK YOU SO MUCH!
    This really save my life, for real!
    I’m starting coding with NW.js and your article helped a lot, it’s a very well done tutorial.
    Now I can do a lot of thing just because of you, so thanks again!
    Keep the good work, sir, and sorry about the bad English.

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Thanks Jonathan!

  • He Zhang

    Thanks for sharing. It looks awesome! One thing I am confused is that I see you use diskdb module to store user data. But it’s local storage in each end-user’c PC, right? So does this mean if someone sign up in one PC but he can’t login in another PC? In real product should we use something like MongoDB hosted in cloud to store user data? Sorry I’m pretty new to desktop apps.

    Thank you in advance!

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hello He Zhang. Yes, you need to use MongoDB for those purposes. But do remember that this may be used offline also, so you may not have access to MongoDB all the time. So for that you can use the online/offline event to detect if the user is online/offline and if the user is offline, you can save data on the user’s machine/diskDB. And once he goes back online you can sync it with MongoDB.

      The main challenge here is password management. If the user is offline, you should be still able to log the user in. So, you need to decide, if diskDB should store a copy of the user’s credentials. This is a design decision you need to make.

      Thanks.

      • ellipee

        Great tutorial, and thank you for it. but will be glad to see a bit of the implementation of the online/offline event.

  • Viktor Trush

    Awesome tutorial.

    Would it be possible to distribute this application to Adroid and iOS devices?

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Thanks Viktor. Not directly. You can wrap the main template in Cordova to achieve that.

  • http://almasaeedstudio.com Abdullah Almsaeed

    Amazing use of AdminLTE! Thanks for sharing such an amazing tutorial.

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Thanks Abdullah! Thank you for open sourcing this awesome template.

  • Jagdeep Sahdeva

    Hi Arvind Thanks for sharing. I noticed that the index.html is missing . This should be just after the tag. This will fix the error reported by Monique.

  • Monique

    Hello Arvind, I have run into a problem following the tutorial, I am getting an error after adding in the auth.js file. Before that point the app ran perfectly. So after adding the authorisation logic I relaunched the app, clicked on register and when I try and create an account I get this error:

    TypeError: Cannot read property ‘findOne’ of undefined
    at Object.dash.registerUser

    Any ideas on how to solve this? Your help will be very much appreciated :) I am still learning

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hello Monique, this error is because you have not installed/included diskdb node module. You need to run

      This should solve the issue.

      Thanks.

      • Monique

        This is my folder structure (attached). I ran the npm i diskdb again but still errors out

        • http://thejackalofjavascript.com/ Arvind Ravulavaru

          Hello Monique, HTML and JSON files need to be outside the node_modules folder at the root of the development folder.. Please refer : https://github.com/arvindr21/mydashboard/tree/master/development

          • Shoalai

            Hi Arvind,

            First i’d like to say thank you so much for sharing this with us, much appreciate!

            I am experiencing the same error as Monique and I would really like your assistance in solving the “Cannot read property ‘findOne’ of undefined” problem.

            As per your suggestion, I have all my files (HTML and JSON) outside the node_modules folder. However am still getting the same error.

            Any suggestion?

            Kind Regards,

            Shoalai

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            Thanks! Can you please share a screenshot of your folder structure, I can help you better.

          • Gerald

            Hi Arvind, I’m getting the same error as Shoalai. Plz enlighten me on how to interact with the diskDB. It works fine when launching from sublime but not from installer created by nodebob.

  • Bruno Seixas

    I havent read all the article but i got to say, thanks for sharing 😉
    That open-source AdminLTE team is pure amazing.

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Thanks Bruno!. And yes the template is awesome!