diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index dceef4a22978159ad9b268808188a9d015b2b6aa..cf4d65b964a020b2d606a6c67c844f60a5b78356 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -7,6 +7,7 @@ import { ShareconnectComponent } from './shareconnect/shareconnect.component';
 import { JoblistComponent } from './joblist/joblist.component';
 
 import {LoginComponent} from './login/login.component';
+import {SettingsComponent} from './settings/settings.component';
 
 
 // import { TokenextractorComponent } from './tokenextractor/tokenextractor.component';
@@ -17,6 +18,7 @@ const routes: Routes = [
   //{ path: 'launch', component: JoblistComponent},
   { path: 'launch', component: LauncherComponent},
   { path: 'login', component: LoginComponent},
+  { path: 'settings', component: SettingsComponent },
   //  { path: 'finishlaunch', component: LauncherComponent},
   //{ path: 'cancellaunch', component: LauncherComponent},
   { path: 'sshauthz_callback', component: KeygenComponent},
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 0233606cc7accfcd1674059c7c33491cadb54eda..1321b8c20057fcd54cf7269f8847941011590b7c 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -7,4 +7,9 @@
 </div> -->
 
 <!--<app-launcher></app-launcher>-->
+<mat-sidenav-container style="height: 100%; width: 100%">
+    <mat-sidenav></mat-sidenav>
+    <mat-sidenav-content>
 <router-outlet></router-outlet>
+    </mat-sidenav-content>
+</mat-sidenav-container>
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index f938199ec7a6b5e4958cb1b0beb564467bf11ce8..fd9c94950adfd7528524a06def06a94943f9a41e 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -38,6 +38,7 @@ export class AppComponent {
     this.computesitesService.setStatusMsg(this.statusMsg);
     this.authService.setStatusMsg(this.statusMsg);
     this.statusMsg.subscribe(msg => this.displayMessage(msg));
+    this.setTheme()
 
   }
 
@@ -51,6 +52,22 @@ export class AppComponent {
      this.snackBarRef = this.snackBar.open(msg,'Dismiss');
    }
  }
+  setTheme()  {
+    var theme;
+    theme=localStorage.getItem('strudel-theme');
+    if (theme == null) {
+      theme = 'strudel-theme-light';
+    }
+    let classList = document.querySelector('app-root').classList
+    var c;
+    for (c of classList.value.split(' ')) {
+      if (c.indexOf('strudel-') == 0) {
+        console.log('remove class'+c);
+        classList.remove(c);
+      }
+    }
+    classList.add(theme);
+  }
 
 
 
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 926328e468aa0067fa4e1abeaaa0d776ad0e0de2..15ee5479ca6771fa4eba908193faab178ed637f5 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -24,6 +24,7 @@ import { StrudelappsService } from './strudelapps.service';
 import { AuthorisationService } from './authorisation.service';
 import { FlexLayoutModule } from '@angular/flex-layout';
 import { FileExplorerModule } from './file-explorer/file-explorer.module';
+import { MatMenuModule } from '@angular/material';
 
 
 import { TesService} from './tes.service';
@@ -49,6 +50,7 @@ import { LaunchDialogComponent } from './launch-dialog/launch-dialog.component';
 import { ModaldialogComponent } from './modaldialog/modaldialog.component'
 import {OverlayModule} from '@angular/cdk/overlay';
 import { LoginComponent } from './login/login.component';
+import { SettingsComponent } from './settings/settings.component';
 
 // import { FileExplorerModule } from './file-explorer/file-explorer.module';
 
@@ -73,6 +75,7 @@ import { LoginComponent } from './login/login.component';
     LaunchDialogComponent,
     ModaldialogComponent,
     LoginComponent,
+    SettingsComponent,
   ],
   imports: [
   BrowserModule,
@@ -99,6 +102,7 @@ import { LoginComponent } from './login/login.component';
   FlexLayoutModule,
   MatProgressBarModule,
   OverlayModule,
+  MatMenuModule,
 
 
   ],
diff --git a/src/app/identity.ts b/src/app/identity.ts
index 7361eeb409bfd85fe52db130e644ab151667fd89..f85d6d5f5b0252e469e67131f4410199d20f69d7 100644
--- a/src/app/identity.ts
+++ b/src/app/identity.ts
@@ -60,4 +60,5 @@ export class SshAuthzServer {
   userdefined: boolean;
   cafp: string;
   signup: string;
+  desc: string;
 }
diff --git a/src/app/launcher/launcher.component.html b/src/app/launcher/launcher.component.html
index ad8095ebb48306748f933a8e84e7d3e7132d1eb6..ff29b7a5dcd29e0457ac752a9be8a9065569dcff 100644
--- a/src/app/launcher/launcher.component.html
+++ b/src/app/launcher/launcher.component.html
@@ -12,68 +12,33 @@
   </mat-toolbar>
 <mat-sidenav-container style="height: 100%; width: 100%">
   <mat-sidenav #idSideNav mode="side" opened>
-    <mat-accordion>
-
-<!-- <mat-accordion> -->
-    <div *ngIf="(computeSitesService.appidentities | async).length == 0">
-      <mat-expansion-panel>
-        <mat-expansion-panel-header>
-        <mat-panel-title>
-          Login
-        </mat-panel-title>
-        </mat-expansion-panel-header>
-        <div *ngFor="let sshauthzserver of (authService.loggedOutAuthZ | async)">
-          <button mat-button (click)=login(sshauthzserver) fxFlex style="text-align: left"> Login to {{ sshauthzserver.name }}</button>
-          <button mat-icon-button *ngIf="sshauthzserver.userdefined === true"><mat-icon>remove</mat-icon></button>
-        </div>
-        <div *ngFor="let sshauthzserver of (authService.loggedOutAuthZ | async)">
-          <button mat-button (click)=signup(sshauthzserver) style="text-align: left"> Signup for {{ sshauthzserver.name }}</button>
+    <div fxLayout="column" style="height: 100%">
+        <div>
+            <mat-accordion>
+                <div *ngFor="let id of computeSitesService.appidentities | async">
+                <mat-expansion-panel (click)=selectId(id)>
+                    <mat-expansion-panel-header>
+                        {{ id.displayName() }}
+                    </mat-expansion-panel-header>
+                    <app-strudelapplist [applist]=id.site.appCatalog [identity]="id"></app-strudelapplist>
+                </mat-expansion-panel>
+                </div>
+            </mat-accordion>
         </div>
-        <!--<button mat-button (click) =logout() style="text-align: left">Logout</button>-->
-        <button mat-button (click) ="authService.updateAgentContents()" style="text-align: left">Refresh</button>
-      </mat-expansion-panel>
-    </div>
-    <div *ngIf="(computeSitesService.appidentities | async).length > 0">
-      <button mat-button (click) =logout() style="text-align: left; width: 100%">Logout</button>
+        <div fxFlex></div>
+            <mat-menu #actionmenu="matMenu">
+
+                <div *ngIf="(computeSitesService.appidentities | async).length > 0">
+                    <button mat-menu-item (click)="logout()"><mat-icon>logout</mat-icon>Logout</button>
+                </div>
+                <button mat-menu-item routerLink="/settings"><mat-icon>settings</mat-icon>Settings</button>
+                <button mat-menu-item routerLink="/login">Login</button>
+            </mat-menu>
+            <button mat-icon-button [matMenuTriggerFor]="actionmenu">
+                <mat-icon>more_vert</mat-icon>
+            </button>
     </div>
-    <div *ngFor="let id of computeSitesService.appidentities | async">
-	<mat-expansion-panel (click)=selectId(id)>
-		<mat-expansion-panel-header>
-			{{ id.displayName() }}
-		</mat-expansion-panel-header>
-        <app-strudelapplist [applist]=id.site.appCatalog [identity]="id"></app-strudelapplist>
-	</mat-expansion-panel>
-	</div>
-    <mat-expansion-panel>
-        <mat-expansion-panel-header>
-            Advanced
-        </mat-expansion-panel-header>
-        Select an API server
-        <div style="width: 100%">
-        <mat-form-field>
-        <mat-select [ngModel]="selectedApiServer" (selectionChange)="backendSelectionService.setApiServer($event.value)">
-            <mat-option *ngFor="let apis of backendSelectionService.apiservers|async" [value]="apis">
-                {{ apis.name }}
-            </mat-option>
-        </mat-select>
-        </mat-form-field>
-        </div>
-        <button type="button" mat-button (click)="fileInput.click()">Load Config</button>
-        <input hidden (change)="loadConfig($event)" accept=".json" #fileInput type="file" id="file">
-        <button mat-button (click)=resetConfig()>Reset Config</button>
-        <div style="width: 100%">
-        Select a theme
-        <mat-form-field >
-            <mat-select [(value)] ="theme" (selectionChange)="selectTheme($event.value)">
-                <mat-option *ngFor="let opttheme of themes" [value]="opttheme">
-                    {{ opttheme.name }}
-                </mat-option>
-            </mat-select>
-        </mat-form-field>
-        </div>
-    </mat-expansion-panel>
-	</mat-accordion>
-</mat-sidenav>
+  </mat-sidenav>
 
 <app-joblist [identity]="(identitySubject | async)"></app-joblist>
 <!--<router-outlet></router-outlet>-->
diff --git a/src/app/launcher/launcher.component.ts b/src/app/launcher/launcher.component.ts
index cd36080a22595ead3b7f6711bb38f830a9f5186a..598eb7a344540d71183c6464cb4d97ded6c622e2 100644
--- a/src/app/launcher/launcher.component.ts
+++ b/src/app/launcher/launcher.component.ts
@@ -36,7 +36,6 @@ import {OverlayContainer} from '@angular/cdk/overlay';
 export class LauncherComponent implements OnInit {
   public strudelapps: Strudelapp[];
   @Input() menuopen: boolean;
-  public themeSubject: BehaviorSubject<string>;
 
   public app: Strudelapp;
   public authorised: boolean;
@@ -47,12 +46,6 @@ export class LauncherComponent implements OnInit {
   public sshauthzservers: SshAuthzServer[];
   private launchwindow: any;
   private launchwindowWatcher: any;
-  public selectedApiServer: any;
-  private file: any;
-  private config: any;
-  public theme: any;
-  public themes: any[] = [ {'name':'Light','value':'strudel-light-theme'},
-                   {'name': 'Dark','value':'strudel-dark-theme'}]
 
   constructor( public dialog: MatDialog,
                 public tesService: TesService,
@@ -63,9 +56,6 @@ export class LauncherComponent implements OnInit {
                 ) {
       this.authService.sshAuthzServers.subscribe(o => {this.updateSshAuthZServers(o)});
       this.computeSitesService.appidentities.subscribe(o => this.verifyIdValid(o));
-      this.backendSelectionService.apiserver.subscribe((s) => this.selectedApiServer = s);
-      this.themeSubject = new BehaviorSubject<string>('strudel-dark-theme');
-      this.themeSubject.subscribe(v => this.setTheme(v));
   }
 
   verifyIdValid(o) {
@@ -90,26 +80,6 @@ export class LauncherComponent implements OnInit {
 
   ngOnInit() {
     this.strudelapps = [];
-    var lstheme: string;
-    try {
-      console.log('retrieve theme from localStorage');
-            lstheme=localStorage.getItem('strudel-theme');
-      console.log(lstheme)
-    } catch {
-    }
-    if (lstheme == null) {
-      console.log('no theme set, using light');
-      lstheme = 'strudel-light-theme';
-    }
-    //Set the value of this.theme so that the selection shows a value rather than a blank
-    console.log('trying to find the initial value for theme');
-    for (let t of this.themes) {
-      if (t.value == lstheme) {
-        console.log('found the initial value',t);
-        this.theme = t;
-      }
-    }
-    this.setTheme(lstheme);
 
   }
 
@@ -140,57 +110,4 @@ export class LauncherComponent implements OnInit {
     this.tesService.getCachetIncidents(id);
   }
 
-  loadConfig(event) {
-      const reader = new FileReader();
-      reader.onload = (e: any) => {
-          try {
-            this.config = JSON.parse(e.target.result);
-              
-              if ('computesites' in this.config) {
-                  this.computeSitesService.storeLocalComputeSites(this.config['computesites'])
-              }
-              if ('apps' in this.config) {
-                  this.computeSitesService.storeLocalStrudelApps(this.config['sitename'],this.config['apps']);
-              }
-              if ('authz' in this.config) {
-                  this.authService.storeLocalAuthZ(this.config['authz'])
-              }
-
-          } catch {
-              console.log('local config file is invalid')
-          }
-      };
-      reader.readAsText(event.target.files[0]);
-  }
-
-
-  resetConfig() {
-      this.computeSitesService.removeLocalStrudelApps();
-      this.computeSitesService.removeLocalComputeSites();
-      this.authService.removeLocalAuthZ()
-  }
-
-  setTheme(v)  {
-    console.log('Theme selected');
-    console.log(v);
-    let theme = v;
-    console.log(this.overlayContainer.getContainerElement().classList);
-    let classList = document.querySelector('app-root').classList
-    console.log('this theme');
-    console.log(this.theme);
-    if (theme == 'strudel-light-theme') {
-      classList.remove('strudel-dark-theme');
-      classList.add('strudel-light-theme');
-    }
-    if (theme == 'strudel-dark-theme') {
-      classList.remove('strudel-light-theme');
-      classList.add('strudel-dark-theme');
-    }
-    console.log('setting localStorage theme',v);
-}
-
-  selectTheme(event) {
-    this.themeSubject.next(event.value);
-    localStorage.setItem('strudel-theme',event.value);
-  }
 }
diff --git a/src/app/login/login.component.css b/src/app/login/login.component.css
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/app/login/login.component.html b/src/app/login/login.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..f61ef29bbdb343dee5196e86e35eeffde715521d
--- /dev/null
+++ b/src/app/login/login.component.html
@@ -0,0 +1,35 @@
+<mat-sidenav-container style="height: 100%; width: 100%">
+    <mat-sidenav>
+    </mat-sidenav>
+    <mat-sidenav-content>
+        <div  fxFlex style="flex: 1 1 0%; box-sizing: border-box">
+            <div fxLayout="column" fxLayoutAlign="space-around stretch" style="height: 100%; width: 100%" >
+                <div fxLayout="row">
+                    <div fxFlex></div>
+                    <div fxFlex fxLayout="column">
+                        <div style="width: 100%">
+                            <mat-form-field fxFlex>
+                                <mat-label>Choose a server</mat-label>
+                                <mat-select [(value)]="selected" (selectionChange)="selectSite($event.value)">
+                                    <mat-option *ngFor="let sshauthzserver of (authService.loggedOutAuthZ | async)" [value]="sshauthzserver">
+                                        {{ sshauthzserver.name }}
+                                    </mat-option>
+                                </mat-select>
+                            </mat-form-field>
+                        </div>
+                        <div style="width: 100%">
+                            <button fxFlex mat-button  (click)="login()">Login</button>
+                            <button fxFlex mat-button  routerLink="/launch">Cancel</button>
+                        </div>
+                        <div *ngIf="selected !== undefined">
+                            {{ selected.desc }}
+                        </div>
+                    </div>
+                    <div fxFlex></div>
+                </div>
+                <div fxFlex></div>
+                <button mat-icon-button routerLink="/settings"><mat-icon>settings</mat-icon></button>
+            </div>
+        </div>
+    </mat-sidenav-content>
+</mat-sidenav-container>
diff --git a/src/app/login/login.component.spec.ts b/src/app/login/login.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d6d85a8465b79ee37cb75c371f6e6e936997c573
--- /dev/null
+++ b/src/app/login/login.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { LoginComponent } from './login.component';
+
+describe('LoginComponent', () => {
+  let component: LoginComponent;
+  let fixture: ComponentFixture<LoginComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ LoginComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(LoginComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a0dd4a5f5aa076a67d3b3da103cd73cefb2144b2
--- /dev/null
+++ b/src/app/login/login.component.ts
@@ -0,0 +1,190 @@
+import { Component, OnInit } from '@angular/core';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA, MatDialogModule, MatDialogConfig } from '@angular/material';
+import {OverlayContainer} from '@angular/cdk/overlay';
+import { BehaviorSubject } from 'rxjs/BehaviorSubject';
+
+import {Strudelapp} from '../strudelapp';
+import { StrudelappsService } from '../strudelapps.service';
+import { TesService } from '../tes.service';
+import {BackendSelectionService } from '../backend-selection.service';
+import { AuthorisationService } from '../authorisation.service';
+import { Identity } from '../identity';
+import { Computesite } from '../computesite';
+import { LogoutdialogComponent } from '../logoutdialog/logoutdialog.component';
+import { SshAuthzServer } from '../identity';
+import { ComputesitesService } from '../computesites.service';
+
+@Component({
+  selector: 'app-login',
+  templateUrl: './login.component.html',
+  styleUrls: ['./login.component.css']
+})
+export class LoginComponent implements OnInit {
+  public strudelapps: Strudelapp[];
+  public themeSubject: BehaviorSubject<string>;
+
+  public app: Strudelapp;
+  public authorised: boolean;
+  public identity: Identity;
+  //  public identitySubject: BehaviorSubject<Identity>;
+
+  public identities: Identity[];
+  public sshauthzservers: SshAuthzServer[];
+  private launchwindow: any;
+  private launchwindowWatcher: any;
+  public selectedApiServer: any;
+  private file: any;
+  private config: any;
+  public theme: any;
+  public themes: any[] = [ {'name':'Light','value':'strudel-light-theme'},
+                   {'name': 'Dark','value':'strudel-dark-theme'}]
+  public selected: any;
+
+
+  constructor( public dialog: MatDialog,
+                public tesService: TesService,
+                public backendSelectionService: BackendSelectionService,
+                public authService: AuthorisationService,
+                public computeSitesService: ComputesitesService,
+                public overlayContainer: OverlayContainer,
+                ) {
+
+
+      this.authService.sshAuthzServers.subscribe(o => {this.updateSshAuthZServers(o)});
+      this.computeSitesService.appidentities.subscribe(o => this.verifyIdValid(o));
+      this.backendSelectionService.apiserver.subscribe((s) => this.selectedApiServer = s);
+      this.themeSubject = new BehaviorSubject<string>('strudel-dark-theme');
+      this.themeSubject.subscribe(v => this.setTheme(v));
+  }
+    
+  updateSshAuthZServers(o) {
+    this.sshauthzservers = o;
+  }
+
+  ngOnInit() {
+    this.strudelapps = [];
+    var lstheme: string;
+    try {
+      console.log('retrieve theme from localStorage');
+            lstheme=localStorage.getItem('strudel-theme');
+      console.log(lstheme)
+    } catch {
+    }
+    if (lstheme == null) {
+      console.log('no theme set, using light');
+      lstheme = 'strudel-light-theme';
+    }
+    //Set the value of this.theme so that the selection shows a value rather than a blank
+    console.log('trying to find the initial value for theme');
+    for (let t of this.themes) {
+      if (t.value == lstheme) {
+        console.log('found the initial value',t);
+        this.theme = t;
+      }
+    }
+    this.setTheme(lstheme);
+
+  }
+
+  verifyIdValid(o) {
+      let currentId = this.tesService.identitySubject.value
+      if (currentId === undefined || currentId == null) {
+          return;
+      }
+      for (let id of this.computeSitesService.appidentities.value) {
+          if (currentId == id) {
+              return;
+          }
+      }
+      this.tesService.identitySubject.next(null);
+      //if (!(this.identitySubject.value in this.computeSitesService.appidentities.value)) {
+      //    this.identitySubject.next(null);
+      //}
+  }
+
+  logout() {
+      let dialogRef = this.dialog.open(LogoutdialogComponent, {
+        width: '250px',
+        height: '400px',
+      });
+  }
+
+  login () {
+    this.authService.login(this.selected);
+  }
+
+  signup(sshauthzserver) {
+      window.open(sshauthzserver.signup);
+  }
+
+  selectSite(event: any) {
+    console.log('selecteSite');
+    console.log(event);
+    console.log(this.selected);
+  }
+
+  selectId(id: Identity) {
+    this.identity=id;
+    this.tesService.identitySubject.next(id);
+    this.tesService.clearJobs();
+    this.tesService.getJobs(id);
+    this.tesService.cancelHealthRequests();
+    this.tesService.getUserHealth(id);
+    this.tesService.getCachetIncidents(id);
+  }
+
+  loadConfig(event) {
+      const reader = new FileReader();
+      reader.onload = (e: any) => {
+          try {
+            this.config = JSON.parse(e.target.result);
+              
+              if ('computesites' in this.config) {
+                  this.computeSitesService.storeLocalComputeSites(this.config['computesites'])
+              }
+              if ('apps' in this.config) {
+                  this.computeSitesService.storeLocalStrudelApps(this.config['sitename'],this.config['apps']);
+              }
+              if ('authz' in this.config) {
+                  this.authService.storeLocalAuthZ(this.config['authz'])
+              }
+
+          } catch {
+              console.log('local config file is invalid')
+          }
+      };
+      reader.readAsText(event.target.files[0]);
+  }
+
+
+  resetConfig() {
+      this.computeSitesService.removeLocalStrudelApps();
+      this.computeSitesService.removeLocalComputeSites();
+      this.authService.removeLocalAuthZ()
+  }
+
+  setTheme(v)  {
+    console.log('Theme selected');
+    console.log(v);
+    let theme = v;
+    console.log(this.overlayContainer.getContainerElement().classList);
+    let classList = document.querySelector('app-root').classList
+    console.log('this theme');
+    console.log(this.theme);
+    if (theme == 'strudel-light-theme') {
+      classList.remove('strudel-dark-theme');
+      classList.add('strudel-light-theme');
+    }
+    if (theme == 'strudel-dark-theme') {
+      classList.remove('strudel-light-theme');
+      classList.add('strudel-dark-theme');
+    }
+    console.log('setting localStorage theme',v);
+}
+
+  selectTheme(event) {
+    this.themeSubject.next(event.value);
+    localStorage.setItem('strudel-theme',event.value);
+  }
+}
+
diff --git a/src/app/settings/settings.component.css b/src/app/settings/settings.component.css
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..a2a6464bcd8cdf0b914ec411fc71ace4b0d1d954
--- /dev/null
+++ b/src/app/settings/settings.component.html
@@ -0,0 +1,25 @@
+
+Select an API server
+                    <div style="width: 100%">
+                    <mat-form-field>
+                    <mat-select [ngModel]="selectedApiServer" (selectionChange)="backendSelectionService.setApiServer($event.value)">
+                        <mat-option *ngFor="let apis of backendSelectionService.apiservers|async" [value]="apis">
+                            {{ apis.name }}
+                        </mat-option>
+                    </mat-select>
+                    </mat-form-field>
+                    </div>
+                    <button type="button" mat-button (click)="fileInput.click()">Load Config</button>
+                    <input hidden (change)="loadConfig($event)" accept=".json" #fileInput type="file" id="file">
+                    <button mat-button (click)=resetConfig()>Reset Config</button>
+                    <div style="width: 100%">
+                    Select a theme
+                    <mat-form-field >
+                        <mat-select [(value)] ="theme" (selectionChange)="selectTheme($event.value)">
+                            <mat-option *ngFor="let opttheme of themes" [value]="opttheme">
+                                {{ opttheme.name }}
+                            </mat-option>
+                        </mat-select>
+                    </mat-form-field>
+                    </div>
+                    <button mat-button routerLink="/launch">Cancel</button>
diff --git a/src/app/settings/settings.component.spec.ts b/src/app/settings/settings.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..91588f354a969adf54e6abca48e6c852e3a2e96b
--- /dev/null
+++ b/src/app/settings/settings.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SettingsComponent } from './settings.component';
+
+describe('SettingsComponent', () => {
+  let component: SettingsComponent;
+  let fixture: ComponentFixture<SettingsComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ SettingsComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(SettingsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cbc8e15c2e59d46d1d5229afa698a768455a5b6d
--- /dev/null
+++ b/src/app/settings/settings.component.ts
@@ -0,0 +1,87 @@
+import { Component, OnInit } from '@angular/core';
+import {BackendSelectionService } from '../backend-selection.service';
+import { BehaviorSubject } from 'rxjs/BehaviorSubject';
+import {OverlayContainer} from '@angular/cdk/overlay';
+import { AuthorisationService } from '../authorisation.service';
+import { ComputesitesService } from '../computesites.service';
+
+@Component({
+  selector: 'app-settings',
+  templateUrl: './settings.component.html',
+  styleUrls: ['./settings.component.css']
+})
+export class SettingsComponent implements OnInit {
+
+  public selectedApiServer: any;
+  private file: any;
+  private config: any;
+  public theme: any;
+  public themeSubject: BehaviorSubject<string>;
+  public themes: any[] = [ {'name':'Light','value':'strudel-light-theme'},
+                   {'name': 'Dark','value':'strudel-dark-theme'}]
+  constructor(
+                public backendSelectionService: BackendSelectionService,
+                public authService: AuthorisationService,
+                public computeSitesService: ComputesitesService,
+                public overlayContainer: OverlayContainer,
+    ) { 
+      this.backendSelectionService.apiserver.subscribe((s) => this.selectedApiServer = s);
+  }
+
+  ngOnInit() {
+    this.setTheme();
+  }
+
+  loadConfig(event) {
+      const reader = new FileReader();
+      reader.onload = (e: any) => {
+          try {
+            this.config = JSON.parse(e.target.result);
+              
+              if ('computesites' in this.config) {
+                  this.computeSitesService.storeLocalComputeSites(this.config['computesites'])
+              }
+              if ('apps' in this.config) {
+                  this.computeSitesService.storeLocalStrudelApps(this.config['sitename'],this.config['apps']);
+              }
+              if ('authz' in this.config) {
+                  this.authService.storeLocalAuthZ(this.config['authz'])
+              }
+
+          } catch {
+              console.log('local config file is invalid')
+          }
+      };
+      reader.readAsText(event.target.files[0]);
+  }
+
+
+  resetConfig() {
+      this.computeSitesService.removeLocalStrudelApps();
+      this.computeSitesService.removeLocalComputeSites();
+      this.authService.removeLocalAuthZ()
+  }
+
+  setTheme()  {
+    var theme;
+    theme=localStorage.getItem('strudel-theme');
+    if (theme == null) {
+      theme = 'strudel-theme-light';
+    }
+    let classList = document.querySelector('app-root').classList
+    var c;
+    for (c of classList.value.split(' ')) {
+      if (c.indexOf('strudel-') == 0) {
+        console.log('remove class'+c);
+        classList.remove(c);
+      }
+    }
+    classList.add(theme)
+}
+
+  selectTheme(event) {
+    localStorage.setItem('strudel-theme',event.value);
+    this.setTheme();
+  }
+
+}
diff --git a/src/assets/config/computesites.json b/src/assets/config/computesites.json
index 3417aa1ff130b2d113aa87be19c0e40b2dcb5295..b5d8b970625330a96faeb93941a5a0b303a61b9c 100644
--- a/src/assets/config/computesites.json
+++ b/src/assets/config/computesites.json
@@ -1,6 +1,6 @@
 [
   {
-    "url": "https://strudel2-api-dev.cloud.cvl.org.au/m3/",
+    "url": "http://localhost:5000/",
     "name": "M3",
     "host": "m3-login2.massive.org.au",
     "dtn": "m3-dtn1.massive.org.au",
@@ -10,7 +10,7 @@
     "cancelcmd": "/usr/local/sv2/dev/sv2scancel.sh {jobid}",
     "statcmd": "/usr/local/sv2/dev/sv2stat.py",
     "userhealth": "/usr/local/sv2/dev/userhealth/bin/jsonuserhealth",
-    "cacheturis": ["https://cachet-dev.erc.monash.edu.au/api/v1/incidents?component_id=7"]
+    "cacheturis": ["https://cachet-dev.erc.monash.edu.au/api/v1/incidents"]
   },
   {
     "url": "https://strudel2-api-dev.cloud.cvl.org.au/cvluwa/",