diff --git a/ui/package.json b/ui/package.json
index 248ec15..2810525 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -10,6 +10,7 @@
     "apollo-link-context": "^1.0.18",
     "apollo-link-error": "^1.1.11",
     "apollo-link-http": "^1.5.15",
+    "apollo-link-ws": "^1.0.18",
     "babel-plugin-styled-components": "^1.10.6",
     "cookie": "^0.4.0",
     "graphql": "^14.2.1",
@@ -24,7 +25,8 @@
     "react-spring": "^8.0.27",
     "semantic-ui-css": "^2.4.1",
     "semantic-ui-react": "^0.87.2",
-    "styled-components": "^4.3.2"
+    "styled-components": "^4.3.2",
+    "subscriptions-transport-ws": "^0.9.16"
   },
   "scripts": {
     "start": "parcel start src/index.html",
diff --git a/ui/src/App.js b/ui/src/App.js
index 1bdfeb2..197960d 100644
--- a/ui/src/App.js
+++ b/ui/src/App.js
@@ -9,6 +9,7 @@ const GlobalStyle = createGlobalStyle`
 `
 
 import Routes from './Routes'
+import Messages from './Messages'
 
 class App extends Component {
   render() {
@@ -16,6 +17,7 @@ class App extends Component {
       <>
         <GlobalStyle />
         <Routes />
+        <Messages />
       </>
     )
   }
diff --git a/ui/src/Layout.js b/ui/src/Layout.js
index cbdbb3f..34ddbf5 100644
--- a/ui/src/Layout.js
+++ b/ui/src/Layout.js
@@ -82,7 +82,7 @@ class Layout extends Component {
             <Icon name="image outline" />
             <SideButtonLabel>Photos</SideButtonLabel>
           </SideButton>
-          <SideButton to="/" exact>
+          <SideButton to="/albums" exact>
             <Icon name="images outline" />
             <SideButtonLabel>Albums</SideButtonLabel>
           </SideButton>
diff --git a/ui/src/Messages.js b/ui/src/Messages.js
new file mode 100644
index 0000000..ec6e168
--- /dev/null
+++ b/ui/src/Messages.js
@@ -0,0 +1,77 @@
+import React, { Component } from 'react'
+import styled from 'styled-components'
+import { Message, Progress } from 'semantic-ui-react'
+import gql from 'graphql-tag'
+import { Subscription } from 'react-apollo'
+
+const syncSubscription = gql`
+  subscription syncSubscription {
+    scannerStatusUpdate {
+      finished
+      error
+      errorMessage
+      progress
+    }
+  }
+`
+
+const Container = styled.div`
+  position: fixed;
+  bottom: 20px;
+  right: 20px;
+  width: 500px;
+`
+
+const MessageProgress = ({ header, content, percent, ...props }) => {
+  const StyledProgress = styled(Progress)`
+    position: absolute !important;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+  `
+
+  return (
+    <Message floating {...props}>
+      <Message.Content>
+        <Message.Header>{header}</Message.Header>
+        {content}
+        <StyledProgress
+          percent={percent}
+          size="tiny"
+          attached="bottom"
+          indicating
+        />
+      </Message.Content>
+    </Message>
+  )
+}
+
+class Messages extends Component {
+  render() {
+    return (
+      <Container>
+        <Subscription subscription={syncSubscription} shouldResubscribe>
+          {({ loading, error, data }) => {
+            if (error) return <div>error {error.message}</div>
+            if (loading) return null
+
+            console.log('Data update', data)
+            const update = data.scannerStatusUpdate
+
+            return (
+              <MessageProgress
+                header={update.finished ? 'Synced' : 'Syncing'}
+                content={
+                  update.finished ? 'Finished syncing' : 'Syncing in progress'
+                }
+                percent={update.progress}
+              />
+            )
+          }}
+        </Subscription>
+      </Container>
+    )
+  }
+}
+
+export default Messages
diff --git a/ui/src/Pages/HomePage/Albums.js b/ui/src/Pages/AllAlbumsPage/Albums.js
similarity index 100%
rename from ui/src/Pages/HomePage/Albums.js
rename to ui/src/Pages/AllAlbumsPage/Albums.js
diff --git a/ui/src/Pages/HomePage/HomePage.js b/ui/src/Pages/AllAlbumsPage/AlbumsPage.js
similarity index 77%
rename from ui/src/Pages/HomePage/HomePage.js
rename to ui/src/Pages/AllAlbumsPage/AlbumsPage.js
index 3584896..008656e 100644
--- a/ui/src/Pages/HomePage/HomePage.js
+++ b/ui/src/Pages/AllAlbumsPage/AlbumsPage.js
@@ -2,7 +2,7 @@ import React, { Component } from 'react'
 import Albums from './Albums'
 import Layout from '../../Layout'
 
-class HomePage extends Component {
+class AlbumsPage extends Component {
   render() {
     return (
       <Layout>
@@ -13,4 +13,4 @@ class HomePage extends Component {
   }
 }
 
-export default HomePage
+export default AlbumsPage
diff --git a/ui/src/Routes.js b/ui/src/Routes.js
index 928795f..8aa2855 100644
--- a/ui/src/Routes.js
+++ b/ui/src/Routes.js
@@ -1,8 +1,8 @@
 import React, { Component } from 'react'
-import { Route, Switch } from 'react-router-dom'
+import { Route, Switch, Redirect } from 'react-router-dom'
 
 import LoginPage from './Pages/LoginPage'
-import HomePage from './Pages/HomePage/HomePage'
+import AlbumsPage from './Pages/AllAlbumsPage/AlbumsPage'
 import AlbumPage from './Pages/AlbumPage/AlbumPage'
 import AuthorizedRoute from './AuthorizedRoute'
 import PhotosPage from './Pages/PhotosPage/PhotosPage'
@@ -12,9 +12,11 @@ class Routes extends Component {
     return (
       <Switch>
         <Route path="/login" component={LoginPage} />
-        <AuthorizedRoute exact path="/" component={HomePage} />
+        <AuthorizedRoute exact path="/albums" component={AlbumsPage} />
         <AuthorizedRoute path="/album/:id" component={AlbumPage} />
         <AuthorizedRoute path="/photos" component={PhotosPage} />
+        <Route path="/" exact render={() => <Redirect to="photos" />} />
+        <Route render={() => <div>Page not found</div>} />
       </Switch>
     )
   }
diff --git a/ui/src/apolloClient.js b/ui/src/apolloClient.js
index 60291c3..04a0559 100644
--- a/ui/src/apolloClient.js
+++ b/ui/src/apolloClient.js
@@ -1,15 +1,41 @@
 import { ApolloClient } from 'apollo-client'
 import { InMemoryCache } from 'apollo-cache-inmemory'
 import { HttpLink } from 'apollo-link-http'
+import { WebSocketLink } from 'apollo-link-ws'
 import { onError } from 'apollo-link-error'
 import { setContext } from 'apollo-link-context'
-import { ApolloLink } from 'apollo-link'
+import { ApolloLink, split } from 'apollo-link'
+import { getMainDefinition } from 'apollo-utilities'
 
 const httpLink = new HttpLink({
   uri: process.env.REACT_APP_GRAPHQL_URI,
   credentials: 'same-origin',
 })
 
+const wsLink = new WebSocketLink({
+  uri: `ws://localhost:4001/graphql`,
+  credentials: 'same-origin',
+  options: {
+    reconnect: true,
+    connectionParams: {
+      Authorization: `Bearer ${localStorage.getItem('token')}`,
+    },
+  },
+})
+
+const link = split(
+  // split based on operation type
+  ({ query }) => {
+    const definition = getMainDefinition(query)
+    return (
+      definition.kind === 'OperationDefinition' &&
+      definition.operation === 'subscription'
+    )
+  },
+  wsLink,
+  httpLink
+)
+
 const linkError = onError(({ graphQLErrors, networkError }) => {
   if (graphQLErrors)
     graphQLErrors.map(({ message, locations, path }) =>
@@ -17,7 +43,8 @@ const linkError = onError(({ graphQLErrors, networkError }) => {
         `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
       )
     )
-  if (networkError) console.log(`[Network error]: ${networkError}`)
+  if (networkError)
+    console.log(`[Network error]: ${JSON.stringify(networkError)}`)
 })
 
 const authLink = setContext((_, { headers }) => {
@@ -33,7 +60,7 @@ const authLink = setContext((_, { headers }) => {
 })
 
 const client = new ApolloClient({
-  link: ApolloLink.from([linkError, authLink.concat(httpLink)]),
+  link: ApolloLink.from([linkError, authLink.concat(link)]),
   cache: new InMemoryCache(),
 })
 
diff --git a/ui/yarn.lock b/ui/yarn.lock
index e2836ae..373dc0c 100644
--- a/ui/yarn.lock
+++ b/ui/yarn.lock
@@ -1133,6 +1133,14 @@ apollo-link-http@^1.5.15:
     apollo-link-http-common "^0.2.14"
     tslib "^1.9.3"
 
+apollo-link-ws@^1.0.18:
+  version "1.0.18"
+  resolved "https://registry.yarnpkg.com/apollo-link-ws/-/apollo-link-ws-1.0.18.tgz#281b9b0826d5fc7e2aa14d2784c5193d8b761112"
+  integrity sha512-nrWh9m7k1FQw1AK1GB1VTJS0o01cpsP2RYmTAh2j+P4lL2/72WgsblhbuF+yA1/jsgVrzg6xa+TNw3UwgGp3+g==
+  dependencies:
+    apollo-link "^1.2.12"
+    tslib "^1.9.3"
+
 apollo-link@^1.0.0, apollo-link@^1.2.12:
   version "1.2.12"
   resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.12.tgz#014b514fba95f1945c38ad4c216f31bcfee68429"
@@ -1328,6 +1336,11 @@ babylon-walk@^1.0.2:
     babel-types "^6.15.0"
     lodash.clone "^4.5.0"
 
+backo2@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
+  integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
+
 balanced-match@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@@ -2515,6 +2528,11 @@ etag@~1.8.1:
   resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
   integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
 
+eventemitter3@^3.1.0:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
+  integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==
+
 events@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
@@ -3531,7 +3549,7 @@ isstream@~0.1.2:
   resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
   integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
 
-iterall@^1.2.2:
+iterall@^1.2.1, iterall@^1.2.2:
   version "1.2.2"
   resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7"
   integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==
@@ -6034,6 +6052,17 @@ stylis@^3.5.0:
   resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe"
   integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==
 
+subscriptions-transport-ws@^0.9.16:
+  version "0.9.16"
+  resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.16.tgz#90a422f0771d9c32069294c08608af2d47f596ec"
+  integrity sha512-pQdoU7nC+EpStXnCfh/+ho0zE0Z+ma+i7xvj7bkXKb1dvYHSZxgRPaU6spRP+Bjzow67c/rRDoix5RT0uU9omw==
+  dependencies:
+    backo2 "^1.0.2"
+    eventemitter3 "^3.1.0"
+    iterall "^1.2.1"
+    symbol-observable "^1.0.4"
+    ws "^5.2.0"
+
 supports-color@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
@@ -6080,7 +6109,7 @@ svgo@^1.0.0, svgo@^1.0.5:
     unquote "~1.1.1"
     util.promisify "~1.0.0"
 
-symbol-observable@^1.0.2, symbol-observable@^1.1.0:
+symbol-observable@^1.0.2, symbol-observable@^1.0.4, symbol-observable@^1.1.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
   integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
