Creating an Aurelia project with Visual Studio code and TypeScript from scratch


What is Aurelia? What is TypeScript? What is Visual Studio Code? If you do not know the answer to any of these questions, I suggest you google them, get the basic idea and then come back here. Because this post assumes that you know what these three things are.


  1. Install NodeJS
  2. Install Asp.Net 5
  3. Install Visual Studio Code

Bonus point: Use a good console emulator on Windows. ConEmu, Console2... the likes. If you are going to spend time on the console, it better be a nice looking window..


Yeoman is a scaffolding tool. We will use Yeoman to do a bit of our bidding. When I said from scratch, I did not mean I will start from the hardware now, did I?


This is a step by step instruction guide. I will explain things as much as possible. Some, I will just leave it to your curiosity to go search and find out. This whole thing is command line heavy... (refer to bonus point above).

Why am I doing this from scratch? To show what the different files mean, what the different packages being installed do and how they actually come together. It is very easy to just download the starter kit on or the skeleton project. There is absolutely nothing wrong with using the skeleton or downloading the starter kit, in fact, that is what most of us will be doing anyways.

You said Yeoman is a scaffolding tool! Why not just use that to create this? Good question. There are generators. In fact there is one for typescript Aurelia too. But it is not updated, uses definitions that are 4 months old and some have fallen on the way side of maintenance. People have explored space and found new life since the time some of them got updated (Gross exaggeration...). Anyways, the point is, they are not from the official Aurelia folks, so cannot be relied upon.

Before you go any further, make sure the prerequisites are met.


Open a command prompt (I use conemu) and navigate to your favorite PoC or Demo or Dev folder. The bullet points give you an idea what that command is doing. You can just skip the bullet points if you know what the command is for and just hit the command.

Note: the "$" at the beginning of the command is just the prompt. The command follows the dollar.

  • Install Yeoman globally
$ npm install yo -g
  • Install jspm globally
$ npm install jspm -g
  • Install the Yeoman aspnet 5 generator. This is what Yeoman will use to scaffold out a aspnet 5 web api application.
$ npm install generator-aspnet -g
  • Run the aspnet generator with yeoman to scaffold the project.
    •  Choose Web API Application
    • I named my project AspnetAureliaTypeScript
$ yo aspnet
  • cd into your project directory and do a package restore (equivalent to a nuget restore) and then build your project.
$ cd AspnetAureliaTypeScript
$ dnu restore
$ dnu build
  • let us make some directories in your project folder. So while you are in your project folder, go ahead and make the following directories.
$ mkdir src
$ mkdir build
$ mkdir test
  • Create a package.json file. This is needed to install and track all your node modules, jspm packages .etc. 
$ yo aspnet:PackageJson

  • Install JSPM (Package manager for the browser), gulp (task runner), tsd (typescript definitions manager) locally
$ npm install jspm gulp tsd --save-dev
  • Visual Studio Code does not understand the objects and modules you will use in your JavaScript and TypeScript modules. If you write a TypeScript module, then Visual Studio Code knows what the interfaces and definitions are. When you install a third party library such as jQuery or gulp, you need to tell TypeScript about them. So, if you use the "$" symbol for jQuery, TypeScript is going to assume you meant "gorilla" and mistakenly typed "$". Hence, you will have to tell TypeScript that Gorilla is a mammal, from the animal kingdom, is big scary.etc. But it will be a royal pain if we have to create the type information for every library we add. Enter "tsd". It is a package manager that provides TypeScript definitions for many popular and not so popular third party libraries. The way things work is, you provide the definition in a "*.d.ts" file. The moment VSCode sees a .d.ts file, it will scan it to understand that "$" means jQuery and not gorilla. Let us initialize tsd. This will create a tsd.json and a typings folder where it will install all the typings we tell it to install.
$ tsd init
  • Create a typescript configuration file. This will be used by the typescript compiler to compile our TypeScript code to JavaScript.
$ yo aspnet:TypeScriptConfig
  • Create a gulpfile. We will be using gulp to automate a lot of tasks. Starting with compilation of our TypeScript code to JavaScript using TypeScript compiler via a gulp task.
$ yo aspnet:Gulpfile
  • Now to initialize JSPM. This is our package manager of choice with Aurelia. Google it, Bing it... read about it. It's an exciting little thing.
    • Enter "wwwroot" for the second question and "no" to the transpiler. Leave the rest to its defaults. Follow the screenshot below
  • Open your project in VSCode
$ code .
  • In VSCode, open the tsconfig.json file and replace it's content with 
    "compilerOptions": {
        "noImplicitAny": false,
        "noEmitOnError": true,
        "removeComments": false,
        "sourceMap": true,
        "target": "es5",
        "module": "amd",
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true
  • Time to get our first TypeScript definition file using tsd. We will need the definition for systemjs and gulp. SystemJS is the default module loader with JSPM. So, back to the console once again.
$ tsd install systemjs gulp --save
  • Wait, wasn't this blog about Aurelia too? Yes. So let us bring in a couple of modules that you will need to get started. We will also bring in "bootstrap" and "font-awesome" to get some basic wire framing going.
$ jspm install aurelia-framework aurelia-bootstrapper bootstrap font-awesome
  • Your project contains a folder "wwwroot". This is the default folder from which static files are loaded. Let us create our main index html file there.
$ cd wwwroot
$ yo aspnet:HTMLPage index
  • Back to VS Code. Open "Startup.cs" and add the following code in the "Configure" function above "app.UseStaticFiles();" statement. 
  • Open the index.html file under wwwroot folder and replace it's content with the code below. We are essentially loading font-awesome, bootstrap stylesheet. Follow that by loading system.js, our module loader and then config.js (a file that was created when you did "jspm init", which contains the magic potion recipes for JSPM to do it's job).
<!doctype html>
<html lang="">
      <meta charset="utf-8" />
      <title>Aspnet Demo</title>
      <link rel="stylesheet" href="jspm_packages/npm/font-awesome@4.5.0/css/font-awesome.min.css">
      <link rel="stylesheet" href="jspm_packages/github/twbs/bootstrap@3.3.6/css/bootstrap.css">
      <meta name="description" content="" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <!-- Place favicon.ico in the root directory -->
  <body aurelia-app>
    <div class="splash">
        <div class="message">Loading</div>
        <i class="fa fa-spinner fa-spin"></i>
    <script src="jspm_packages/system.js"></script>
    <script src="config.js"></script>
  • Right click the "src" folder in your project and add two files "app.html" and "app.ts". 
  • Open app.ts and replace it's content with the code below.
export class App {
    firstName: string = "";
    lastName: string = "";
  • Open app.html and replace it's content with the html below. Notice the <template> tag. This is how you will specify every html in Aurelia. Everything except the index.html is wrapped inside template tags.
    <div class="container">
            <div class="form-group">
                <input type="text" class="form-control" id="inpFirstName" placeholder="First Name" value.bind="firstName">
            <div class="form-group">
                <input type="text" class="form-control" id="inpLastName" placeholder="Last Name" value.bind="lastName">
                <h4>${firstName} ${lastName}</h4>
  • Right click the "build" folder and create a new JavaScript file called "paths.js" and put the code below in that. (Note: It's a .js file and not .ts). This file contains the paths of all our source files and where the destination folder is. This is the key to our gulp build process.
var appRoot = 'src/';
var outputRoot = 'wwwroot/dist/';

module.exports = {
  root: appRoot,
  source: appRoot + '**/*.ts',
  html: appRoot + '**/*.html',
  css: appRoot + '**/*.css',
  output: outputRoot,
  dtsSrc: [
  • Create a folder named "tasks" under the "build" folder and then add a JavaScript file named "build.js". Add the following code to that. Note all the "require" calls. We need to install all those modules. We will do that in the next step. I will leave it to your curiosity to find out what they are supposed to accomplish. At this point, we are just creating a TypeScript compilation task using gulp. We want to compile the files that are changed and we will use the typescript compiler to do that.
var gulp = require("gulp");
var paths = require("../paths");
var plumber = require("gulp-plumber");
var changed = require("gulp-changed");
var typescript = require("gulp-typescript");
var tsc = require("typescript");
var sourcemaps = require("gulp-sourcemaps");
var tsProject = typescript.createProject("./tsconfig.json", {
    typescript: tsc

gulp.task("build-system", function () {
    return gulp.src(paths.dtsSrc.concat(paths.source))
        .pipe(sourcemaps.init({loadMaps: true}))
        .pipe(changed(paths.output, {extension: '.js'}))
        .pipe(sourcemaps.write({includeContent: true}))
  • Back to the console. Let us get all those modules used in the previous step. We have already installed gulp earlier. Let us install the rest. Make sure you are in the root directory.
$ cd..
$ npm install gulp-plumber gulp-changed gulp-typescript gulp-sourcemaps typescript --save-dev
  • Let us also get the TypeScript definition files for the modules installed above. This will help get intellisense on these modules.
$ tsd install node gulp-plumber gulp-changed gulp-typescript gulp-sourcemaps typescript core-js --save
  • Back in VS Code. Open build/tasks/build.js and add the following two tasks at the end of the file. This basically copies all your "html" and "css" files over to a single distrubution folder where TypeScript puts your generated JavaScript files. the distribution folder is "wwwroot/dist".
gulp.task("build-html", function () {
    return gulp.src(paths.html)
        .pipe(changed(paths.output, { extension: '.html'}))

gulp.task("build-css", function () {
    return gulp.src(paths.css)
        .pipe(changed(paths.output, { extension: '.css'}))
  • Open config.js file under wwwroot, and replace the "paths" property with the section below. All we are doing is saying that all our files will be served from "dist/" unless otherwise specified.
paths: {
        "*": "dist/*",
        "github:*": "jspm_packages/github/*",
        "npm:*": "jspm_packages/npm/*"
  • One final thing before we compile everything and see the fruits of our labor. Back in the console, install "require-dir" with npm. Because we created a "build" folder, and we have all our gulp tasks there, in our gulpfile, we will point it to that directory to load all our tasks. This is achieved using require-dir.
$ npm install require-dir --save-dev
  • Now open your gulpfile.js in VSCode and replace it's contents with the code below.
// all gulp tasks are located in the ./build/tasks directory
// gulp configuration is in files in ./build directory
  • Back in the console, let us do our build and see the fruits of our labor.
$ gulp build-system build-html build-css
$ dnu build
$ dnx web
  • Now open a browser window and navigate to "http://localhost:5000"
  • You should see the page shown below. Enter a First Name and Last Name and you will see Aurelia binding in play when the name is displayed below the input controls.


If you have followed through so far, that might seem an awful lot to do to get two input controls on the screen. I agree. But you will most likely not create something like this from scratch. Frankly, all you need is that "package.json" file and the gulp build files. It won't change unless you add more to it. Which is what we are going to do now. Here on, it is actually about showing what Aurelia can do. There are tons of articles and videos showing how to scaffold and get started with Aurelia. My goal with this post is to highlight the various files involved and why they are there and how to best use them.


Let us take our application a little further. But before we go any further, let us add a few things to make our development experience a little better. As you make edits and make more changes, it will be a boring thing to constantly do a "gulp build-system" or "gulp build-html". Let us automate that. Now that you know where the gulp tasks go, let us begin there.

  • Right click your build/tasks folder and a JavaScript file "watch.js" and add the following code to it. This will create a task called watch, which will monitor our three file types, "ts", "html" and "css" and run their respective compilation tasks when they are changed.
var gulp = require('gulp');
var paths = require('../paths');

// outputs changes to files to the console
function reportChange(event) {
    console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');

gulp.task('watch', function () {, ['build-system']).on('change', reportChange);, ['build-html']).on('change', reportChange);, ['build-css']).on('change', reportChange);
  • Back to the console. Use a separate window or tab and navigate to the root of your application and type the following command. Note: The command will not exit till you press ctrl+c. Hence the need for a separate window to let it run and monitor our files.
$ gulp watch


Now that we have something of a structure and a skeleton, let us dig in a little deep and get to know Aurelia a little better. And, yes, the blog is still about setting up an Aurelia application (from scratch... remember?).

  • Install more of Aurelia framework packages. Ideally, we would have required aurelia-framework and aurelia-bootstrapper. But it is considered a good practice to directly install a package if you will reference it. Also, a bug in babel transpiler currently requires some of the internal packages also to be installed. Let us not worry too much about that and install the needed packages.
$ jspm install aurelia-history-browser aurelia-loader-default aurelia-logging-console aurelia-router aurelia-templating-binding aurelia-templating-resources aurelia-templating-router
  • Back in VS Code, open wwwroot/index.html file. Notice the line "<body aurelia-app>". By convention, when aurelia-bootstrapper sees aurelia-app, it will look for files named app.html and app.js and load it up. That's how the application is setup to run right now. Let us change that. We need a bit more flexibility and control. change that line to 
<body aurelia-app="main">
  • Now instead of a file named app, aurelia-bootstrapper will look for a file named "main". Let us create that. Right click "src" folder and create a new typescript file "main.ts". Add the following code. This will load app.ts/app.html after doing any required configuration.
import {Aurelia} from "aurelia-framework";

export function configure(aurelia: Aurelia){
            .then(a => a.setRoot());
  • Open app.ts and replace it's content with the code below. Once main.ts loads up app.ts, it will look for a configureRouter function. When it finds it, it will execute it. We will create a single route here. Basically, when you navigate to http://localhost:5000, or http://localhost:5000/#home, it will look for (by convention) a file pair "home.js and home.html", load it up, bind it and serve it!
import {Router, RouterConfiguration} from 'aurelia-router'

export class App {
    router: Router;

    configureRouter(config: RouterConfiguration, router: Router) {
        config.title = 'Aurelia Demo';[
            { route: ['', 'home'], name: 'home', moduleId: 'home', nav: true, title: 'Home' }

        this.router = router;
  • Open app.html and replace its content. <router-view> is an aurelia component that will look what aurelia-router is serving up and load the contents inside it. Essentially, when home.html becomes available, its content will be loaded inside <router-view> tag.
  <div class="page-host container">
  • But we don't have a home.html or home.ts file. So create "src/home.hml" and "src/home.ts".
  • Add the following html to home.html
    <h1>Welcome to ${welcomeMessage}</h1>
  • Open the file named home.ts and add the following code.
export class Home {
    welcomeMessage: string = "Aurelia Skeleton using TypeScript and VSCode";
  • If you have been running "gulp watch" and "dnx web" already in your console, reload your browser. You should now see the welcome message.


You are now all set to follow all the aurelia blogs, articles and of course the official aurelia docs to get more out of your Aurelia application. This is only a beginning. A start to creating your own skeleton. So where to go from here? Look up Custom Elements, Custom Attributes, testing with Karma and protractor. There is so much to learn and apply. This is just a beginning. I will write more and be back with more. Hope this was an easy to follow guide and helped you understand all those different files that make up an aurelia project.