Node-Webkit Development

I’m in the process of porting RiddleMeThis from Realbasic (er Xojo) to Node-Webkit (henceforth nw). The latest version of nw allows full menu customization, which means you can produce pretty decently behaved applications with it, and they have the advantage of launching almost instantly and being able to run the same codebase everywhere (including online and, using something like PhoneGap, on mobile). It has the potential to be cross-platform nirvana.

Now, there are IDEs for nw, but I’m not a big fan of IDEs in general, and I doubt that I’m going to be converted to them any time soon. In the meantime, I’ve been able to knock together applications using handwritten everything pretty damn fast (as fast as with Realbasic, for example, albeit with many of the usual UI issues of web applications).

Here’s my magic sauce — a single shell script that I simply put in a project directory and double-click to perform a build:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo "$DIR"
cd "$DIR"
pwd
zip app.nw *.html package.json *.png *.js *.css *.map
mv app.nw ../node-webkit.app/Contents/Resources/
cp nw.icns ../node-webkit.app/Contents/Resources/
cp info.plist ../node-webkit.app/Contents/
open ../node-webkit.app

What this shell script does is set the working directory to the project directory, zip together the source files and name the archive app.nw, and then move that, the icon, and the (modified) info.plist into the right place (assuming the node-webkit app is in the parent directory), and launch it. This basically takes maybe 2s before my app is running in front of me.

info.plist is simply copied from the basic nw app, and modified so that the application name and version are what I want to appear in the about box and menubar.

This is how I make sure the standard menus are present (on Mac builds):

var gui = require('nw.gui'),
    menubar = new gui.Menu({ type: 'menubar' });
if(process.platform === 'darwin'){
    menubar.createMacBuiltin(appName);
}
gui.Window.get().menu = menubar;

And finally, to enable easy debugging:

if(dev){
    var debugItem = new gui.MenuItem({ label: 'Dev' }),
        debugMenu = new gui.Menu(),
        menuItem;
    debugItem.submenu = debugMenu;
    menubar.append(debugItem);
    menuItem = new gui.MenuItem({ label: "Open Debugger" });
    debugMenu.append(menuItem);
    menuItem.click = function(){
        gui.Window.get().showDevTools();
    }
}

So with a few code snippets you get a Mac menubar (where appropriate), a Dev menu (if dev is truthy) and a single double-click to package and build your application in the blink of an eye. You can build your application with whatever Javascript / HTML / CSS combination suits you best.

Obviously, you don’t get a real “native” UI (but the next best thing is a web UI, since people expect to deal with web applications on every platform), and this isn’t going to be a great way to deliver performant applications that do heavy lifting (e.g. image processing), but it’s very easy to orchestrate command-line tools, and of course the chrome engine offers a ridiculous amount of functionality out of the box.

I should mention that Xojo is actually quite capable of producing decent Cocoa applications these days. (It sure took a while.) But its performance is nowhere near nw in practical terms. For example, C3D Buddy is able to load thousands of PNGs in the blink of an eye; the equivalent Xojo application is torpid. Now if I were doing heavy lifting with Javascript, perhaps it would tilt Xojo’s way, but it’s hard to think of just how heavy the lifting would need to get.

The Race to Replace Illustrator: Affinity Designer

Just as Core Graphics created a race to replace Photoshop (at least for the great unwashed masses who don’t care about Color Spaces, CMYK, Lab Color, HDR, Stitching, Content-Aware Resizing and Deletion, seamless integration with other Adobe software, and so forth) there is now a race to replace Illustrator. Part of the problem is that the bewildering range of screen densities has made working primarily with bitmaps essentially a mug’s game (even Apple-targeted designers, used to supporting two resolutions, are suddenly faced with four (one of which is seriously weird).

You may recall some old stalwarts, such as Inkscape, Intaglio Designer, iDraw, Artboard, ZeusDraw, EasyDraw — of which I like iDraw — and Sketch; some of these are pretty credible Illustrator replacements (at least for casual users) but there are even more entrants in the field now, and they’re even more interesting:

Sketch 3 is the new version of Sketch — the vector-based, UI-focused drawing tool. It adds user interface refinements, symbols (“instances”), scripting via Javascript, automatic detection of colors used in a layout, and streamlined export functions. The fact that most of the new features are focused on workflow shows that BohemianCoding has been listening to professional users. I’ve not bought Sketch 3 yet because I’m a bit miffed that there’s no upgrade path for Sketch 2 owners (for which Apple is at least partially responsible) and — worse — that they pulled Sketch 2 from the App Store so I can’t conveniently reinstall the old version on my computers. Again, that might be Apple’s fault (i.e. perhaps they can’t set things up so that existing owners could continue to download and install it while taking it off the market).

Let me pause here to say this: I freaking love Sketch (2). I probably use it more than any other non-3d graphics program (I use it in preference to iDraw these days). I probably use it more than all other non-3d graphics software put together. Sketch is my go-to app for UI graphics and textures for (cartoony) 3d models.

Paintcode and Webcode are, like Sketch, focused on user interface design. The big difference between these tools and predecessors is that they’re focused on outputing your graphics as code that will recreate them at arbitrary resolutions (Paintcode will output Objective-C, Swift, or C# Xamarin, while Webcode will output SVG, Javascript (Canvas), and HTML+CSS. I’ve got a Paintcode 1.x license which seemed a bit limited (Paintcode 2 has beefed up its import and export functionality, as well as adding Swift support). Of the two, Webcode actually looks more compelling to me than Paintcode (and it doesn’t hurt that it’s much cheaper) — I’d probably pony up for Paintcode if it offered all of Webcode’s functionality, but it appears not to.

Finally, Affinity Designer comes from Serif, a company dedicated to competing with Adobe at the low-end in the Windows market, switching over to the Mac-only market with a bang. Their plan is to start with an Illustrator-killer, then proceed with Affinity Photo and Affinity Publisher. (Publisher? Really? Do they want to take on Pages and InDesign at once because that seems to me to be a losing proposition.) Of the three, Affinity Designer is clearly the most Illustrator-like, while Sketch 3 is kind of an Illustrator/Fireworks hybrid, and Paintcode/Webcode are simply unique.

iDraw is my current benchmark for wannabe Illustrator-replacements.
iDraw is my current benchmark for wannabe Illustrator-replacements.

Affinity Designer

I played with Affinity Designer briefly during the free beta, but it didn’t leave me with a strong impression. When they announced its release, I ponied up the (discounted) $40 (iDraw, my current favorite, is $25, but there’s been no significant improvements to it over the last year, and the things that annoy me about it still annoy me). The first thing I noticed when I launched Affinity Designer is that — like Illustrator — it defaults to print usage (CMYK, paper-oriented layout). It’s nice to discover that it also has web- and device-centric settings and defaults, and @2x retina support out of the box (but unlike Paintcode it hasn’t figured out what to do about the iPhone 6/Plus).

Screen Shot 2014-10-06 at 11.26.51 AM
I imported the SVG from iDraw into Affinity Designer. Everything looks great (and it even preserved layers) except for the fonts (which unfortunately are not easily fixed).

The first thing I did was take a pretty damn complicated SVG file (with layers and typography) and export it from iDraw and import it into Affinity Designer. Every font failed to import correctly (Helvetica Bold and DIN Condensed), but otherwise it seemed to do a pretty good job — overall, it did a better job than Sketch (2) at importing the same file. I think the problem lies with how SVG stores font information (Sketch had the same issue when importing the file; note that iDraw can import its own SVGs flawlessly.)

But here’s where things get ugly — when I tried to fix the font issues, I discovered that I can’t change the character style settings for more than one object at a time. (And this is not a problem in Sketch or iDraw.) As a workaround, I tried to create a style from one object and apply it to others but that didn’t work at all — styles seem to be limited to fill color and the like (and fill color doesn’t seem to be the same thing as text color). Bad start.

Time to look at the program in its own terms. One of the best things about Sketch relative to iDraw is its support for gaussian blur as a style. Affinity Designer has this and more (e.g. emboss, and a weird “3D” effect that I’m not sure what it’s supported to do). What it doesn’t do (and what Sketch and iDraw both do) is allow you to apply the same filters multiple times (e.g. much the same way you can stack box-shadow effects in CSS). Another annoyance with Affinity Designer’s effects is that important settings are buried in a modal dialog box (iDraw is annoying in a different way in that you need to disclose the settings with an extra double-click, but that’s a pretty minor annoyance). So far, I’d call this a mixed result.

Here’s an example of Affinity Designer at its worst. I draw a test bezier curve and then try to apply a stroke to it. So far so good. But it’s stroked in the center of the curve.

  • I almost always want to stroke inside the curve, and sometimes outside, but almost never centered on the curve. So I look at the stroke settings, and all that is exposed is color, opacity, and radius.
  • To access the extra properties I need to click on the little “gear” icon that lets you configure the other settings of a given filter.
  • As I’ve mentioned before, this dialog is modal; it also defaults to showing some random filter setting, not the one you were working on (which confused me a minute, since it was showing bevel/emboss options and not line options).
When I clicked the stroke "gear" I get deposited in a modal dialog with Bevel selected. WTF?
When I clicked the stroke “gear” I get deposited in a modal dialog with Bevel selected. WTF?

 

  • OK, so having switched over to the line settings, I discover that the options (inside, outside, centered) which — for some reason — is not the top setting (compositing mode is at the top).
To add injury to insult, the stroke settings don't actually work — note that I've chosen outside and it's displaying a centered stroke.
To add injury to insult, the stroke settings don’t actually work — note that I’ve chosen outside and it’s displaying a centered stroke.
  • Here’s the rub — the different options (a) don’t work and (b) appear to override and block the modeless setting (i.e. when I change radius in the modeless view, the setting no longer works. WTF?).
The basic selection / transformation affordances are nice.
The basic selection / transformation affordances are nice.

This is a freaking disaster. First of all, how can an Illustrator clone go out the door with broken strokes?

I do like the basic selection affordances. In particular rotation gets its own affordance (the little dot out on its own) rather than requiring mouse/keyboard chording. The basic Bezier drawing tools seem to be solid.

But there’s one more global observation I need to make before I move on: the tools all feel wrong. There’s a nuance to the rules that govern how 2d graphics tools, in drawing programs especially, behave. When they should be sticky vs. revert to a selection tool, and so forth. This stuff is so basic that it happens below the level of conscious decision-making. For better or (mostly) worse, a lot of us have Illustrator’s behavior in our muscle memory (where it displayed MacDraw, which was generally more intuitive).

In any event, just as iDraw and Sketch and many other Mac graphics programs get this somehow right, Affinity Designer gets this somehow wrong, and it bugs the hell out of me. If the program were in a more functional state, I might even spend the time to go figure out exactly what’s wrong and write some kind of detailed bug report for the development team, but I find the program, as a whole, to be so fractally unusable that I just can’t be bothered.

At this point, it’s not worth continuing the review. Affinity Designer is a promising and polished looking piece of software, but basic functionality is completely broken, and it has horrific workflow problems (styles don’t work with text formatting, you can’t edit multiple selections in a useful way, the wrong properties are disclosed in the modeless floater, and the modal dialog is both weird and buggy). So, in summary:

  • Some features that are lacking in iDraw (Gaussian Blur effect)
  • Single window UI (unlike iDraw which suffers from palette-itis)
  • Better SVG import than most rivals
  • Limited effects options (can’t apply multiple instances of a given effect to a single element)
  • Editing effects is clumsy (useful stuff is buried in modal dialog, which does not open on the right effect) and buggy (the settings don’t work properly).
  • Affinity Designer’s tools just feel wrong; they stick in modes when they shouldn’t (or I don’t expect them to) and it’s just infuriating.

Affinity Designer manages to be promising, attractive, and completely useless in its current form.

Note: I purchased Affinity Designer from the App Store after using the public beta a few times. I was so frustrated with the release version that I have requested a refund from Apple, and have deleted the app. (I think this is maybe the second time I have ever asked for an App purchase to be refunded.)

Dropbox vs. Box vs. HubiC

Edit: Brain Fart — I seem to have omitted about a paragraph of pertinent information.

I’ll assume you all know what Dropbox is. If you don’t, go get Dropbox now. It’s free and it’s awesome.

The only downside of Dropbox is that if you want more than the 2GB of storage you get for free, it gets more expensive, and the upper limit on how much you can store is (for practical purposes) quite low. Personally, I haven’t found either of these an issue — but thanks to my link on opensourcemac.com, I have a pretty huge “free” account. But it would be awesome to have something like Dropbox that was so big I could just stop managing what I keep on it altogether (of course, this is the problem with stuff that’s free — you waste it).

Box.com has been around about as long as Dropbox (heck, it has an even better domain name, right?) but has been targeted at the enterprise.

hubiC.com (their capitalization) I just found out about via Hacker News. It offers more free storage than Dropbox, but not quite as much as Box, and vastly cheaper paid plans, including about $140/year for 10TB. (I’m not sure how you can actually get 10TB into it, short of using a ZFS or Drobo style multi-disk volume.)

2GB vs 50GB vs 25GB

This is how much storage you get for free.

$100/year for 100GB vs. $10/month for 100GB vs. $13.60/year for 100GB (or $136/month for 10TB)

Edit: I’ve corrected the costs for HubiC.

This is how much it costs for more storage. Box gives you — by far — the most free storage but gets more expensive than Dropbox (while offering various enterprisey features). HubiC is insanely cheaper than both of them. By way of comparison, iCloud costs $20/year for 20GB, so in terms of dollars per unit storage, only HubiC is a better deal. In terms of useful features out of the box, Dropbox support is built into far more programs while iCloud offers useful functionality (notably over-the-air backups of devices and integration with Apple products) to Mac and iOS users that no other platform can (currently) match.

For Android users, the iCloud equivalent is Google Drive, which gives you 15GB free, and costs $60/year for 100GB, making it a bit cheaper (and less useful) than Dropbox.

Mac OS X Integration

All three programs appear as folders in your home directory by default, and stick shortcuts to themselves in Finder’s sidebar. Having installed HubiC and then Box after installing Dropbox, Box was very flaky when first installed. Its installer provided no feedback, and the first few times I tried to launch the application nothing seemed to happen, followed by weird broken delayed launches. Once I’d patiently killed a bunch of Box.app instances and started over it worked well.

Box and Dropbox have similar levels of Finder integration — they indicate the state of files and provide context menu items for sharing links. HubiC appears not to do anything like this, unfortunately.

All three applications provide status menus — those icons that appear in the menubar to the left of the Spotlight magnifying glass. I should note that HubiC’s icon looks like a shapeless blue blob — a blue cloud? — which is an anti-feature. The status menus of all three seem to be perfectly fine and offer decent functionality. Oddly enough, Box and Dropbox no longer keep you apprised of your usage level whereas HubiC does.

Box has one glaring defect — it won’t sync Mac OS X “bundles” (i.e. directories masquerading as files). I have no idea why — they’re just directories. It tells you to zip them up first (gee, how about doing it yourself?)

All three services offer support for all the usual platforms — although I can’t comment on how good any of them are (except the Dropbox client for iOS is decent, and all three work decently in a web browser, although HubiC’s in-browser account management is awful). I cannot yet comment on the security of Box or HubiC. Dropbox offers, and I use, two-factor authentication, and I’m pretty sure HubiC does not (but its website is pretty hard to navigate so maybe it’s there somewhere).

Conclusion

If you just want some free storage and don’t mind not being able to sync bundles then Box is a better deal than Dropbox and it’s probably quite robust given the money behind it. If you’re already using Dropbox and don’t need more storage, Box does not work as well so unless you want its enterprisey features (and you know who you are) you might as well stick with Dropbox. I can’t really comment on HubiC until I’ve exercised it by, saying syncing a buttload of RAW files to it (if I’m going to get more cloud storage, I want enough of it to not need more than one service). If you’re interested, HubiC is a damn good deal for free and it works side-by-side with the others. If it turns out to deliver the goods, I may well end up buying a 10TB plan and switching to it from Crashplan.

AppleTV

Yesterday, 9to5 Mac noticed that Apple had rejigged its online store so as to position AppleTV as a product category. Also interestingly, Lee Clow has apparently hinted that, for the first time since 1984, Apple may be airing a super bowl spot. And then during Apple’s first quarter earnings call, Tim Cook foreshadowed new product categories for 2014. We’ve also had rumors of Apple cutting content deals over the last year that never turned into announcements.

It seems pretty clear that one new product category is going to be AppleTV. And here’s where things get really interesting.

Facts

  • Apple’s online store now treats AppleTV as a product category rather than an accessory.
  • Apple is not currently selling an Apple-branded 4K display (the 4K displays it is selling are from Sharp)
  • Apple’s OS-level support for 4K displays is conspicuously poor (they need to be treated as Retina displays)
  • iOS now provides proper (API) support for bluetooth game controllers
  • The price for high quality 4K displays is about to drop well under $1000
  • The current AppleTV does not support 4K displays
  • The current AppleTV does not support 802.11ac

Opinions

  • The last crop of consoles (Xbox One, PS4, Wii U) had the most anemic rollout (in terms of launch titles) in recent memory
  • The way AppleTV’s remote app works is primitive compared to the way Chromecast can be “handed” a playback task (and Apple knows this)
  • AppleTV currently needs a system update in order to add a new content channel; the tools for managing “apps” in AppleTV are primitive to put it mildly
  • There is already an ecosystem of iOS-compatible controllers and iOS games supporting those controllers
  • 4K displays blur or even erase the line between monitors and TVs

Rumors

  • Apple has bought a Super Bowl spot
  • Nintendo has suggested it is looking at developing titles for mobile platforms
  • Apple has been negotiating content deals with major players (movie studios, etc.) but it has borne no visible fruit as yet

Predictions

  • Apple is at last going to release an AppleTV console (whether it’s called AppleTV or not remains to be seen)
    • It will have access to major new sources of content
    • It will have an App Store
    • It will support Bluetooth controllers
    • It will support the use of other iOS devices as controllers
    • It will be powered by the A7 or something more powerful
    • If it is powered by a new chip (e.g. “A7x”) it will support 4K (the A7 can drive 2K)
    • It will have a shockingly good set of launch titles (how else to explain the lackluster launch titles for all the other consoles?)
    • It will not have a tuner or Cablecard support or any other horrific kludge
    • It may introduce streaming video with ads for content from networks (effectively on-demand playback of licensed content with ads)
    • It will cost $199-399 (I’d predict $199, but Apple might actually sell a range of products with varying storage capacities)
    • The ghastly Apple Remote iOS app will be given a proper overhaul, and work in more of a peer-to-peer manner (and be able to hand off tasks to the AppleTV)
  • An even smaller $99 version which doesn’t play games might continue as AppleTV Nano or some such
  • We’re going to see extensive 4K support across Apple’s product lines over the next 12 months
  • We’re going to see Apple-branded 4K displays (“Retina HD” perhaps?) designed to work seamlessly with all this new stuff

node-webkit

C3D Buddy 2.0 in action — built in an evening using node-webkit
C3D Buddy 2.0 in action — built in an evening using node-webkit

I don’t do very much desktop software development these days, and I’ve become increasingly frustrated with Realbasic (now Xojo), so the prospect of forking out $500 for an upgrade that may or may not be usable did not fill me with glee. Furthermore, as the years roll on, there’s more and more functionality tied to the web that desktop-centric development tools struggle to work with.

I was dimly interested in a thread on Hacker News this morning concerning a workflow for developing desktop applications with node. Turns out that the workflow was mostly to do with things like angular and jade, which I’m not especially keen on, and not so much with the actual desktop stuff — the heavy lifting for which is all done by node-webkit. So I started looking into node-webkit.

I like a tool which has you up-and-running in about three paragraphs.

It goes something like this:

Download an appropriate node-webkit binary. (Disappointingly, the Mac version is restricted to 32-bit.)

  • Write an index.html file. (The sample “hello world” app calls node inline.)
  • Write a package.json file. (The documentation suggests it’s like a “manifest” file, but really it’s more like a configuration file.)
  • Zip this stuff into a file into an archive whose name ends in .nw.
  • Double-click the archive.
  • Voila, your app works.

After working on this for about fifteen minutes, I knocked up a bash script (which I turned into a .command file, allowing me to double-click it in Finder) which does the archiving and then launches the file in one step. (It does leave dead terminal windows lying around, and it doesn’t quit the app if it’s still running. I think I may build an app for building apps if I do much more of this.)

And to build a distributable application you can simply put the archive in the application bundle (on the Mac) renaming it “app.nw” or name the file package.nw and put it in the same directory as the application (for those benighted platforms that don’t have bundles). One minor annoyance is that it’s not clear exactly what needs to be changed in the Info.plist file to fully customize your application.

So what is node-webkit? It’s essentially a version of Chromium that puts node.js alongside the DOM in your web pages, along with a few custom HTML and DOM extensions that let you do things like handle platform-native file requesters).

I should note that it’s a potential security nightmare as it stands. There’s no sandboxing (that’s kind of the point), so deploying an app that loads your banking website and then watches you press keys is totally doable. That said, it’s a desktop app so it can also delete all your files or encrypt them and hold them hostage.

Anyway, I had a lot of fun this evening rewriting a utility application I originally wrote in Realbasic a few years ago. It probably took me about twice as long to write it as it took me to do it in Realbasic. Part of that is I know (or knew) Realbasic very well, and I don’t know node very well. Another part of it is that Realbasic is almost always synchronous while node is almost always asynchronous. Writing code that spelunks a directory tree asynchronously is a lot more complex both conceptually and in practice than doing so in linear fashion, but the payoff is quite impressive — despite running an “interpreted” language, a task that took significant time in Realbasic (loading and displaying hundreds of thumbnails) happens in the blink of an eye.

One of the things that’s especially intriguing about node-webkit is that it gives you control over the browser you normally don’t have (e.g. window placement, file system access) — these are a constant usability sore-point in the project I am currently working on (which is a web app that is replacing a suite of desktop apps). It would be so much easier to get a lot of the things we want to do working smoothly using a hybrid desktop application built on top of something like node-webkit — it’s kind of a lemma of Alan Kay’s observation that anyone who wants to write really good software needs to build hardware — anyone who wants to write really good web apps really needs to build the browser.

The github repo for my project is here. It’s not a very general-purpose application; if you don’t use Cheetah 3D it’s completely useless.