diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index cd88c188..d9706960 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -4,119 +4,137 @@ import routes from './routes'
 
 import App from '../App.vue'
 
-const afterStoreSetup = ({ store, i18n }) => {
-  window.fetch('/api/statusnet/config.json')
-    .then((res) => res.json())
-    .then((data) => {
-      const { name, closed: registrationClosed, textlimit, uploadlimit, server, vapidPublicKey } = data.site
+const getStatusnetConfig = async ({ store }) => {
+  try {
+    const res = await window.fetch('/api/statusnet/config.json')
+    const data = await res.json()
+    const { name, closed: registrationClosed, textlimit, uploadlimit, server, vapidPublicKey } = data.site
 
-      store.dispatch('setInstanceOption', { name: 'name', value: name })
-      store.dispatch('setInstanceOption', { name: 'registrationOpen', value: (registrationClosed === '0') })
-      store.dispatch('setInstanceOption', { name: 'textlimit', value: parseInt(textlimit) })
-      store.dispatch('setInstanceOption', { name: 'server', value: server })
+    store.dispatch('setInstanceOption', { name: 'name', value: name })
+    store.dispatch('setInstanceOption', { name: 'registrationOpen', value: (registrationClosed === '0') })
+    store.dispatch('setInstanceOption', { name: 'textlimit', value: parseInt(textlimit) })
+    store.dispatch('setInstanceOption', { name: 'server', value: server })
 
-      // TODO: default values for this stuff, added if to not make it break on
-      // my dev config out of the box.
-      if (uploadlimit) {
-        store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadlimit.uploadlimit) })
-        store.dispatch('setInstanceOption', { name: 'avatarlimit', value: parseInt(uploadlimit.avatarlimit) })
-        store.dispatch('setInstanceOption', { name: 'backgroundlimit', value: parseInt(uploadlimit.backgroundlimit) })
-        store.dispatch('setInstanceOption', { name: 'bannerlimit', value: parseInt(uploadlimit.bannerlimit) })
+    // TODO: default values for this stuff, added if to not make it break on
+    // my dev config out of the box.
+    if (uploadlimit) {
+      store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadlimit.uploadlimit) })
+      store.dispatch('setInstanceOption', { name: 'avatarlimit', value: parseInt(uploadlimit.avatarlimit) })
+      store.dispatch('setInstanceOption', { name: 'backgroundlimit', value: parseInt(uploadlimit.backgroundlimit) })
+      store.dispatch('setInstanceOption', { name: 'bannerlimit', value: parseInt(uploadlimit.bannerlimit) })
+    }
+
+    if (vapidPublicKey) {
+      store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey })
+    }
+
+    return data.site.pleromafe
+  } catch (error) {
+    console.error('Could not load statusnet config, potentially fatal')
+    console.error(error)
+  }
+}
+
+const getStaticConfig = async () => {
+  try {
+    const res = await window.fetch('/static/config.json')
+    return res.json()
+  } catch (error) {
+    console.warn('Failed to load static/config.json, continuing without it.')
+    console.warn(error)
+    return {}
+  }
+}
+
+const setSettings = async ({ apiConfig, staticConfig, store }) => {
+  const overrides = window.___pleromafe_dev_overrides || {}
+  const env = window.___pleromafe_mode.NODE_ENV
+
+  // This takes static config and overrides properties that are present in apiConfig
+  let config = {}
+  if (overrides.staticConfigPreference && env === 'development') {
+    console.warn('OVERRIDING API CONFIG WITH STATIC CONFIG')
+    config = Object.assign({}, apiConfig, staticConfig)
+  } else {
+    config = Object.assign({}, staticConfig, apiConfig)
+  }
+
+  const copyInstanceOption = (name) => {
+    store.dispatch('setInstanceOption', { name, value: config[name] })
+  }
+
+  copyInstanceOption('nsfwCensorImage')
+  copyInstanceOption('background')
+  copyInstanceOption('hidePostStats')
+  copyInstanceOption('hideUserStats')
+  copyInstanceOption('hideFilteredStatuses')
+  copyInstanceOption('logo')
+
+  store.dispatch('setInstanceOption', {
+    name: 'logoMask',
+    value: typeof config.logoMask === 'undefined'
+      ? true
+      : config.logoMask
+  })
+
+  store.dispatch('setInstanceOption', {
+    name: 'logoMargin',
+    value: typeof config.logoMargin === 'undefined'
+      ? 0
+      : config.logoMargin
+  })
+
+  copyInstanceOption('redirectRootNoLogin')
+  copyInstanceOption('redirectRootLogin')
+  copyInstanceOption('showInstanceSpecificPanel')
+  copyInstanceOption('scopeOptionsEnabled')
+  copyInstanceOption('formattingOptionsEnabled')
+  copyInstanceOption('collapseMessageWithSubject')
+  copyInstanceOption('loginMethod')
+  copyInstanceOption('scopeCopy')
+  copyInstanceOption('subjectLineBehavior')
+  copyInstanceOption('postContentType')
+  copyInstanceOption('alwaysShowSubjectInput')
+  copyInstanceOption('noAttachmentLinks')
+  copyInstanceOption('showFeaturesPanel')
+
+  if ((config.chatDisabled)) {
+    store.dispatch('disableChat')
+  } else {
+    store.dispatch('initializeSocket')
+  }
+
+  return store.dispatch('setTheme', config['theme'])
+}
+
+const afterStoreSetup = async ({ store, i18n }) => {
+  const apiConfig = await getStatusnetConfig({ store })
+  const staticConfig = await getStaticConfig()
+  await setSettings({ store, apiConfig, staticConfig })
+  // Now we have the server settings and can try logging in
+  if (store.state.oauth.token) {
+    store.dispatch('loginUser', store.state.oauth.token)
+  }
+
+  const router = new VueRouter({
+    mode: 'history',
+    routes: routes(store),
+    scrollBehavior: (to, _from, savedPosition) => {
+      if (to.matched.some(m => m.meta.dontScroll)) {
+        return false
       }
+      return savedPosition || { x: 0, y: 0 }
+    }
+  })
 
-      if (vapidPublicKey) {
-        store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey })
-      }
-
-      var apiConfig = data.site.pleromafe
-
-      window.fetch('/static/config.json')
-        .then((res) => res.json())
-        .catch((err) => {
-          console.warn('Failed to load static/config.json, continuing without it.')
-          console.warn(err)
-          return {}
-        })
-        .then((staticConfig) => {
-          const overrides = window.___pleromafe_dev_overrides || {}
-          const env = window.___pleromafe_mode.NODE_ENV
-
-          // This takes static config and overrides properties that are present in apiConfig
-          let config = {}
-          if (overrides.staticConfigPreference && env === 'development') {
-            console.warn('OVERRIDING API CONFIG WITH STATIC CONFIG')
-            config = Object.assign({}, apiConfig, staticConfig)
-          } else {
-            config = Object.assign({}, staticConfig, apiConfig)
-          }
-
-          const copyInstanceOption = (name) => {
-            store.dispatch('setInstanceOption', {name, value: config[name]})
-          }
-
-          copyInstanceOption('nsfwCensorImage')
-          copyInstanceOption('background')
-          copyInstanceOption('hidePostStats')
-          copyInstanceOption('hideUserStats')
-          copyInstanceOption('hideFilteredStatuses')
-          copyInstanceOption('logo')
-
-          store.dispatch('setInstanceOption', {
-            name: 'logoMask',
-            value: typeof config.logoMask === 'undefined'
-              ? true
-              : config.logoMask
-          })
-
-          store.dispatch('setInstanceOption', {
-            name: 'logoMargin',
-            value: typeof config.logoMargin === 'undefined'
-              ? 0
-              : config.logoMargin
-          })
-
-          copyInstanceOption('redirectRootNoLogin')
-          copyInstanceOption('redirectRootLogin')
-          copyInstanceOption('showInstanceSpecificPanel')
-          copyInstanceOption('scopeOptionsEnabled')
-          copyInstanceOption('formattingOptionsEnabled')
-          copyInstanceOption('collapseMessageWithSubject')
-          copyInstanceOption('loginMethod')
-          copyInstanceOption('scopeCopy')
-          copyInstanceOption('subjectLineBehavior')
-          copyInstanceOption('postContentType')
-          copyInstanceOption('alwaysShowSubjectInput')
-          copyInstanceOption('noAttachmentLinks')
-          copyInstanceOption('showFeaturesPanel')
-
-          if (config.chatDisabled) {
-            store.dispatch('disableChat')
-          }
-
-          return store.dispatch('setTheme', config['theme'])
-        })
-        .then(() => {
-          const router = new VueRouter({
-            mode: 'history',
-            routes: routes(store),
-            scrollBehavior: (to, _from, savedPosition) => {
-              if (to.matched.some(m => m.meta.dontScroll)) {
-                return false
-              }
-              return savedPosition || { x: 0, y: 0 }
-            }
-          })
-
-          /* eslint-disable no-new */
-          new Vue({
-            router,
-            store,
-            i18n,
-            el: '#app',
-            render: h => h(App)
-          })
-        })
-    })
+  /* eslint-disable no-new */
+  new Vue({
+    router,
+    store,
+    i18n,
+    el: '#app',
+    render: h => h(App)
+  })
 
   window.fetch('/static/terms-of-service.html')
     .then((res) => res.text())
@@ -157,7 +175,7 @@ const afterStoreSetup = ({ store, i18n }) => {
       store.dispatch('setInstanceOption', { name: 'instanceSpecificPanelContent', value: html })
     })
 
-  window.fetch('/nodeinfo/2.0.json')
+  return window.fetch('/nodeinfo/2.0.json')
     .then((res) => res.json())
     .then((data) => {
       const metadata = data.metadata
@@ -167,8 +185,6 @@ const afterStoreSetup = ({ store, i18n }) => {
       store.dispatch('setInstanceOption', { name: 'chatAvailable', value: features.includes('chat') })
       store.dispatch('setInstanceOption', { name: 'gopherAvailable', value: features.includes('gopher') })
 
-      store.dispatch('setInstanceOption', { name: 'postFormats', value: metadata.postFormats })
-
       store.dispatch('setInstanceOption', { name: 'restrictedNicknames', value: metadata.restrictedNicknames })
 
       const suggestions = metadata.suggestions