5 Min Quickstart

Let's start from zero and build a super simple Angular 2 application in TypeScript.

Don't want TypeScript?

Although we're getting started in TypeScript, you can also write Angular 2 apps in JavaScript and Dart by selecting either of those languages from the combo-box in the banner.

See It Run!

Running the live example is the quickest way to see an Angular 2 app come to life.

Clicking that link fires up a browser, loads the sample in plunker, and displays a simple message:

Output of quickstart app

Here is the file structure:


Functionally, it's an index.html and two TypeScript files in an app/ folder. We can handle that!

Of course we won't build many apps that only run in plunker. Let's follow a process that's closer to what we'd do in real life.

  1. Set up our development environment
  2. Write the Angular root component for our app
  3. Bootstrap it to take control of the main web page
  4. Write the main page (index.html)

We really can build the QuickStart from scratch in five minutes if we follow the instructions and ignore the commentary.

Most of us will be interested in the "why" as well as the "how" and that will take longer.

Development Environment

We'll need a place to stand (the application project folder), some libraries, some TypeScript configuration and the TypeScript-aware editor of your choice.

Create a new project folder

mkdir angular2-quickstart cd angular2-quickstart

Add the libraries we need

We recommend the npm package manager for acquiring and managing our development libraries.

Don't have npm? Get it now because we're going to use it now and repeatedly throughout this documentation.

Add a package.json file to the project folder and copy/paste the following:

{ "name": "angular2-quickstart", "version": "1.0.0", "scripts": { "tsc": "tsc", "tsc:w": "tsc -w", "lite": "lite-server", "start": "concurrent \"npm run tsc:w\" \"npm run lite\" " }, "license": "ISC", "dependencies": { "angular2": "2.0.0-beta.0", "systemjs": "0.19.6", "es6-promise": "^3.0.2", "es6-shim": "^0.33.3", "reflect-metadata": "0.1.2", "rxjs": "5.0.0-beta.0", "zone.js": "0.5.10" }, "devDependencies": { "concurrently": "^1.0.0", "lite-server": "^1.3.1", "typescript": "^1.7.3" } }

Itching to know the details? We explain in the appendix below

Install these packages. Open a terminal window (command window in Windows) and run this npm command.

npm install

Scary error messages in red may appear during install. Ignore them. The install will succeed. See the appendix below for more information.

Configure TypeScript

We must guide the TypeScript compiler with very specific settings.

Add a tsconfig.json file to the project folder and copy/paste the following:

{ "compilerOptions": { "target": "ES5", "module": "system", "moduleResolution": "node", "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "removeComments": false, "noImplicitAny": false }, "exclude": [ "node_modules" ] }

We explore the tsconfig.json in an appendix below

We're all set. Let's write some code.

Our First Angular Component

The Component is the most fundamental of Angular concepts. A component manages a view - a piece of the web page where we display information to the user and respond to user feedback.

Technically, a component is a class that controls a view template. We'll write a lot of them as we build Angular apps. This is our first attempt so we'll keep it ridiculously simple.

Create an application source sub-folder

We like to keep our application code in a sub-folder off the root called app/. Execute the following command in the console window.

mkdir app cd app

Add the component file

Now add a file named app.component.ts and paste the following lines:

import {Component} from 'angular2/core'; @Component({ selector: 'my-app', template: '<h1>My First Angular 2 App</h1>' }) export class AppComponent { }

Let's review this file in detail, starting at the bottom where we define a class.

The Component class

At the bottom of the file is an empty, do-nothing class named AppComponent. When we're ready to build a substantive application, we can expand this class with properties and application logic. Our AppComponent class is empty because we don't need it to do anything in this QuickStart.


Angular apps are modular. They consist of many files each dedicated to a purpose.

Most application files export one thing such as a component. Our app.component file exports the AppComponent.

app/app.component.ts (export)
export class AppComponent { }

The act of exporting turns the file into a module. The name of the file (without extension) is usually the name of the module. Accordingly, 'app.component' is the name of our first module.

A more sophisticated application would have child components that descended from AppComponent in a visual tree. A more sophisticated app would have more files and modules, at least as many as it had components.

Quickstart isn't sophisticated; one component is all we need. Yet modules play a fundamental organizational role in even this small app.

Modules rely on other modules. In TypeScript Angular apps, when we need something provided by another module, we import it. When another module needs to refer to AppComponent, it imports the AppComponent symbol like this:

app/boot.ts (import)
import {AppComponent} from './app.component'

Angular is also modular. It is a collection of library modules. Each library is itself a module made up of several, related feature modules.

When we need something from Angular, we import it from an Angular library module. We need something from Angular right now to help us define metadata about our component.

Component Metadata

A class becomes an Angular component when we give it metadata. Angular needs the metadata to understand how to construct the view and how the component interacts with other parts of the application.

We define a component's metadata with the Angular Component function. We access that function by importing it from the primary Angular library,angular2/core.

app/app.component.ts (import)
import {Component} from 'angular2/core';

In TypeScript we apply that function to the class as a decorator by prefixing it with the @ symbol and invoking it just above the component class:

app/app.component.ts (metadata)
@Component({ selector: 'my-app', template: '<h1>My First Angular 2 App</h1>' })

@Component tells Angular that this class is an Angular component. The configuration object passed to the @Component method has two fields, a selector and a template.

The selector specifies a simple CSS selector for a host HTML element named my-app. Angular creates and displays an instance of our AppComponent wherever it encounters a my-app element in the host HTML.

Remember the my-app selector! We'll need that information when we write our index.html

The template property holds the component's companion template. A template is a form of HTML that tells Angular how to render a view. Our template is a single line of HTML announcing "My First Angular App".

Now we need something to tell Angular to load this component.

Give it the boot

Add a new file , boot.ts, to the app/ folder as follows:

import {bootstrap} from 'angular2/platform/browser' import {AppComponent} from './app.component' bootstrap(AppComponent);

We need two things to launch the application:

  1. Angular's browser bootstrap function
  2. The application root component that we just wrote.

We import both. Then we call bootstrap, passing in the root component type, AppComponent.

Learn why we import bootstrap from angular2/platform/browser and why we create a separate boot.ts file in the appendix below.

We've asked Angular to launch the app in a browser with our component at the root. Where will Angular put it?

Add the index.html

Angular displays our application in a specific location on our index.html. It's time to create that file.

We won't put our index.html in the app/ folder. We'll locate it up one level, in the project root folder.

cd ..

Now create theindex.html file and paste the following lines:

<html> <head> <title>Angular 2 QuickStart</title> <!-- 1. Load libraries --> <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="node_modules/rxjs/bundles/Rx.js"></script> <script src="node_modules/angular2/bundles/angular2.dev.js"></script> <!-- 2. Configure SystemJS --> <script> System.config({ packages: { app: { format: 'register', defaultExtension: 'js' } } }); System.import('app/boot') .then(null, console.error.bind(console)); </script> </head> <!-- 3. Display the application --> <body> <my-app>Loading...</my-app> </body> </html>

There are three noteworthy sections of HTML:

  1. We load the JavaScript libraries we need. angular2-polyfills.js and Rx.js are needed by Angular 2.

  2. We configure something called System and ask it to import the boot file we just wrote.

  3. We add the <my-app> tag in the <body>. This is where our app lives!

Something has to find and load our application modules. We're using SystemJS to do that. There are other choices and we're not saying SystemJS is the best. We like it and it works.

The specifics of SystemJS configuration are out of bounds. We'll briefly describe this particular configuration in the appendix below.

When Angular calls the bootstrap function in boot.ts, it reads the AppComponent metadata, finds the my-app selector, locates an element tag named my-app, and loads our application between those tags.

Compile and run!

Open a terminal window and enter this command:

npm start

That command runs two parallel node processes

  1. The TypeScript compiler in watch mode
  2. A static server called lite-server that loads index.html in a browser and refreshes the browser when application files change

In a few moments, a browser tab should open and display

Output of quickstart app

Congratulations! We are in business.

If you see Loading... displayed instead, see the Browser ES6 support appendix.

Make some changes

Try changing the message to "My SECOND Angular 2 app".

The TypeScript compiler and lite-server are watching. They should detect the change, recompile the TypeScript into JavaScript, refresh the browser, and display the revised message.

It's a nifty way to develop an application!

We close the terminal window when we're done to terminate both the compiler and the server.

Final structure

Our final project folder structure looks like this:


And here are the files:

import {Component} from 'angular2/core'; @Component({ selector: 'my-app', template: '<h1>My First Angular 2 App</h1>' }) export class AppComponent { } import {bootstrap} from 'angular2/platform/browser' import {AppComponent} from './app.component' bootstrap(AppComponent); <html> <head> <title>Angular 2 QuickStart</title> <!-- 1. Load libraries --> <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="node_modules/rxjs/bundles/Rx.js"></script> <script src="node_modules/angular2/bundles/angular2.dev.js"></script> <!-- 2. Configure SystemJS --> <script> System.config({ packages: { app: { format: 'register', defaultExtension: 'js' } } }); System.import('app/boot') .then(null, console.error.bind(console)); </script> </head> <!-- 3. Display the application --> <body> <my-app>Loading...</my-app> </body> </html> { "name": "angular2-quickstart", "version": "1.0.0", "scripts": { "tsc": "tsc", "tsc:w": "tsc -w", "lite": "lite-server", "start": "concurrent \"npm run tsc:w\" \"npm run lite\" " }, "license": "ISC", "dependencies": { "angular2": "2.0.0-beta.0", "systemjs": "0.19.6", "es6-promise": "^3.0.2", "es6-shim": "^0.33.3", "reflect-metadata": "0.1.2", "rxjs": "5.0.0-beta.0", "zone.js": "0.5.10" }, "devDependencies": { "concurrently": "^1.0.0", "lite-server": "^1.3.1", "typescript": "^1.7.3" } } { "compilerOptions": { "target": "ES5", "module": "system", "moduleResolution": "node", "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "removeComments": false, "noImplicitAny": false }, "exclude": [ "node_modules" ] }

Wrap Up

Our first application doesn't do much. It's basically "Hello, World" for Angular 2.

We kept it simple in our first pass: we wrote a little Angular component, we added some JavaScript libraries to index.html, and launched with a static file server. That's about all we'd expect to do for a "Hello, World" app.

We have greater ambitions.

The good news is that the overhead of setup is (mostly) behind us. We'll probably only touch the package.json to update libraries. We'll likely open index.html only if we need to add a library or some css stylesheets.

We're about to take the next step and build a small application that demonstrates the great things we can build with Angular 2.

Join us on the Tour of Heroes Tutorial!


The balance of this chapter is a set of appendices that elaborate some of the points we covered quickly above.

There is no essential material here. Continued reading is for the curious.

Appendix: Browser ES6 support

Angular 2 relies on some ES2015 features, most of them found in modern browsers. Some browsers (including IE 11) require a shim to support the the needed functionality. Try loading the following shim above the other scripts in the index.html:

<script src="node_modules/es6-shim/es6-shim.js"></script>

Appendix: package.json

npm is a popular package manager and Angular application developers rely on it to acquire and manage the libraries their apps require.

We specify the packages we need in an npm package.json file.

The Angular team suggests the packages listed in the dependencies and devDependencies sections listed in this file:

package.json (dependencies)
{ "dependencies": { "angular2": "2.0.0-beta.0", "systemjs": "0.19.6", "es6-promise": "^3.0.2", "es6-shim": "^0.33.3", "reflect-metadata": "0.1.2", "rxjs": "5.0.0-beta.0", "zone.js": "0.5.10" }, "devDependencies": { "concurrently": "^1.0.0", "lite-server": "^1.3.1", "typescript": "^1.7.3" } }

There are other possible package choices. We're recommending this particular set that we know work well together. Play along with us for now. Feel free to make substitutions later to suit your tastes and experience.

A package.json has an optional scripts section where we can define helpful commands to perform development and build tasks. We've included a number of such scripts in our suggested package.json:

package.json (scripts)
{ "scripts": { "tsc": "tsc", "tsc:w": "tsc -w", "lite": "lite-server", "start": "concurrent \"npm run tsc:w\" \"npm run lite\" " } }

We've seen how we can run the compiler and a server at the same time with this command:

npm start

We execute npm scripts in that manner: npm run + script-name. Here's what these scripts do:

Appendix: Npm errors and warnings

All is well if there are no console messages starting with npm ERR! at the end of an npm install. There might be a few npm WARN messages along the way — and that is perfectly fine.

We often see an npm WARN message after a series of gyp ERR! messages. Ignore them. A package may try to re-compile itself using node-gyp. If the re-compile fails, the package recovers (typically with a pre-built version) and everything works.

We are in good shape as long as there are no npm ERR! messages at the very end of npm install.

Appendix: TypeScript configuration

We added a TypeScript configuration file (tsconfig.json) to our project to guide the compiler as it generates JavaScript files. Get details about tsconfig.json from the official TypeScript wiki.

The options and flags in the file we provided are essential.

We'd like a moment to discuss the noImplicitAny flag. TypeScript developers disagree about whether it should be true or false. There is no correct answer and we can change the flag later. But our choice now can make a difference in larger projects so it merits discussion.

When the noImplicitAny flag is false, the compiler silently defaults the type of a variable to any if it cannot infer the type based on how the variable is used. That's what we mean by "implicitly any".

When the noImplicitAny flag is true and the TypeScript compiler cannot infer the type, it still generates the JavaScript files but it also reports an error.

In this QuickStart and many of the other samples in this Developer Guide we set the noImplicitAny flag to false.

Developers who prefer stricter type checking should set the noImplicitAny flag to true. We can still set a variable's type to any if that seems like the best choice. We'd be doing so explicitly after giving the matter some thought.

If we set the noImplicitAny flag to true, we may get implicit index errors as well. If we feel these are more annoying than helpful, we can suppress them with the following additional flag.


Appendix: SystemJS Configuration

The QuickStart uses SystemJS to load application and library modules. There are alternatives that work just fine including the well-regarded webpack. SystemJS happens to be a good choice but we want to be clear that it was a choice and not a preference.

All module loaders require configuration and all loader configuration becomes complicated rather quickly as soon as the file structure diversifies and we start thinking about building for production and performance.

We suggest becoming well-versed in the loader of your choice.

Learn more about SystemJS configuration here.

With those cautions in mind, what are we doing here?

index.html (System configuration
<script> System.config({ packages: { app: { format: 'register', defaultExtension: 'js' } } }); System.import('app/boot') .then(null, console.error.bind(console)); </script>

The packages node tells SystemJS what to do when it sees a request for a module from the app/ folder.

Our QuickStart makes such requests when one of its application TypeScript files has an import statement like this:

boot.ts (excerpt)
import {AppComponent} from './app.component'

Notice that the module name (after from) does not mention a filename extension. The packages: configuration tells SystemJS to default the extension to 'js', a JavaScript file.

That makes sense because we transpile TypeScript to JavaScript before running the application.

In the live example on plunker we transpile (AKA compile) to JavaScript in the browser on the fly. That's fine for a demo. That's not our preference for development or production.

We recommend transpiling (AKA compiling) to JavaScript during a build phase before running the application for several reasons including:

The System.import call tells SystemJS to import the boot file (boot.js ... after transpiling boot.ts, remember?). boot is where we tell Angular to launch the application. We also catch and log launch errors to the console.

All other modules are loaded upon request either by an import statement or by Angular itself.

Appendix: boot.ts

Bootstrapping is platform-specific

We import the bootstrap function from angular2/platform/browser, not angular2/core. There's a good reason.

We only call "core" those capabilities that are the same across all platform targets. True, most Angular applications run only in a browser and we'll call the bootstrap function from this library most of the time. It's pretty "core" if we're always writing for a browser.

But it is possible to load a component in a different enviroment. We might load it on a mobile device with Apache Cordova We might wish to render the first page of our application on the server to improve launch performance or facilitate SEO.

These targets require a different kind of bootstrap function that we'd import from a different library.

Why do we create a separate boot.ts file?

The boot.ts file is tiny. This is just a QuickStart. We could have folded its few lines into the app.component file and spared ourselves some complexity.

We didn't for what we believe to be good reasons:

  1. Doing it right is easy
  2. Testability
  3. Reusability
  4. Separation of concerns
  5. We learned about import and export

It's easy

Sure it's an extra step and an extra file. How hard is that in the scheme of things?

We'll see that a separate boot.ts is beneficial for most apps even if it isn't critical for the QuickStart. Let's develop good habits now while the cost is low.


We should be thinking about testability from the beginning even if we know we'll never test the QuickStart.

It is difficult to unit test a component when there is a call to bootstrap in the same file. As soon as we load the component file to test the component, the bootstrap function tries to load the application in the browser. It throws an error because we're not expecting to run the entire application, just test the component.

Relocating the bootstrap function to boot.ts eliminates this spurious error and leaves us with a clean component module file.


We refactor, rename, and relocate files as our application evolves. We can't do any of those things while the file calls bootstrap. we can't move it. We can't reuse the component in another application. We can't pre-render the component on the server for better performance.

Separation of concerns

A component's responsibility is to present and manage a view.

Launching the application has nothing to do with view management. That's a separate concern. The friction we're encountering in testing and reuse stems from this unnecessary mix of responsibilities.


While writing a separate boot.ts file we learned an essential Angular skill: how to export from one module and import into another. We'll do a lot of that as we learn more Angular.