Moved back to ng1

Change-Id: I43b284e3b3cb3ac19d43c088de988c89a7ea8807
diff --git a/src/.eslintrc.js b/src/.eslintrc.js
new file mode 100644
index 0000000..2a3da4b
--- /dev/null
+++ b/src/.eslintrc.js
@@ -0,0 +1,8 @@
+module.exports = {
+  extends: [
+    'angular'
+  ],
+  rules: {
+    'angular/no-service-method': 0
+  }
+}
diff --git a/src/app/components/logout/logout.component.ts b/src/app/components/logout/logout.component.ts
deleted file mode 100644
index 199cc10..0000000
--- a/src/app/components/logout/logout.component.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-/// <reference path="../../../../typings/index.d.ts"/>
-import {Component, OnInit} from '@angular/core';
-import {Router} from '@angular/router';
-import {AuthService} from '../../services/rest/auth.service';
-
-@Component({
-  selector: 'xos-logout',
-  template: `
-    <button *ngIf="show" (click)="logout()">Logout</button>
-    `,
-  providers: [AuthService],
-})
-export class LogoutComponent implements OnInit {
-  public show: boolean = false;
-  constructor(private AuthService: AuthService, private router: Router) {
-  }
-
-  ngOnInit() {
-    if (this.AuthService.isAuthenticated()) {
-      this.show = true;
-    }
-  }
-
-  logout() {
-    this.AuthService.logout()
-      .subscribe(
-        () => {
-          this.router.navigate(['/login']);
-        }
-      );
-  }
-}
-
diff --git a/src/app/components/tables/table.component.html b/src/app/components/tables/table.component.html
deleted file mode 100644
index d945ae7..0000000
--- a/src/app/components/tables/table.component.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<table>
-    <tr>
-        <th *ngFor="let col of _config.columns">{{col.label}}</th>
-    </tr>
-    <tr *ngFor="let item of _data">
-        <td *ngFor="let col of _config.columns">
-            {{item[col.prop]}}
-        </td>
-    </tr>
-</table>
\ No newline at end of file
diff --git a/src/app/components/tables/table.component.ts b/src/app/components/tables/table.component.ts
deleted file mode 100644
index 7e62235..0000000
--- a/src/app/components/tables/table.component.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { Observable } from 'rxjs/Rx';
-/// <reference path="../../../../typings/index.d.ts"/>
-import { IXosTableConfig } from './../../interfaces/xos-components/table.interface';
-import {Component, OnInit, Input} from '@angular/core';
-
-@Component({
-  selector: 'xos-table',
-  template: require('./table.component.html'),
-})
-export class XosTableComponent implements OnInit {
-
-  public _config;
-  public _data;
-
-  @Input() config: IXosTableConfig;
-  @Input() data: Observable<any>;
-
-
-  ngOnInit() {
-
-    if (!this.config) {
-      throw new Error('[XosTable]: You must pass a configuration');
-    }
-
-    this._config = this.config;
-    this.data.subscribe(
-      (items: any[]) => {
-        this._data = items;
-      }
-    );
-  }
-}
-
diff --git a/src/app/config/.gitignore b/src/app/config/.gitignore
deleted file mode 100644
index c96a04f..0000000
--- a/src/app/config/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!.gitignore
\ No newline at end of file
diff --git a/src/app/config/app.config.ts b/src/app/config/app.config.ts
new file mode 100644
index 0000000..7b6fa12
--- /dev/null
+++ b/src/app/config/app.config.ts
@@ -0,0 +1,11 @@
+/// <reference path="../../../typings/index.d.ts"/>
+
+export interface IAppConfig {
+    apiEndpoint: string;
+    websocketClient: string;
+}
+
+export const AppConfig: IAppConfig = {
+    apiEndpoint: 'http://xos.dev:3000/api',
+    websocketClient: 'http://xos.dev:3000'
+};
diff --git a/src/app/config/style.config.ts b/src/app/config/style.config.ts
new file mode 100644
index 0000000..120725f
--- /dev/null
+++ b/src/app/config/style.config.ts
@@ -0,0 +1,11 @@
+/// <reference path="../../../typings/index.d.ts"/>
+
+export interface IStyleConfig {
+    projectName: string;
+    favicon: string;
+}
+
+export const StyleConfig: IStyleConfig = {
+    projectName: 'CORD',
+    favicon: 'cord-favicon.png'
+};
diff --git a/src/app/core/footer/footer.html b/src/app/core/footer/footer.html
new file mode 100644
index 0000000..8d14479
--- /dev/null
+++ b/src/app/core/footer/footer.html
@@ -0,0 +1,6 @@
+<footer class="footer">
+  Build with ♥ by the&nbsp;
+  <a href="https://github.com/opencord/xos/team">
+    {{vm.brand}} Team
+  </a>
+</footer>
diff --git a/src/app/core/footer/footer.spec.ts b/src/app/core/footer/footer.spec.ts
new file mode 100644
index 0000000..06c1044
--- /dev/null
+++ b/src/app/core/footer/footer.spec.ts
@@ -0,0 +1,22 @@
+/// <reference path="../../../../typings/index.d.ts" />
+
+import * as angular from 'angular';
+import 'angular-mocks';
+import {xosFooter} from './footer';
+import {StyleConfig} from '../../config/style.config';
+
+describe('footer component', () => {
+  beforeEach(() => {
+    angular
+      .module('xosFooter', ['app/core/footer/footer.html'])
+      .component('xosFooter', xosFooter);
+    angular.mock.module('xosFooter');
+  });
+
+  it('should render "XOS Team"', angular.mock.inject(($rootScope: ng.IRootScopeService, $compile: ng.ICompileService) => {
+    const element = $compile('<xos-footer></xos-footer>')($rootScope);
+    $rootScope.$digest();
+    const footer = element.find('a');
+    expect(footer.html().trim()).toEqual(`${StyleConfig.projectName} Team`);
+  }));
+});
diff --git a/src/app/core/footer/footer.ts b/src/app/core/footer/footer.ts
new file mode 100644
index 0000000..77a223b
--- /dev/null
+++ b/src/app/core/footer/footer.ts
@@ -0,0 +1,16 @@
+import {StyleConfig} from '../../config/style.config';
+
+class FooterCtrl {
+  public brand: string;
+
+  /** @ngInject */
+  constructor() {
+    this.brand = StyleConfig.projectName;
+  }
+}
+
+export const xosFooter: angular.IComponentOptions = {
+  template: require('./footer.html'),
+  controllerAs: 'vm',
+  controller: FooterCtrl
+};
diff --git a/src/app/core/header/header.html b/src/app/core/header/header.html
new file mode 100644
index 0000000..b327754
--- /dev/null
+++ b/src/app/core/header/header.html
@@ -0,0 +1,7 @@
+<header class="header">
+  <p class="header-title">
+    <a href="#/" target="_blank">
+      {{vm.title}}
+    </a>
+  </p>
+</header>
diff --git a/src/app/core/header/header.spec.ts b/src/app/core/header/header.spec.ts
new file mode 100644
index 0000000..7c00602
--- /dev/null
+++ b/src/app/core/header/header.spec.ts
@@ -0,0 +1,22 @@
+/// <reference path="../../../../typings/index.d.ts" />
+
+import * as angular from 'angular';
+import 'angular-mocks';
+import {xosHeader} from './header';
+import {StyleConfig} from '../../config/style.config';
+
+describe('header component', () => {
+  beforeEach(() => {
+    angular
+      .module('xosHeader', ['app/core/header/header.html'])
+      .component('xosHeader', xosHeader);
+    angular.mock.module('xosHeader');
+  });
+
+  it('should render the appropriate title', angular.mock.inject(($rootScope: ng.IRootScopeService, $compile: ng.ICompileService) => {
+    const element = $compile('<xos-header></xos-header>')($rootScope);
+    $rootScope.$digest();
+    const header = element.find('a');
+    expect(header.html().trim()).toEqual(StyleConfig.projectName);
+  }));
+});
diff --git a/src/app/core/header/header.ts b/src/app/core/header/header.ts
new file mode 100644
index 0000000..c2e4c41
--- /dev/null
+++ b/src/app/core/header/header.ts
@@ -0,0 +1,15 @@
+import {StyleConfig} from '../../config/style.config';
+
+class HeaderController {
+  public title: string;
+
+  constructor() {
+    this.title = StyleConfig.projectName;
+  }
+}
+
+export const xosHeader: angular.IComponentOptions = {
+  template: require('./header.html'),
+  controllerAs: 'vm',
+  controller: HeaderController
+};
diff --git a/src/app/core/index.ts b/src/app/core/index.ts
new file mode 100644
index 0000000..d0875b6
--- /dev/null
+++ b/src/app/core/index.ts
@@ -0,0 +1,15 @@
+import {xosHeader} from './header/header';
+import {xosFooter} from './footer/footer';
+import {xosNav} from './nav/nav';
+import routesConfig from './routes';
+import {xosLogin} from './login/login';
+
+export const xosCore = 'xosCore';
+
+angular
+  .module('xosCore', ['ui.router'])
+  .config(routesConfig)
+  .component('xosHeader', xosHeader)
+  .component('xosFooter', xosFooter)
+  .component('xosNav', xosNav)
+  .component('xosLogin', xosLogin);
diff --git a/src/app/core/login/login.html b/src/app/core/login/login.html
new file mode 100644
index 0000000..f4a0724
--- /dev/null
+++ b/src/app/core/login/login.html
@@ -0,0 +1,5 @@
+<form name="login">
+  <input type="text" name="username" ng-model="username" required>
+  <input type="text" name="password" ng-model="password" required>
+  <button type="button" ng-click="vm.login(username, password)">Login</button>
+</form>
diff --git a/src/app/core/login/login.ts b/src/app/core/login/login.ts
new file mode 100644
index 0000000..af46619
--- /dev/null
+++ b/src/app/core/login/login.ts
@@ -0,0 +1,30 @@
+import {AuthService} from '../../rest/auth.rest';
+
+class LoginCtrl {
+  static $inject = ['AuthService', '$state'];
+
+  /** @ngInject */
+  constructor(
+    private authService: AuthService,
+    private $state: angular.ui.IStateService
+  ) {
+  }
+
+  public login(username: string, password: string) {
+    this.authService.login({
+      username: username,
+      password: password
+    })
+      .then(res => {
+        console.log(res);
+        this.$state.go('app');
+      })
+      .catch(e => console.error);
+  }
+}
+
+export const xosLogin: angular.IComponentOptions = {
+  template: require('./login.html'),
+  controllerAs: 'vm',
+  controller: LoginCtrl
+};
diff --git a/src/app/core/nav/nav.html b/src/app/core/nav/nav.html
new file mode 100644
index 0000000..6256369
--- /dev/null
+++ b/src/app/core/nav/nav.html
@@ -0,0 +1,7 @@
+<div class="nav">
+  <ul>
+    <li ng-repeat="route in vm.routes" ui-sref-active="active">
+      <a ui-sref="{{route.state}}">{{route.label}}</a>
+    </li>
+  </ul>
+</div>
diff --git a/src/app/core/nav/nav.scss b/src/app/core/nav/nav.scss
new file mode 100644
index 0000000..8591c15
--- /dev/null
+++ b/src/app/core/nav/nav.scss
@@ -0,0 +1,37 @@
+xos-nav {
+  display: flex;
+  flex: 1;
+  flex-direction: column;
+  flex-basis: 10%;
+  background: darken(grey, 10);
+
+  ul {
+    list-style: none;
+    padding: 0;
+    margin: 0;
+    background: grey;
+
+    > li {
+      display: flex;
+      flex-direction: column;
+      padding: 10px 20px;
+      border-bottom: 1px solid darken(grey, 20);
+
+      &.active {
+        background: darken(grey, 10);
+
+        > a {
+          color: #5aadbb;
+        }
+      }
+
+      &:hover {
+        background: darken(grey, 10);
+      }
+
+      > a {
+        cursor: pointer;
+      }
+    }
+  }
+}
diff --git a/src/app/core/nav/nav.ts b/src/app/core/nav/nav.ts
new file mode 100644
index 0000000..d90df10
--- /dev/null
+++ b/src/app/core/nav/nav.ts
@@ -0,0 +1,37 @@
+import './nav.scss';
+
+interface INavItem {
+  label: string;
+  state: string;
+}
+
+class NavCtrl {
+  public routes: INavItem[];
+
+  constructor() {
+    this.routes = [
+      {
+        label: 'Home',
+        state: 'xos.dashboard'
+      },
+      {
+        label: 'Instances',
+        state: 'xos.instances'
+      },
+      {
+        label: 'Slices',
+        state: 'xos.slices'
+      },
+      {
+        label: 'Nodes',
+        state: 'xos.nodes'
+      }
+    ];
+  }
+}
+
+export const xosNav: angular.IComponentOptions = {
+  template: require('./nav.html'),
+  controllerAs: 'vm',
+  controller: NavCtrl
+};
diff --git a/src/app/core/routes.ts b/src/app/core/routes.ts
new file mode 100644
index 0000000..5f37713
--- /dev/null
+++ b/src/app/core/routes.ts
@@ -0,0 +1,10 @@
+export default routesConfig;
+
+/** @ngInject */
+function routesConfig($stateProvider: angular.ui.IStateProvider, $urlRouterProvider: angular.ui.IUrlRouterProvider, $locationProvider: angular.ILocationProvider) {
+  $stateProvider
+    .state('login', {
+      url: '/login',
+      component: 'xosLogin'
+    });
+}
diff --git a/src/app/directives/protected.directive.ts b/src/app/directives/protected.directive.ts
deleted file mode 100644
index 8eac4fd..0000000
--- a/src/app/directives/protected.directive.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * Created by teone on 12/5/16.
- */
-import {Directive, OnDestroy} from '@angular/core';
-import {AuthService} from '../services/rest/auth.service';
-import {Router} from '@angular/router';
-
-@Directive({
-  selector: '[xosProtected]',
-  providers: [AuthService]
-})
-export class ProtectedDirective implements OnDestroy {
-
-  constructor(private authService: AuthService, private router: Router) {
-    if (!this.authService.isAuthenticated()) {
-      this.router.navigate(['/login']);
-    }
-    // TODO listen for logout
-  }
-
-  ngOnDestroy() {
-    // if (this.sub != null) {
-    //   this.sub.unsubscribe();
-    // }
-  }
-}
diff --git a/src/app/hello.html b/src/app/hello.html
deleted file mode 100644
index 3ed1088..0000000
--- a/src/app/hello.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<div xos-protected></div>
-
-<h1>{{ hello }}</h1>
-
-<xos-logout></xos-logout>
-
-<xos-table [config]="cfg" [data]="data"></xos-table>
-
-<div *ngFor="let slice of slices">
-  <b>{{slice.name}}</b>
-  <i>{{slice.backend_status}}</i>
-</div>
diff --git a/src/app/hello.ts b/src/app/hello.ts
deleted file mode 100644
index cd90d22..0000000
--- a/src/app/hello.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { Observable } from 'rxjs/Rx';
-import { IXosTableConfig } from './interfaces/xos-components/table.interface';
-/// <reference path="../../typings/index.d.ts"/>
-import {Component, OnInit} from '@angular/core';
-import {StyleConfig} from './config/style.config';
-import {ISlice} from './interfaces/models.interface';
-import {SliceStore} from './services/stores/slice.store';
-
-@Component({
-  selector: 'xos-app',
-  template: require('./hello.html'),
-  providers: [SliceStore],
-})
-export class HelloComponent implements OnInit {
-
-  // declare class properties
-  public hello: string;
-  public slices: ISlice[];
-  public data: Observable<any>;
-
-  public cfg: IXosTableConfig = {
-    columns: [
-      {
-        label: 'Name',
-        prop: 'name'
-      },
-      {
-        label: 'Default Isolation',
-        prop: 'default_isolation'
-      }
-    ]
-  };
-
-  constructor(
-    private sliceStore: SliceStore
-  ) {
-    this.hello = `Hello ${StyleConfig.projectName}!`;
-    this.slices = [];
-  }
-
-  ngOnInit() {
-    console.log('on init');
-    this.data = this.sliceStore.query();
-  }
-}
diff --git a/src/app/index.ts b/src/app/index.ts
deleted file mode 100644
index 2648153..0000000
--- a/src/app/index.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import { XosTableComponent } from './components/tables/table.component';
-import {NgModule} from '@angular/core';
-import {BrowserModule} from '@angular/platform-browser';
-import {HttpModule}    from '@angular/http';
-import {FormsModule}   from '@angular/forms';
-import {CookieService} from 'angular2-cookie/services/cookies.service';
-
-import {routing, RootComponent} from './routes';
-
-// registering components
-import {HelloComponent} from './hello';
-import {LoginComponent} from './views/login/login.component';
-import {LogoutComponent} from './components/logout/logout.component';
-
-// registering directives
-import {ProtectedDirective} from './directives/protected.directive';
-
-// registering services
-import {AuthService} from './services/rest/auth.service';
-import {XosHttp} from './services/rest/xoshttp.service';
-import {InstanceService} from './services/rest/instance.service';
-import {GlobalEvent} from './services/websockets/websocket.global';
-import {SliceService} from './services/rest/slices.service';
-
-@NgModule({
-  imports: [
-    BrowserModule,
-    FormsModule,
-    routing,
-    HttpModule
-  ],
-  declarations: [
-    RootComponent,
-    HelloComponent,
-    LoginComponent,
-    LogoutComponent,
-    XosTableComponent,
-    ProtectedDirective
-  ],
-  providers: [
-    CookieService,
-    AuthService,
-    XosHttp,
-    InstanceService,
-    SliceService,
-    GlobalEvent
-  ],
-  bootstrap: [RootComponent]
-})
-export class AppModule {}
diff --git a/src/app/interfaces/auth.interface.ts b/src/app/interfaces/auth.interface.ts
deleted file mode 100644
index 1742fb7..0000000
--- a/src/app/interfaces/auth.interface.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-export interface IAuthRequest {
-  username: string;
-  password: string;
-}
-
-export interface IAuthResponse {
-  xossessionid: string;
-  xoscsrftoken: string;
-  user: string;
-}
diff --git a/src/app/interfaces/models.interface.ts b/src/app/interfaces/models.interface.ts
deleted file mode 100644
index 77c0534..0000000
--- a/src/app/interfaces/models.interface.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-export interface IInstance {
-  id: number;
-  name: string;
-  backend_status: string;
-  created: string;
-}
-
-/**
- * @whatItDoes Describes the slice model.
- * @stable
- */
-export interface ISlice {
-  id: number;
-  name: string;
-  backend_status: string;
-  created: string;
-}
-
diff --git a/src/app/interfaces/ws.interface.ts b/src/app/interfaces/ws.interface.ts
deleted file mode 100644
index cadf44c..0000000
--- a/src/app/interfaces/ws.interface.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface IWSEvent {
- model: string;
- msg: {
-   changed_fields: string[],
-   object?: any,
-   pk?: number
- };
-}
diff --git a/src/app/interfaces/xos-components/table.interface.ts b/src/app/interfaces/xos-components/table.interface.ts
deleted file mode 100644
index 657c89d..0000000
--- a/src/app/interfaces/xos-components/table.interface.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-export interface IXosTableConfigColumn {
-    label: string;
-    prop: string;
-}
-
-export interface IXosTableConfigActionCallback {
-    (item: string): void;
-}
-
-export interface IXosTableConfigAction {
-    label: string;
-    cb: IXosTableConfigActionCallback
-}
-
-export interface IXosTableConfig {
-    columns: IXosTableConfigColumn[];
-    actions?: IXosTableConfigAction[];
-}
\ No newline at end of file
diff --git a/src/app/main.html b/src/app/main.html
new file mode 100644
index 0000000..21ebfc2
--- /dev/null
+++ b/src/app/main.html
@@ -0,0 +1,10 @@
+<div class="main-container">
+  <xos-header></xos-header>
+  <main class="main">
+    <xos-nav></xos-nav>
+    <div class="content">
+      <div ui-view></div>
+    </div>
+  </main>
+  <xos-footer></xos-footer>
+</div>
diff --git a/src/app/main.spec.ts b/src/app/main.spec.ts
new file mode 100644
index 0000000..2409163
--- /dev/null
+++ b/src/app/main.spec.ts
@@ -0,0 +1,21 @@
+/// <reference path="../../typings/index.d.ts" />
+
+import * as angular from 'angular';
+import 'angular-mocks';
+import {main} from './main';
+
+describe('main component', () => {
+  beforeEach(() => {
+    angular
+      .module('app', ['app/main.html'])
+      .component('app', main);
+    angular.mock.module('app');
+  });
+
+  it('should render the header, title, techs and footer', angular.mock.inject(($rootScope: ng.IRootScopeService, $compile: ng.ICompileService) => {
+    const element = $compile('<app></app>')($rootScope);
+    $rootScope.$digest();
+    expect(element.find('xos-header').length).toEqual(1);
+    expect(element.find('xos-footer').length).toEqual(1);
+  }));
+});
diff --git a/src/app/main.ts b/src/app/main.ts
new file mode 100644
index 0000000..11dd35a
--- /dev/null
+++ b/src/app/main.ts
@@ -0,0 +1,3 @@
+export const main: angular.IComponentOptions = {
+  template: require('./main.html')
+};
diff --git a/src/app/rest/auth.rest.ts b/src/app/rest/auth.rest.ts
new file mode 100644
index 0000000..c72b51e
--- /dev/null
+++ b/src/app/rest/auth.rest.ts
@@ -0,0 +1,41 @@
+import {AppConfig} from '../config/app.config';
+import IHttpPromiseCallbackArg = angular.IHttpPromiseCallbackArg;
+export interface IAuthRequestData {
+  username: string;
+  password: string;
+}
+
+export interface IAuthResponseData extends IHttpPromiseCallbackArg<any> {
+  data: {
+    user: string;
+    xoscsrftoken: string;
+    xossessionid: string;
+  };
+}
+export class AuthService {
+
+
+  /** @ngInject */
+  constructor(
+    private $http: angular.IHttpService,
+    private $q: angular.IQService,
+    private $cookies: angular.cookies.ICookiesService
+  ) {
+  }
+
+  public login(data: IAuthRequestData): Promise<any> {
+    const d = this.$q.defer();
+    this.$http.post(`${AppConfig.apiEndpoint}/utility/login/`, data)
+      .then((res: IAuthResponseData) => {
+        this.$cookies.put('xoscsrftoken', res.data.xoscsrftoken);
+        this.$cookies.put('xossessionid', res.data.xossessionid);
+        this.$cookies.put('xosuser', res.data.user);
+        res.data.user = JSON.parse(res.data.user);
+        d.resolve(res.data);
+      })
+      .catch(e => {
+        d.reject(e);
+      });
+    return d.promise;
+  }
+}
diff --git a/src/app/rest/core.rest.ts b/src/app/rest/core.rest.ts
new file mode 100644
index 0000000..aace3aa
--- /dev/null
+++ b/src/app/rest/core.rest.ts
@@ -0,0 +1,18 @@
+import {AppConfig} from '../config/app.config';
+export class CoreRest {
+
+  /** @ngInject */
+  constructor(
+    private $http: angular.IHttpService,
+    private $q: angular.IQService
+  ) {
+  }
+
+  public query(): Promise<any> {
+    const d = this.$q.defer();
+    this.$http.get(`${AppConfig.apiEndpoint}/core/`)
+      .then(res => d.resolve(res.data))
+      .catch(d.reject);
+    return d.promise;
+  }
+}
diff --git a/src/app/rest/index.ts b/src/app/rest/index.ts
new file mode 100644
index 0000000..d28084b
--- /dev/null
+++ b/src/app/rest/index.ts
@@ -0,0 +1,11 @@
+import {CoreRest} from './core.rest';
+import {SlicesRest} from './slices.rest';
+import {AuthService} from './auth.rest';
+
+export const xosRest = 'xosRest';
+
+angular
+  .module('xosRest', ['ngCookies'])
+  .service('CoreRest', CoreRest)
+  .service('SlicesRest', SlicesRest)
+  .service('AuthService', AuthService);
diff --git a/src/app/rest/slices.rest.ts b/src/app/rest/slices.rest.ts
new file mode 100644
index 0000000..0d1d8a1
--- /dev/null
+++ b/src/app/rest/slices.rest.ts
@@ -0,0 +1,20 @@
+import {AppConfig} from '../config/app.config';
+
+export interface IXosResourceService {
+  getResource(): ng.resource.IResourceClass<any>;
+}
+
+export class SlicesRest implements IXosResourceService{
+  static $inject = ['$resource'];
+
+  /** @ngInject */
+  constructor(
+    private $resource: ng.resource.IResourceService
+  ) {
+
+  }
+
+  public getResource(): ng.resource.IResourceClass<ng.resource.IResource<any>> {
+    return this.$resource(`${AppConfig.apiEndpoint}/core/slices/`);
+  }
+}
diff --git a/src/app/routes.ts b/src/app/routes.ts
deleted file mode 100644
index 53fa2cc..0000000
--- a/src/app/routes.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-/// <reference path="../../typings/index.d.ts"/>
-
-import {Component} from '@angular/core';
-import {RouterModule, Routes} from '@angular/router';
-import {HelloComponent} from './hello';
-import {LoginComponent} from './views/login/login.component';
-
-@Component({
-  selector: 'xos-root',
-  template: `
-    <router-outlet></router-outlet>
-  `
-})
-export class RootComponent {}
-
-export const routes: Routes = [
-  {
-    path: '',
-    component: HelloComponent
-  },
-  {
-    path: 'login',
-    component: LoginComponent
-  }
-];
-
-export const routing = RouterModule.forRoot(routes);
diff --git a/src/app/services/helpers/store.service.ts b/src/app/services/helpers/store.service.ts
deleted file mode 100644
index 80e8e05..0000000
--- a/src/app/services/helpers/store.service.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import {Injectable} from '@angular/core';
-import {IWSEvent} from '../../interfaces/ws.interface';
-import {BehaviorSubject} from 'rxjs';
-import * as _ from 'lodash';
-
-/**
- * @whatItDoes Update a BehaviorSubject after receiving an event from an Observable
- * @stable
- */
-
-@Injectable()
-export class ObservableCollectionHandler {
-
-    static update(event: IWSEvent, subject: BehaviorSubject<any>): BehaviorSubject<any> {
-      const collection: any[] = subject.value;
-
-      const index: number = _.findIndex(collection, (i) => {
-        return i.id === event.msg.object.id;
-      });
-      const exist: boolean = index > -1;
-      const isDeleted: boolean = _.includes(event.msg.changed_fields, 'deleted');
-
-      // remove
-      if (exist && isDeleted) {
-        _.remove(collection, {id: event.msg.object.id});
-      }
-      // Replace item at index using native splice
-      else if (exist && !isDeleted) {
-        collection.splice(index, 1, event.msg.object);
-      }
-      // if the element is not deleted add it
-      else if (!exist && !isDeleted) {
-        collection.push(event.msg.object);
-      }
-
-      subject.next(collection);
-
-      return subject;
-    }
-}
diff --git a/src/app/services/rest/auth.service.ts b/src/app/services/rest/auth.service.ts
deleted file mode 100644
index 978825f..0000000
--- a/src/app/services/rest/auth.service.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/// <reference path="../../../../typings/index.d.ts"/>
-
-// Imports
-import {AppConfig} from '../../config/app.config';
-import {Injectable} from '@angular/core';
-import {Http, Response, Headers} from '@angular/http';
-import {Observable} from 'rxjs/Rx';
-import {IAuthRequest, IAuthResponse} from '../../interfaces/auth.interface';
-import {CookieService} from 'angular2-cookie/core';
-
-// Import RxJs required methods
-import 'rxjs/add/operator/map';
-import 'rxjs/add/operator/catch';
-
-@Injectable()
-export class AuthService {
-  private xosToken: string;
-  private xosSessionId: string;
-  // resolve HTTP using the constructor
-  constructor (private http: Http, private cookieService: CookieService) {
-  }
-
-  // check if the user is authenticated
-  isAuthenticated(): string {
-    this.xosToken = this.cookieService.get('xoscsrftoken');
-    this.xosSessionId = this.cookieService.get('xossessionid');
-    return this.xosToken && this.xosSessionId;
-  }
-
-  // get auth info to authenticate API
-  getUserHeaders(): Headers {
-    const headers = new Headers();
-    headers.append('x-csrftoken', this.cookieService.get('xoscsrftoken'));
-    headers.append('x-sessionid', this.cookieService.get('xossessionid'));
-    return headers;
-  }
-
-  // log the user in
-  login(auth: IAuthRequest): Observable<IAuthResponse> {
-    return this.http.post(`${AppConfig.apiEndpoint}/utility/login/`, auth)
-      .map((res: Response) => res.json())
-      .map((auth: IAuthResponse) => {
-        this.storeAuth(auth);
-        auth.user = JSON.parse(auth.user);
-        return auth;
-      })
-      .catch((error: any) => Observable.throw(error.json().error || 'Server error'));
-  }
-
-  // logout the user
-  logout(): Observable<any> {
-    return this.http.post(`${AppConfig.apiEndpoint}/utility/logout/`, {xossessionid: this.xosSessionId})
-      .map((res: Response) => {
-        this.removeAuth();
-        return res.text();
-      })
-      .catch((error: any) => Observable.throw(error.json().error || 'Server error'));
-  }
-
-  // save cookies
-  private storeAuth(auth: IAuthResponse): void {
-    this.cookieService.put('xoscsrftoken', auth.xoscsrftoken);
-    this.cookieService.put('xossessionid', auth.xossessionid);
-  }
-
-  // remove cookies
-  private removeAuth(): void {
-    this.cookieService.remove('xoscsrftoken');
-    this.cookieService.remove('xossessionid');
-  }
-}
-
diff --git a/src/app/services/rest/core.service.ts b/src/app/services/rest/core.service.ts
deleted file mode 100644
index a283024..0000000
--- a/src/app/services/rest/core.service.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-/// <reference path="../../../../typings/index.d.ts"/>
-
-// Imports
-import {AppConfig} from '../../config/app.config';
-import {Injectable}     from '@angular/core';
-import {Response} from '@angular/http';
-import {Observable} from 'rxjs/Rx';
-import {XosHttp} from './xoshttp.service';
-
-// Import RxJs required methods
-import 'rxjs/add/operator/map';
-import 'rxjs/add/operator/catch';
-
-@Injectable()
-export class CoreService {
-  // private instance variable to hold base url
-  private baseUrl = AppConfig.apiEndpoint;
-
-  // Resolve HTTP using the constructor
-  constructor (private http: XosHttp) {}
-
-  // Fetch all existing comments
-  getCoreEndpoints(): Observable<any[]> {
-
-    const search = 'some=param';
-
-    // ...using get request
-    return this.http.get(`${this.baseUrl}/core/`, {search})
-    // ...and calling .json() on the response to return data
-      .map((res: Response) => res.json())
-      // ...errors if any
-      .catch((error: any) => Observable.throw(error.json().error || 'Server error'));
-
-  }
-}
diff --git a/src/app/services/rest/instance.service.ts b/src/app/services/rest/instance.service.ts
deleted file mode 100644
index 899b484..0000000
--- a/src/app/services/rest/instance.service.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/// <reference path="../../../../typings/index.d.ts"/>
-
-// Imports
-import {AppConfig} from '../../config/app.config';
-import {AuthService} from './auth.service';
-import {Injectable}     from '@angular/core';
-import {Response} from '@angular/http';
-import {XosHttp} from './xoshttp.service';
-import {Observable} from 'rxjs/Rx';
-
-// Import RxJs required methods
-import 'rxjs/add/operator/map';
-import 'rxjs/add/operator/catch';
-
-@Injectable()
-export class InstanceService {
-  private baseUrl = AppConfig.apiEndpoint;
-  constructor (private http: XosHttp, private authService: AuthService) {}
-  // Fetch all existing instances
-  query() : Observable<any[]> {
-    return this.http.get(`${this.baseUrl}/core/instances/`)
-      .map((res: Response) => res.json())
-      .catch((error: any) => Observable.throw(error.response.json().error || 'Server error'));
-  }
-}
diff --git a/src/app/services/rest/slices.service.ts b/src/app/services/rest/slices.service.ts
deleted file mode 100644
index 2b71d7a..0000000
--- a/src/app/services/rest/slices.service.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/// <reference path="../../../../typings/index.d.ts"/>
-
-// Imports
-import {AppConfig} from '../../config/app.config';
-import { Injectable }     from '@angular/core';
-import { Response} from '@angular/http';
-import {XosHttp} from './xoshttp.service';
-import {Observable} from 'rxjs/Rx';
-
-// Import RxJs required methods
-import 'rxjs/add/operator/map';
-import 'rxjs/add/operator/catch';
-
-@Injectable()
-export class SliceService {
-  private baseUrl = AppConfig.apiEndpoint;
-  constructor (private http: XosHttp) {}
-  // Fetch all existing instances
-  query() : Observable<any[]> {
-    return this.http.get(`${this.baseUrl}/core/slices/`)
-      .map((res: Response) => res.json())
-      .catch((error: any) => Observable.throw(error.response.json().error || 'Server error'));
-  }
-}
diff --git a/src/app/services/rest/xoshttp.service.ts b/src/app/services/rest/xoshttp.service.ts
deleted file mode 100644
index a300ee3..0000000
--- a/src/app/services/rest/xoshttp.service.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import {Http, RequestOptionsArgs, Response, URLSearchParams} from '@angular/http';
-import {Injectable} from '@angular/core';
-import {Observable} from 'rxjs';
-import {AuthService} from './auth.service';
-/**
- * Created by teone on 12/6/16.
- */
-@Injectable()
-export class XosHttp {
-  constructor(
-    private http: Http,
-    private authService: AuthService
-  ) {
-  }
-
-  // TODO intercept non authenticated calls and send to login (remove cookies)
-  // TODO add POST, PUT, DELETE declaration
-  get(url: string, options?: RequestOptionsArgs): Observable<Response> {
-
-    options = this.checkOptions(options);
-    options = this.getHeaders(options);
-    options = this.getParams(options);
-
-    return this.http.get(url, options);
-  }
-
-  private checkOptions(options?: RequestOptionsArgs): RequestOptionsArgs {
-    // if options are not there, create them
-    if (!options) {
-      options = {};
-    }
-    return options;
-  }
-
-  private getHeaders(options: RequestOptionsArgs): RequestOptionsArgs {
-    // add auth headers
-    options.headers = this.authService.getUserHeaders();
-    return options;
-  }
-
-  private getParams(options: RequestOptionsArgs): RequestOptionsArgs {
-    // add the no_hyperlinks param
-    if (!options.search) {
-      options.search = new URLSearchParams();
-    }
-
-    if (options.search instanceof URLSearchParams) {
-      options.search.set('no_hyperlinks', '1');
-    }
-    else if (typeof options.search === 'string') {
-      options.search += '&no_hyperlinks=1';
-    }
-    return options;
-  }
-}
diff --git a/src/app/services/stores/instance.store.ts b/src/app/services/stores/instance.store.ts
deleted file mode 100644
index 9a07095..0000000
--- a/src/app/services/stores/instance.store.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-/// <reference path="../../../../typings/index.d.ts"/>
-
-import {Injectable} from '@angular/core';
-import {BehaviorSubject} from 'rxjs/Rx';
-import {IInstance} from '../../interfaces/models.interface';
-import {InstanceService} from '../rest/instance.service';
-import {IWSEvent} from '../../interfaces/ws.interface';
-import {GlobalEvent} from '../websockets/websocket.global';
-import {ObservableCollectionHandler} from '../helpers/store.service';
-
-@Injectable()
-export class InstanceStore {
-  private _instances: BehaviorSubject<IInstance[]> = new BehaviorSubject([]);
-  constructor(private instanceService: InstanceService, private globalEvent: GlobalEvent) {
-    this.loadInitialData();
-    this.globalEvent.list()
-      .filter((e: IWSEvent) => e.model === 'Instance')
-      .subscribe(
-        (event: IWSEvent) => {
-          ObservableCollectionHandler.update(event, this._instances);
-        }
-      );
-  }
-
-  loadInitialData() {
-    this.instanceService.query()
-      .subscribe(
-        res => {
-          this._instances.next(res);
-        },
-        err => console.log('Error retrieving Instances', err)
-      );
-  }
-
-  query() {
-    return this._instances.asObservable();
-  }
-
-}
diff --git a/src/app/services/stores/slice.store.ts b/src/app/services/stores/slice.store.ts
deleted file mode 100644
index aeab9f3..0000000
--- a/src/app/services/stores/slice.store.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-/// <reference path="../../../../typings/index.d.ts"/>
-
-import {Injectable} from '@angular/core';
-import {BehaviorSubject} from 'rxjs/Rx';
-import {ISlice} from '../../interfaces/models.interface';
-import {IWSEvent} from '../../interfaces/ws.interface';
-import {GlobalEvent} from '../websockets/websocket.global';
-import {SliceService} from '../rest/slices.service';
-import {ObservableCollectionHandler} from '../helpers/store.service';
-
-@Injectable()
-export class SliceStore {
-  private _slices: BehaviorSubject<ISlice[]> = new BehaviorSubject([]);
-  constructor(private sliceService: SliceService, private globalEvent: GlobalEvent) {
-    this.loadInitialData();
-    this.globalEvent.list()
-      .filter((e: IWSEvent) => e.model === 'Slice')
-      .subscribe(
-        (event: IWSEvent) => {
-          ObservableCollectionHandler.update(event, this._slices);
-        }
-      );
-  }
-
-  loadInitialData() {
-    this.sliceService.query()
-      .subscribe(
-        res => {
-          this._slices.next(res);
-        },
-        err => console.log('Error retrieving Instances', err)
-      );
-  }
-
-  query() {
-    return this._slices.asObservable();
-  }
-
-}
diff --git a/src/app/services/websockets/websocket.global.ts b/src/app/services/websockets/websocket.global.ts
deleted file mode 100644
index 46bfbe1..0000000
--- a/src/app/services/websockets/websocket.global.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/// <reference path="../../../../typings/index.d.ts"/>
-
-import {Injectable} from '@angular/core';
-import {Subject} from 'rxjs/Rx';
-import * as io from 'socket.io-client';
-import {AppConfig} from '../../config/app.config';
-import {IWSEvent} from '../../interfaces/ws.interface';
-
-@Injectable()
-export class GlobalEvent {
-  private _events: Subject<IWSEvent> = new Subject<IWSEvent>();
-  private socket;
-  constructor() {
-    this.socket = io(AppConfig.websocketClient);
-    this.socket.on('event', (data: IWSEvent): void => {
-      console.log('event', data);
-      this._events.next(data);
-    });
-  }
-  list() {
-    return this._events.asObservable();
-  }
-}
diff --git a/src/app/views/login/login.component.ts b/src/app/views/login/login.component.ts
deleted file mode 100644
index 96492e3..0000000
--- a/src/app/views/login/login.component.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/// <reference path="../../../../typings/index.d.ts"/>
-import {Component} from '@angular/core';
-import {Router} from '@angular/router';
-import {IAuthRequest, IAuthResponse} from '../../interfaces/auth.interface';
-import {StyleConfig} from '../../config/style.config';
-import {AuthService} from '../../services/rest/auth.service';
-
-export class Auth {
-  constructor(
-    public username: string,
-    public password: string
-  ) {
-  }
-}
-
-@Component({
-  selector: 'xos-login',
-  template: require('./login.html'),
-  providers: [AuthService],
-})
-export class LoginComponent {
-  public auth: IAuthRequest;
-  public brandName;
-  constructor(private AuthService: AuthService, private router: Router) {
-    this.auth = new Auth('', '');
-    this.brandName = StyleConfig.projectName;
-  }
-
-  onSubmit(auth: IAuthRequest) {
-    this.AuthService.login(auth)
-      .subscribe(
-        (user: IAuthResponse) => {
-          this.router.navigate(['/']);
-        }
-      );
-  }
-}
-
diff --git a/src/app/views/login/login.html b/src/app/views/login/login.html
deleted file mode 100644
index 0f8362c..0000000
--- a/src/app/views/login/login.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<div class="login-container">
-  <div class="login-form">
-    <h2>Login to {{brandName}}</h2>
-    <form (ngSubmit)="onSubmit(loginForm.value)" #loginForm="ngForm">
-      <input type="email" [(ngModel)]="auth.username" name="username" required/>
-      <input type="password" [(ngModel)]="auth.password" name="password" required/>
-      <button type="submit" [disabled]="!loginForm.form.valid">Login</button>
-    </form>
-  </div>
-</div>
diff --git a/src/images/cord-favicon.png b/src/images/cord-favicon.png
deleted file mode 100644
index 758902e..0000000
--- a/src/images/cord-favicon.png
+++ /dev/null
Binary files differ
diff --git a/src/images/opencloud-favicon.png b/src/images/opencloud-favicon.png
deleted file mode 100644
index d49afe0..0000000
--- a/src/images/opencloud-favicon.png
+++ /dev/null
Binary files differ
diff --git a/src/index.html b/src/index.html
index 6d6e8c1..591a249 100644
--- a/src/index.html
+++ b/src/index.html
@@ -3,13 +3,13 @@
   <head>
     <base href="/">
     <meta charset="utf-8">
-    <title>XOS</title>
+    <title>FountainJS</title>
     <meta name="description" content="">
     <meta name="viewport" content="width=device-width">
-    <link rel="icon" type="image/png" href="images/cord-favicon.png" />
+    <link rel="icon" type="image/png" href="http://fountainjs.io/assets/imgs/fountain.png" />
   </head>
 
-  <body>
-    <xos-root>Loading XOS...</xos-root>
+  <body ng-app="app">
+    <ui-view></ui-view>
   </body>
 </html>
diff --git a/src/index.scss b/src/index.scss
index f1df96a..2cbe173 100644
--- a/src/index.scss
+++ b/src/index.scss
@@ -1,3 +1,65 @@
-body {
-  background-color: lightgrey;
+
+
+html, body, #root {
+  margin: 0;
+  height: 100%;
+  font-family: 'Open Sans', sans-serif;
+}
+
+body, h1, h2, h3 {
+  font-weight: 300
+}
+
+a {
+  color: white;
+  text-decoration: none;
+
+  &:hover {
+    color: #5aadbb;
+  }
+}
+
+.main-container {
+  display: flex;
+  flex-direction: column;
+  min-height: 100%;
+}
+.main {
+  flex: 1;
+  display: flex;
+  flex-direction: row;
+
+  .content {
+    display: flex;
+    flex: 1;
+    flex-direction: column;
+    flex-basis: 90%;
+    background: darken(grey, 25);
+    padding: 20px;
+  }
+}
+
+.header {
+  display: flex;
+  align-items: center;
+  background-color: #1f1f1f;
+}
+.header-title {
+  flex: 1;
+  font-size: 1.5rem;
+  margin: 1rem;
+}
+.header-date {
+  flex: 1;
+  text-align: right;
+  margin: 1rem;
+  white: white;
+}
+
+.footer {
+  padding: 0.5rem;
+  font-size: 1rem;
+  background-color: #1f1f1f;
+  text-align: center;
+  color: white;
 }
diff --git a/src/index.spec.js b/src/index.spec.js
index 4a2f55b..8c19f76 100644
--- a/src/index.spec.js
+++ b/src/index.spec.js
@@ -1,46 +1,4 @@
-Error.stackTraceLimit = Infinity;
-require('core-js/client/shim');
-
-require('@angular/common');
-require('rxjs');
-
-require('zone.js/dist/zone');
-require('zone.js/dist/long-stack-trace-zone');
-require('zone.js/dist/proxy');
-require('zone.js/dist/sync-test');
-require('zone.js/dist/jasmine-patch');
-require('zone.js/dist/async-test');
-require('zone.js/dist/fake-async-test');
-require('jquery');
-
-// loading app files
 const context = require.context('./app', true, /\.(js|ts|tsx)$/);
-context.keys().forEach(context);
-
-// use this for debug
-// context.keys().forEach(function(path) {
-//   try {
-//     context(path);
-//   } catch(err) {
-//     console.error('[ERROR] WITH SPEC FILE: ', path);
-//     console.error(err);
-//   }
-// });
-
-// loading specs
-const specFiles = require.context('../spec', true, /\.(js|ts|tsx)$/);
-specFiles.keys().forEach(specFiles);
-// use this for debug
-// specFiles.keys().forEach(function(path) {
-//   try {
-//     specFiles(path);
-//   } catch(err) {
-//     console.error('[ERROR] WITH SPEC FILE: ', path);
-//     console.error(err);
-//   }
-// });
-
-const testing = require('@angular/core/testing');
-const testingBrowser = require('@angular/platform-browser-dynamic/testing');
-
-testing.TestBed.initTestEnvironment(testingBrowser.BrowserDynamicTestingModule, testingBrowser.platformBrowserDynamicTesting());
+context.keys().forEach(function(f) {
+  context(f);
+});
diff --git a/src/index.ts b/src/index.ts
index baed6f9..66a32f1 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,24 +1,25 @@
-/// <reference path="../typings/index.d.ts"/>
+/// <reference path="../typings/index.d.ts" />
 
-import 'core-js/client/shim';
-import 'zone.js/dist/zone';
+import * as angular from 'angular';
 
-import '@angular/common';
-import 'rxjs';
+import 'angular-ui-router';
+import 'angular-resource';
+import 'angular-cookies';
+import routesConfig from './routes';
+
+import {main} from './app/main';
 
 import './index.scss';
+import {xosCore} from './app/core/index';
+import {xosRest} from './app/rest/index';
+import {xosViews} from './app/views/index';
+import {interceptorConfig, userStatusInterceptor, CredentialsInterceptor} from './interceptors';
 
-import {enableProdMode} from '@angular/core';
-import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
-import {AppModule} from './app';
+angular
+  .module('app', [xosCore, xosRest, xosViews, 'ui.router', 'ngResource'])
+  .config(routesConfig)
+  .config(interceptorConfig)
+  .factory('UserStatusInterceptor', userStatusInterceptor)
+  .factory('CredentialsInterceptor', CredentialsInterceptor)
+  .component('xos', main);
 
-declare var process: any;
-
-if (process.env.NODE_ENV === 'production') {
-  enableProdMode();
-} else {
-  Error['stackTraceLimit'] = Infinity; // tslint:disable-line:no-string-literal
-  require('zone.js/dist/long-stack-trace-zone'); // tslint:disable-line:no-var-requires
-}
-
-platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/src/interceptors.ts b/src/interceptors.ts
new file mode 100644
index 0000000..bd4cba3
--- /dev/null
+++ b/src/interceptors.ts
@@ -0,0 +1,39 @@
+/// <reference path="../typings/index.d.ts" />
+
+export function interceptorConfig($httpProvider: angular.IHttpProvider, $resourceProvider: angular.resource.IResourceServiceProvider) {
+  $httpProvider.interceptors.push('UserStatusInterceptor');
+  $httpProvider.interceptors.push('CredentialsInterceptor');
+  $resourceProvider.defaults.stripTrailingSlashes = false;
+}
+
+export function userStatusInterceptor($state: angular.ui.IStateService) {
+
+  const checkLogin = (res) => {
+    if (res.status === 403) {
+      $state.go('login');
+    }
+    else if (res.data.status === 403) {
+      $state.go('login');
+    }
+    return res;
+  };
+
+  return {
+    response: checkLogin,
+    responseError: checkLogin
+  };
+}
+
+export function CredentialsInterceptor($cookies: angular.cookies.ICookiesService) {
+  return {
+    request: (req) => {
+      if (!$cookies.get('xoscsrftoken') || !$cookies.get('xossessionid')) {
+        return req;
+      }
+      req.headers['X-CSRFToken'] = $cookies.get('xoscsrftoken');
+      req.headers['x-csrftoken'] = $cookies.get('xoscsrftoken');
+      req.headers['x-sessionid'] = $cookies.get('xossessionid');
+      return req;
+    }
+  };
+}
diff --git a/src/routes.ts b/src/routes.ts
new file mode 100644
index 0000000..3c8ae3d
--- /dev/null
+++ b/src/routes.ts
@@ -0,0 +1,43 @@
+/// <reference path="../typings/index.d.ts" />
+
+export default routesConfig;
+
+/** @ngInject */
+function routesConfig($stateProvider: angular.ui.IStateProvider, $urlRouterProvider: angular.ui.IUrlRouterProvider, $locationProvider: angular.ILocationProvider) {
+  $locationProvider.html5Mode(false).hashPrefix('');
+  $urlRouterProvider.otherwise('/');
+
+  $stateProvider
+    .state('xos', {
+      abstract: true,
+      url: '/',
+      component: 'xos'
+    })
+    .state('xos.dashboard', {
+      url: '',
+      parent: 'xos',
+      template: '<h1>Dashboard</h1>'
+    })
+    .state('xos.instances', {
+      url: 'instances',
+      parent: 'xos',
+      template: '<h1>Instances</h1>'
+    })
+    .state('xos.slices', {
+      url: 'slices',
+      parent: 'xos',
+      component: `xosCrud`,
+      data: {
+        title: 'Slices',
+        resource: 'SlicesRest',
+        xosTableCfg: {
+          columns: ['name', 'default_isolation']
+        }
+      }
+    })
+    .state('xos.nodes', {
+      url: 'nodes',
+      parent: 'xos',
+      template: '<h1>Nodes</h1>'
+    });
+}