Index Thing


The NW.js Thing

The NW.js Page

Basically this page encapsulates some of the experience I have had with using NW.js

A short history:
NW.js started out as Node-Webkit which basically uses the Chrome/Chromium browser in conjunction with Node.js providing a unified framework for the client/server contexts based on javascript - it allows cross-platform development of desktop applications utilizing web technologies (HTML/CSS/JS).
It should be noted that a similar project exists called Electron (formerly Atom) which is gaining a lot of traction with devs/larger companies (eg: Microsoft with Visual Studio Code).
Unfortunately I notice a number of apps formerly built with NW.js have now moved to Electron and the resourcing of Electron looks more plentiful - looking a bit like a VHS/Betamax scenario however I'm happy enough with NW.js although I find understanding the contexts a bit tricky but I don't want to have to work out how Electron does stuff ....

Not sure I can remember how I came across this but at the time I was looking for a technology to make apps for the desktop that was also cross-platform. Q7Basic which I was using for a couple of projects had been abandoned and YWE although still useful was no longer supported


Basic/Visual Basic projects
Visual Basic was just getting too cumbersome with .NET frameworks, etc. Tried Q7Basic which was excellent but unfortunately has been abandoned by the sole owner. Q7Basic was built on Qt4 and had some limitations which would need delving into the C++ world of Qt which is a bit much for me. I also found the compilation time needed for projects was getting tiresome. The cross-platform capability was a bit limited.

Konfabulator/Yahoo Widgets Engine projects
This was a great wee app that still generally works on later OSes but has been abandoned by Yahoo for a few years now. I used this for a number of widgets and being based on web technologies it didn't require huge amounts of compilation time.


NW.js ticks a lot of boxes for me -
   Cross-platform (OSX/Win/Linux)
   Web technologies (HTML/CSS/JS)
   No compilation required
   Easy to encapsulate web sites into desktop apps
   Transparency to allow widget type functionality

Current State of the Play:
NW.js has been updated quite regularly (inline with the Chromium browser) since the architectural change from Node-Webkit 0.12.3 to NW.js 0.13 and currently 0.35 works pretty well.

On balance for me (a non-professional hobbyist) NW.js offers a great way to build cross-platform desktop apps that work relatively easily but be aware that documentation can be quite sparse in places (Basic tended to be great in this respect). NW.js offers me a good replacement for Visual Basic/Basic (aside from the lack of an IDE - I think it is happening but likely to be online only eg: Macaw).

Documentation has improved a bit but the wiki that exists still adds confusion - it was done for 0.12 and earlier and only some parts are good for the 0.13 or later versions. Unfortunately a lot of forum references still relate to the old wiki which can be confusing.
The official docs usually give enough for professional developers to use but for the lesser skilled hobbyist needing real world examples it will involve a lot of searching/trawling to understand some stuff.
A particular hassle is with plugins/extensions for audio/flash/etc - the docs will say it can be done and give a short one-liner but there is very little by way of example on how to do it.
I have included sections below to try and fill out areas that I have come across which may help some folk.

There are quite a lot of books on Node.js and a few on NW.js in particular however a lot of the existing books/documents/sample projects (as at early 2016) are still based on 0.12.3 or earlier. With the advent of the re-architected 0.13 and later docs can be a bit thin and prior knowledge of the Chrome/Chromium project is assumed.
One book I have found to be excellent is written by Paul Jensen.
It is currently available via the Manning Early Access Program (MEAP) and is titled -
Cross-Platform Desktop Applications with Node, Electron and NW.js HERE

Bug Support:
The team available to fix bugs with NW.js is extremely small (King Roger Wang and a couple of others) but important bugs are usually dealt with promptly. I find it helps a lot by providing a wee sample app that demonstrates the problem and therefore 'puts it on a plate' for the developer - quick turnaround may ensue. P1 bugs are generally quick (crash bugs are generally P1), P2 less so but a sample helps.

Useful NW.js Links

NW.js site HERE the main site with docs, etc

Live Builds HERE useful for getting latest builds

Roger Wang Twitter Feed HERE Useful for short updates on NW.js project

NW.js site HERE the official NW.js mailing list

Node.js site HERE the main Node.js site with docs, etc

NPM site HERE tons of useful modules

Web2Executable HERE use for packaging Apps (NOTE: Python-based GUI - this repo is now unmaintained)

nw-builder HERE use for packaging Apps (NOTE: CLI - this repo struggles for maintainers but basically OK)

nwjs-builder-phoenix HERE use for packaging Apps (NOTE: CLI - this repo is now looking for new maintainer)

nw-autoupdater HERE Auto update tool for apps

node-appdmg HERE DMG packaging tool for OSX (note: is picky on the node module version)

Chromium Command Line Switches HERE used with chrome-arguments in package.json

Universal Graphical User Interface project HERE Courtesy The Jared Wilcurt - useful for learning

Gitter site HERE Good forum superbly held together by The Jared Wilcurt

StackOverflow HERE search for nwjs

Chromium site HERE Chromium download site (NW.js is based on Chromium code base)

NWjs Concepts/Packaging

Node-Webkit : Uses Node.js and Webkit browser (legacy)
NW transition : Uses io.js and Chrome browser with Blink rendering engine (legacy)
NW.js : Uses Node.js and Chrome browser with Blink rendering engine

OSX support is 64bit only with the later releases of NW.js - 0.29.0 or later supports OSX 10.10 onwards.
Windows: OK from Windows 7 onwards (32/64bit).
Legacy Windows: Vista using the Aero interface will be OK with transparency (not supported with later NW.js).
 XP/Vista non-Aero will work but will have problems with transparency since graphics layering is used rather than compositing (not supported with later NW.js).
Linux: There is 32/64bit support but may need particular versions of distros.

NW.js 0.14.x LTS supports XP.

If a NW.js binary is started outside an app folder (therefore no package.json found) the default window will show as -

The NW.js Default Screen

Typical OSX Project to produce a desktop App:

New Project :: - call it Hippo

I generally use two styles of App - normal desktop mode and transparent widget type, Hippo is setup as a widget style App.

=> App folder
=> Resources folder (Icons,plist,etc for project)
=> Info.plist file

App folder
=> package.json file (REQUIRED)
=> index.html (or similar REQUIRED for main in package.json)
=> node_modules folder (REQUIRED for NPM modules)
=> css folder
=> js folder
=> Resources folder (images,etc within application)

The NW.js binary can be placed in the App folder and if double-clicked will startup as the application. The binary will look for the package.json (also called the manifest) and execute it - the start page is generally specified as the main: parameter within the manifest.

When the application is run the support files will be placed in User/Library/Application Support/Hippo
Strange issues/problems with the app can sometimes be cured by deleting this folder and it will be recreated next time the app is run.

Using NPM modules ::

NWjs makes use of the NPM packaging system which gives quite a lot of flexibility in projects.

To use fs-extra with project called Hippo eg:
Use Terminal and navigate to Hippo project folder and then to App folder within then enter -

npm install fs-extra --save

This will install the npm module fs-extra into the node_modules folder within the app folder and the save command will write the dependencies into the package.json file of the app folder.

NOTE: NPM modules should be installed/uninstalled correctly to best avoid error issues during development.

Packaging the App ::

My packaging app of choice is now a custom version of nw-builder with a GUI frontend which creates cross-platform app packages.

I tend to develop on the OSX platform but nw-builder allows me to use the same source project to package for Win/Linux as well. It should be noted however that certain OS particular features may be easier to develop on the appropriate platform eg: transparent widgets on Windows will tend to require use of the context menu whereas the OSX native menu can still be used if desired. Windows also makes use of the registry quite a bit.
It is quite OK to use the same source folder arrangement on the Windows platform - the app can be run by simply dragging the app folder (containing package.json) onto the nw.exe binary.

NW Structure - Basic Layout of a Packaged App (OSX) using 0.12.3 (legacy)

NW Structure - Basic Layout of a Packaged App (OSX) using 0.13 or later

Download Hippo project source (ZIP) HERE
 Sample NW.js transparent widget type app called Hippo -
=> Unzip and place NWjs binary into the Hippo folder(contains package.json) - 0.14 or later
=> Double-click NW.js binary to run app

Use a builder app to package project if desired.

Using Audio/Video (MP3/MP4)

Since c. 0.22.1 NW.js has included the MP3 codecs (patent restrictions just expired). Pre-built codecs can be obtained from various sources - some work, some don't.

The iteufel GitHub repo is the best source for pre-built binaries -

OSX - libffmpeg.dylib
Win - ffmpeg.dll
Linux -

NWjs includes -
  vp8 & vp9
  pcm_u8, pcm_s16le, pcm_s24le, pcm_f32le, pcm_s16be & pcm_s24be
  mp3 (v0.22.1+)

iTeufel pre-built adds -

I guess that the status of codecs should be checked if apps are destined for commercial distribution however.

Using Flash

Basically everyone is running away from Adobe Flash as fast as they can but there is still a lot of legacy requirements out there.
Chrome no longer supports NPAPI plugins but now use Pepper Flash plugins (PPAPI). NW.js does not include a flash plugin but it can be obtained from Adobe.

The PepperFlash folder resides in the Internet Plug-Ins folder within the Chrome/Chromium Framework.framework package
This needs to be placed in the nwjs Framework.framework/Internet Plug-Ins folder of the NW.js binary
NOTE: NW.js requires a manifest.json file to accompany the PepperFlashPlayer.plugin and this is NOT provided in the Chrome/Chromium apps so here is an example - HERE - typical for use with PepperFlashPlayer.plugin
- download HERE

Using Webview Tag -

index.html -
<webview id="wbv" src="sound.swf" style="width:200px; height:100px" partition="trusted"></webview>

package.json -

   "webkit": {
      "plugins": true
   "webview": {
      "partitions": [
            "name": "trusted",
            "accessible_resources": [

Current status as at 0.32.0:
If PepperFlash is installed within the app and on the system NW.js seems to use the latest version available.
   eg: (checked on OSX)
         App Version       System Version    -->  App version used    -->  System version used
             N/A         -->  System version used                  N/A      -->  App version used

The PPAPI version of flash is available from Adobe for all OS types.

Handy manifest (package.json) settings

Transparency ClickThrough requires -
   "frame": false
   "resizable": false
   "chromium-args": "--disable-gpu --force-cpu-draw" (pre - 0.28)
   "chromium-args": "--disable-gpu-compositing --force-cpu-draw" (since 0.28)

Print Preview uses PDF plugin so requires -
   "plugin": true for webkit parameter

Full DevTool logging may require -
   "chromium-args" : "--mixed-context"

Debug logging (chrome_debug.log file in Application Support/<Appname> folder)    "chromium-args": "--enable-logging --v=1"


Storage of app specific settings (NWjs) -
~/Library/Application\ Support/<appname>
NOTE: Deleting this folder can sometimes clear unexplained errors and the folder will be re-created the next time the app is run.

Java Applet support ceased about 0.13 since later Chrome browsers no longer support it. Support exists in 0.12.3

PDF support is built in to NW.js

I have also noticed when doing restarts/reloads to test changes the first start is often buggy so I need to run a second test - I think there must be an obscure cache which has data from the last run in it.

Chrome Extension Support


"chromium-args" : "--load-extension" eg: "chromium-args" : "--load-extension=/Users/whateveruser/Desktop/fmkadmapgofadopljbjfkapdkoienihi"

Extension can be taken from chrome (unpacked).
chromium-args requires a full path - relative will not work.
eg: using react-devtools example -

"chromium-args" : "--load-extension=/Users/whateveruser/Desktop/fmkadmapgofadopljbjfkapdkoienihi"

"chrome-extension://*" needs to be placed in permissions of manifest.json inside extension folder

Drag and Drop

Plenty of descriptions on the web but my use case is usually for a file selection zone that will react to either a click for folder dialog or DnD of files directly.
Example below uses a bit of html layout trickery but works quite well.

Essential concept is place all of BODY content in newBody and apply ondragstart/ondragenter/ondragover/ondrop parameters - this kills all DnD within this DIV.
DnD zone DIV is created outside the newBody DIV and this allows DnD - it has an INPUT tag (with opacity of 0.01 to allow click-through) on top of a label div.

GREEN - DnD related code

BLUE - draggable related code

Although strictly not DnD content within the app window will tend to behave as per a normal browser where images can be dragged and the body content will move if 'swiped' whereas this is not a feature of desktop mode.
The blue code shows the tweaks needed - the img tag css could also be used to limit draggability (overflow: hidden; used to stop 'swiping' movement).
user-select: none; can also be placed in the BODY CSS to avoid selection/dragging of page text.


<body style="background-color: black; overflow: hidden;" class="yui3-skin-sam">

   <div id="newBody" style="position: absolute; display: block; text-align: center; width: 100%; height: 100%;" ondragstart="return false;" ondragenter="return false;" ondragover="return false;" ondrop="return false;">

      <div id="header">
         <div id="banner"><img src="assets/hc.png" draggable="false" style="width: 96px; height: 96px;" alt="banner" /></div>
         <img src="assets/pano.png" draggable="false" style="margin-left: 300px; width: 343px; height: 100px; border: none; border-radius: 10px;" />
         <br />
         <img id="proggo" src="assets/proggo.png" alt="Pending" draggable="false" style="position: absolute; display: block; top: 30px; left: 980px; width: 30px; height: 30px;" />

   <p id="currentSrc">Current Source Image:</p><textarea id="currentFile" rows="1" cols="120" style="resize: none;"></textarea>

   <!-- must remain outside newBody div -->
      <div id="filednd">
         <p id="newLabel">Select Source Image<br />Click to Choose or Drag/Drop file here</p>
         <input type="file" id="fileSelection" name="files[]" />
         <output id="list"></output>


#filednd {
   position: absolute;
   display: block;
   border: 2px dotted gray;
   border-radius: 8px;
   top: 20px;
   left: 950px;
   width: 300px;
   height: 80px;

   margin-left: auto;
   margin-right: auto;
   text-align: center;

#fileSelection {
   position: absolute;
   opacity: 0.01;
   top: 0px;
   left: 0px;
   width: 298px;
   height: 78px;


#newLabel {
   position: relative;
   top: 20px;
   color: gray;
   font: 13px "Comic Sans MS";

JS -

// ******************** Get Image File to process *****************************
* @param evt - listener trigger event to be processed
* @returns
function handleFileSelect(evt) {

   var fileToProcess =; // FileList object
   srcFile = fileToProcess[0].path;

   srcFileReal = srcFile;
   localStorage.pref_srcFileToProcess = srcFile; // make available as global
   localStorage.pref_firstStart = false;


// ***************************** Mainline **************************************
// Occurs on Load/reload

   if (localStorage.pref_firstStart == "true") { // this flag set in js code defined by main in package.json
      document.getElementById('filednd').style.borderColor = 'red';
   } else {
      document.getElementById('filednd').style.borderColor = 'darkorange';

      document.getElementById('currentFile').innerText = localStorage.pref_srcFileToProcess;
      var el = document.getElementById('currentFile');

   var tempo = document.getElementById('viewDng').classList;
   if (localStorage.pref_fileOutput == 'dng') {
   } else {


document.getElementById('fileSelection').addEventListener('change', handleFileSelect, false);

Project Building

The toolchain for NW.js is rather fragmented - project build/update tools tend to get left to the community rather than be integral to the NW.js project (shows lack of support from bigger companies/stronger developer base).

Build tools:
   nw-builder -> npm package available - CLI app using js - github repo limping along not very active.
   nwjs-builder-phoenix -> npm package available - CLI app using js - supercedes nwjs-builder - github repo more active.
   web2executable -> GUI app using Python - github repo no longer maintained

I was using web2executable which worked fairly well but since maintenance has ceased I have migrated to a custom build of nw-builder which underpins a homemade GUI.

Most builders will output a folder with executable files but further packaging (eg: DMG, MSI, EnigmaVB, etc) will require further tools. Many developers will choose CLI tools such as Grunt, Gulp, Yeoman, etc

Update Tools:
   Again Update tools are generally not available with the project and rely on the community to some extent (Electron is well supported in the updating stakes eg: Squirrel).

Signing Tools:
   I don't personally develop for the Mac App Store but tried to incorporate it in my builder GUI however documentation regarding signing is sparse and as a hobbyist I haven't paid the required yearly Developer's Signing Fee from Apple which is a required pre-requisite. The only MAS build for NW.js is using 0.19 (current build - 0.36) and it appears to be a resourcing issue to produce a later version.
It is difficult to differentiate between signing procedures for apps destined for the MAS and those that are distributed via normal download methods. I believe an app can be signed without using the MAS build but again the process is unclear and good examples lacking. It definitely looks like the OSX Gatekeeper will only let an app auto run if a correct signature is found (this means a yearly Developer fee folks).
The GateKeeper blocking is becoming a hassle because the option to allow unsigned apps in Sys Prefs has been removed in High Sierra (identified developers only) and unsigned apps will have to be manually authorised by the user on the first run.

Content Verification is also thrown into the mix and this works with caveats.
This basically provides a couple of files (verified_contents.json/computed_hashes.json) within the app that are used by NW.js to determine if content files have been altered. I can get it to work but due to outstanding bugs (#6540/#6541) implementation can't be done using just the latest build.

Important Changes

0.13.0 - Architectural changes (major)

0.14.7 - Last XP supported build

0.21.0 - CSS Grid supported

0.22.0 - Architectural change (symlinks used in nwjs Framework.framework bundle - upstream change)

0.22.1 - MP3 codec included - (patents expired)

0.23.0 - Headless Chromium supported

0.23.0 - Dramatic performance improvement with Source Code protection

0.24.4 - Helper Renaming supported - uses product_string parameter in package.json (if running an app using the standard nwjs binary this needs to be set as 'nwjs' otherwise should be the app name when packaged).

0.25.0 - Architectural change (minor - libffmpeg location moved up to parent folder)

0.25.2 (node 8.5.0) - fs.copyFile/copyFileSync supported

0.26.0 - Min OSX 10.9 required

0.29.0 - Widevine supported

0.29.0 - Min OSX 10.10 required

0.35.4 - Architectural change - moves NW application window implementation from Chrome App window to Chromium browser window (only with --enable-features=nw2 switch)

0.36.0 - Minor architectural change - libffmpeg in OSX moved back nwjs Framework.framework as 10.9 no longer supported

Application Package Renaming

eg: App name is foobar

package.json --> new parameter --v
      product_string: foobar

Contents/Info.plist - CFBundleDisplayName --> update to foobar
Contents/Resources/en.lproj/InfoPlist.strings - CFBundleDisplayName --> update to foobar
Contents/Versions/n.n.n.n/nwjs Helper --> rename to 'foobar Helper'
Contents/Versions/n.n.n.n/nwjs --v
      - CFBundleDisplayName --> update to foobar
      - CFBundleExecutable --> update to foobar (avoid broken icon on Helper package)
      - CFBundleName --> update to foobar
Contents/Versions/n.n.n.n/nwjs --> rename to 'foobar'

Widevine Support

Sourcing -

OSX - included in NWjs but is in libraries folder in versions branch
Win32 - Chrome Downloads - install and see below
Win64 - Chrome Downloads - install and see below
Linux32 - Chrome Downloads - unavailable
Linux64 - Chrome Downloads - google-chrome-stable_current_amd64.deb - unzip and drill data.tar.xz folder - data/opt/google/chrome/

- OSX:

      Contents/Versions/66.0.3359.117/nwjs Framework.framework/Libraries/WidevineCDM/ ( package)

- On a 64-bit #windows:

      C:\Program Files (x86)/Google/Chrome/Application/66.0.3359.117/WidevineCDM/

- On a 32-bit #windows:

      C:\Program Files/Google/Chrome/Application/66.0.3359.117/WidevineCDM/

Application Start Modes

Apps generally start from NW.js binary looking up the package.json (manifest) file and checking the "main": setting.
   "main": "index.html", --- app will start in browser context with the html page and css/js will be introduced in normal web fashion.

   "main": "js/app.js", --- app will start in node/javascript context and html pages are generated via etc.

(Electron tends to use the JS start method, NW.js default is HTML but is happy with either).

I tend not to use the CLI very much during development but NW.js is easy to use in a GUI environment
eg: an app called hippo (this example assumes MacOS) -

hippo - appfolder

Place the NW.js package into the appfolder and double click - it will look for the manifest and start according to the 'main' setting.
Since v0.24.4 it is important that the manifest 'product_string' setting is 'nwjs' otherwise NW.js will start but the app will not operate.

When the app is packaged (with nw-builder or suchlike) the app name will probably change (in this case - "name": "hippo", "product_string": "hippo",) but the app copy of NW.js will have been updated with the new name. If the package is opened the folder structure will contain a file called 'hippo Helper' whereas a default NW.js package it would be 'nwjs Helper'.

Node Module Versions

eg: Terminal shows - Expected 47, got 46 (also sometimes 57, got 46)

Can happen if node that npm is using is upgraded and the installed modules haven't been upgraded.
eg: v4.2.2 on system was upgraded to v8.1.3 - a module (appdmg) had been installed in a project with npm using 4.2.2 and when npm was running on 8.1.3 the error occurred.
The fix was to re-install the appdmg module with npm running 8.1.3

46 - 4.x
47 - 5.x
48 - 6.x
51 - 7.x
57 - 8.x
59 - 9.x
64 - 10.x
67 - 11.x