Building Angular Chrome Apps
The Chrome web browser is Google’s custom browser. Not only is it incredibly speedy and on the bleeding edge of web development, it is at the forefront of delivering web experiences both on and off the web.
Chrome Apps are embedded applications that run within the web browser, but are intended to deliver a native app feel. Since they run within Chrome itself, they are written in HTML5, JavaScript, and CSS3, and they have access to native-like capabilities that true web applications do not.
Chrome apps have access to the Chrome API and services and can provide an integrated desktop-like experience to the user.
One more interesting difference between Chrome apps and web apps is that they always load locally, so they show up immediately, rather than waiting for the network to fully download the components. This feature greatly improves the apps’ performance and our user’s experience with running our apps.
Understanding Chrome Apps
Let’s dive into looking at how Chrome apps actually work and how we can start building our own.
Every Chrome application has three core files:
manifest.json
This manifest.json
file describes metadata about the application, such as the name, description, version, and how to launch our application.
A Background Script
This background script sets up how our application responds to system-level events, such as a user installing our app or launching it, etc.
A View
Most Chrome applications have a view. This component is optional, but is most generally used for our applications.
Building our Chrome App
In this section, we’ll walk through creating an advanced Chrome application using Angular. We’re going to create a clone of the fantastic Chrome web app Currently by the team at Rainfall.

We’ll be building a clone that we’ll call Presently.
Architecting Presently
When we’re building Presently, we’ll need to take into account the application architecture. Doing so will give us insight into how we’ll build the app when we get to code.
Like Currently, Presently will be a “newtab” app, meaning that it will launch every time we open a new tab.
Presently has two main screens:
This screen features the current time and the current weather. It also features several weather icons beside the weather.
This screen allows our users to change their location within the app.
In order to support the home screen, we need to be able to show a properly formatted date and time as well as fetch weather from a remote API service.
To support the settings screen, we must integrate with a remote API service to auto-suggest potential locations for an input box.
Finally, we’ll use the basic local storage (session storage) to persist our settings across the app.
Building the Skeleton
Building our app, we’ll set up a file structure like this one:

We’ll place our CSS files in css/
, our custom fonts in fonts/
, and our JavaScript files in js/
. We’ll set the main JavaScript file in the js/app.js
file and the HTML for our app in tab.html
at the root.
There are great tools to help bootstrap Chrome app extensions, such as Yeoman.
Before we can start up our Chrome extension, we’ll need to grab a few dependencies.
We’ll grab the latest version of angular.min.js (1.2.13), as well as angular-route.min.js, from angularjs.org and save them to the js/vendor/
directory.
Lastly, we’ll use Twitter’s Bootstrap 3 framework to style our app, so we’ll need to get the bootstrap.min.css
and save it to css/
from getbootstrap.com.
In production, when working with multiple developers, it’s often more efficient to use a tool like Bower to manage dependencies. Since we’re building a newtab app, however, it’s important that we keep our app lightweight so it launches quickly.
manifest.json
With every Chrome app we write, we need to set up a manifest.json
. This manifest tells Chrome how the application should run, what files it should use, what permissions it has, etc.
Our manifest.json
needs to describe our app as a newtab app and describe the content_security_policy
(the policies that describe what our application can and cannot do) and the background script that Chrome needs.
{
"manifest_version": 2,
"name": "Presently",
"description": "A currently clone",
"version": "0.1",
"permissions": ["http://api.wunderground.com/api/"],
"background": {
"scripts": ["js/vendor/angular.min.js"]
},
"content_security_policy": "script-src 'self'; object-src 'self'",
"chrome_url_overrides" : {
"newtab": "tab.html"
}
}
The keys in the manifest.json
are relatively straightforward and allows us to set the name, the manifest_version, the version, etc. In order to tell Chrome to launch our app as a newtab
app, we set the app to override the newtab
page.
tab.html
The main HTML file for our application is the tab.html
file. This file loads when we open a new tab in Chrome.
We’ll set up the basic Angular app inside of the tab.html
file:
<!doctype html>
<html ng-app="myApp" ng-csp="">
<head>
<meta charset="UTF-8">
<title>Presently</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div class="container">
</div>
<script src="./js/vendor/angular.min.js"></script>
<script src="./js/vendor/angular-route.min.js"></script>
<script src="./js/app.js"></script>
</body>
</html>
This very basic structure of an Angular application looks almost identical to any Angular app, with one exception: ng-csp=""
.
The ngCsp
directive enables Content Security Policy (or CSP) support for our Angular app. Since Chrome apps prevent the browser from using eval
or function(string)
generated functions, and Angular uses the function(string)
generated function for speed, ngCsp
causes Angular to evaluate all expressions.
This compatibility mode comes as a cost of performance, however, as it executes operations much more slowly, but it won’t throw any security violations in the process.
CSP also forbids JavaScript files from inlining stylesheet rules, so we need to include angular-csp.css
manually.
We can find the angular-csp.css
file at http://code.angularjs.org/snapshot/angular-csp.css.
Lastly, we must place ngCsp
alongside the root of our Angular apps:
Without the ng-csp
directive, our Chrome app will not run; it will throw a security exception. If you see a security exception thrown, make sure you check the root element for the directive.
Loading the App in Chrome
With our app in progress, let’s load it into Chrome so we can follow our progress in the browser. To load our app in Chrome, we should navigate to the URL chrome://extensions/
.
Once there, we can click on the button “Load unpackged extension…” and find the root directory (the directory that contains our manifest.json
file from above).

Once the application has been loaded into the Chrome browser, we open a new tab and should see our empty app with one error (don’t worry, we’ll fix it shortly):

Ready to master AngularJS?
- What if you could master the entire framework – with solid foundations – in less time without beating your head against a wall? Imagine how quickly you could work if you knew the best practices and the best tools?
- Stop wasting your time searching and have everything you need to be productive in one, well-organized place, with complete examples to get your project up without needing to resort to endless hours of research.
- You will learn what you need to know to work professionally with ng-book: The Complete Book on AngularJS or get your money back.
Get it now