A NativeScript Development Workflow for Sublime Text

One of the great things about NativeScript is that you can use it in any development environment. By using NativeScript through Telerik AppBuilder, you can build native apps from the browser, a dedicated Windows editor, and even Visual Studio. By using NativeScript through its CLI, you can build NativeScript apps, well, anywhere.

I prefer the CLI because it lets me use my development environment of choice: Sublime Text on OS X. A got a lot of questions about my Sublime workflow at TelerikNEXT last week, so I thought I’d put the workflow down on paper. Internet paper.

Here’s what the workflow looks like in action:

Starting up

To start, I’m going to assume you have Sublime Text 3 and the NativeScript CLI installed on your development machine. You can definitely get this same workflow working in Sublime Text 2, but the specifics of where files are placed are a bit different. If you run into issues feel free to comment on this article and we can figure things out.

Let’s start by creating a new NativeScript project. Run the following command in your terminal of choice:

$ tns create hello-world

Next, navigate into your newly created project, and add each platform you want your app to run on:

$ cd hello-world
$ tns platform add android
$ tns platform add ios

After that, open your newly created project in Sublime Text. On OS X I use the subl command to do that:

$ subl .

If you get an error that the subl command cannot be found you can create a symlink to it using ln -s "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" /usr/local/bin/subl. If you’re still having issues, check out this article which will help you get the command up and running.

At this point you should see your newly created project open in Sublime Text.


Now that you have an app let’s see what it looks like. The easiest way to do that this to return to your terminal and run the tns run command. For instance the following command runs your app in the iOS emulator:

$ tns run ios --emulator

You should see your app pop up in the iOS simulator within a few seconds:


This works, but it’s a bit manual. Yes, all you have to do is return to the terminal and run a single command, but that’s a whole lot of work for a lazy software developer like me. Let’s look at how we can improve this workflow.

Build systems

Sublime Text has a concept of build systems, which are basically configuration files you can use to control what happens when you type Cmd+B. It’s a nice lightweight system you can leverage to speed up your NativeScript development workflow.

Like a lot of things in Sublime, creating a build system involves creating a text file with a naming convention in a location you can never remember. For build systems you need to create a .sublime-build file in your Sublime Packages directory. Since it’s impossible to remember where the Packages directory is, you can open it using the Browse Packages option in the Preferences menu:


Next you’ll want to create a nativescript.sublime-build file in the Users directory. The file should end up here:


You can create this file however you’d like, but personally I find that creating from the command line is the easiest. Here’s how I created this file:

$ subl /Users/tj/Library/Application\ Support/Sublime\ Text\ 3/Packages/User/nativescript.sublime-build

Obviously you’ll need to replace the path’s “tj” directory with your own username — unless your username is “tj”, in which case :fist_bump:.

Here’s what you’ll want to use as the contents of your nativescript.sublime-build file:

  "working_dir": "${project_path}",
  "cmd": ["tns run ios --emulator --device iPhone-6"],
  "shell": true

You can refer to the Sublime Text docs if you want to dig into exactly how this works, but the succinct way to think about this is that every time you type Cmd+B, Sublime runs the commands you specify in the "cmd" property, in this case tns run ios --emulator --device iPhone-6.

Let’s see how this works.

Development workflow

With this build system in place head back to your app in Sublime and open the main-page.xml file. You should see the following code:

<Page xmlns="http://www.nativescript.org/tns.xsd" loaded="pageLoaded">
    <Label text="Tap the button" cssClass="title"/>
    <Button text="TAP" tap="{{ tapAction }}" />
    <Label text="{{ message }}" cssClass="message" textWrap="true"/>

With this file open, type Cmd+B to kick your newly created NativeScript build system. If everything went right your app should load in the simulator within a few seconds:


If you’re not seeing the simulator try closing and reopening Sublime Text, as the editor may need a restart to recognize the new build system. Also, if you’re getting an error that the tns command cannot be found, try closing Sublime Text and opening it with the subl command, as when you open Sublime from the command line it’ll recognize any changes to your PATH that you’ve made in your .bash_profile.

Next try making a change, for instance changing the <Button> element’s text attribute from "TAP" to "CLICK ME". After you make the change type Cmd+B again. You should see your app update within a few seconds.


Cool, right? Try making a few changes to see just how fast your iOS app updates.


This workflow helps with development, but it also helps when things go wrong, as console logging statements will now appear directly within Sublime Text. For example, open your project’s main-page.js file and replace its contents with the following code (the only change is the addition of a console.log() call):

var vmModule = require("./main-view-model");
function pageLoaded(args) {
    var page = args.object;
    page.bindingContext = vmModule.mainViewModel;
exports.pageLoaded = pageLoaded;

With this change in place, use Cmd+B to run your app again, and pay attention to the output within Sublime Text. If all went well you should see your console log statement in the Sublime’s Console when your app loads.


But it gets even cooler. As of NativeScript 1.0 stack traces are logged to the console — meaning that with this workflow you can see stack traces directly within Sublime Text. For example, try changing your main-page.js file to call a method that doesn’t exist:

var vmModule = require("./main-view-model");
function pageLoaded(args) {

    // There is no tj method, but let's try anyways!

    var page = args.object;
    page.bindingContext = vmModule.mainViewModel;
exports.pageLoaded = pageLoaded;

Use Cmd+B to run your changes, and you should see the helpful stack trace shown below:


Other devices

To this point all of the demos you’ve seen have been running on the iOS simulator, specifically the iPhone 6 simulator. This is because the nativescript.sublime-build file you created earlier explicitly specified this device:

  "working_dir": "${project_path}",
  "cmd": ["tns run ios --emulator --device iPhone-6"],
  "shell": true

I use the iOS simulator because I find it to be the fastest way to experiment with NativeScript, but it’s easy to change up this command to target other devices as you need.

For example, by changing tns run ios --emulator --device iPhone-6 to tns run android --emulator you can run your app on an Android emulator. You don’t even have to reload Sublime Text—just save your nativescript.sublime-build file and type Cmd+B in your project again. Here’s what your project looks like on an Android emulator:


If you omit the --emulator flag you can do your development from physical iOS and Android devices, or even Genymotion emulators. Here’s the same app running on my iPhone with tns run ios:


And here’s the same app running on my Nexus 4 using tns run android (mirrored to my screen using Droid @ Screen):


The important thing is that regardless of the device you choose, all the logging and debugging conveniences are still in place.

Wrapping up

The NativeScript CLI makes it possible to work in just about any development environment. In this article I shared the workflow I use Sublime Text, but I’d love to hear about the workflow you use, or would like to use. Let me know in the comments.

Also, if you are a Sublime Text user, and know some additional tips or tricks I can use to improve my workflow, please let me know in the comments as well.