diff --git a/keyserver/src/responders/website-responders.js b/keyserver/src/responders/website-responders.js
--- a/keyserver/src/responders/website-responders.js
+++ b/keyserver/src/responders/website-responders.js
@@ -4,80 +4,21 @@
 import { detect as detectBrowser } from 'detect-browser';
 import type { $Response, $Request } from 'express';
 import fs from 'fs';
-import _isEqual from 'lodash/fp/isEqual.js';
-import _keyBy from 'lodash/fp/keyBy.js';
 import * as React from 'react';
 // eslint-disable-next-line import/extensions
 import ReactDOMServer from 'react-dom/server';
-import t from 'tcomb';
 import { promisify } from 'util';
 
 import { inviteLinkURL } from 'lib/facts/links.js';
-import { baseLegalPolicies } from 'lib/facts/policies.js';
 import stores from 'lib/facts/stores.js';
-import { daysToEntriesFromEntryInfos } from 'lib/reducers/entry-reducer.js';
-import { freshMessageStore } from 'lib/reducers/message-reducer.js';
-import { mostRecentlyReadThread } from 'lib/selectors/thread-selectors.js';
-import { mostRecentMessageTimestamp } from 'lib/shared/message-utils.js';
-import {
-  threadHasPermission,
-  threadIsPending,
-  parsePendingThreadID,
-  createPendingThread,
-} from 'lib/shared/thread-utils.js';
-import { defaultWebEnabledApps } from 'lib/types/enabled-apps.js';
-import { entryStoreValidator } from 'lib/types/entry-types.js';
-import { defaultCalendarFilters } from 'lib/types/filter-types.js';
-import { keyserverStoreValidator } from 'lib/types/keyserver-types.js';
-import { inviteLinksStoreValidator } from 'lib/types/link-types.js';
-import {
-  defaultNumberPerThread,
-  messageStoreValidator,
-} from 'lib/types/message-types.js';
-import { defaultEnabledReports } from 'lib/types/report-types.js';
-import { defaultConnectionInfo } from 'lib/types/socket-types.js';
-import { threadPermissions } from 'lib/types/thread-permission-types.js';
-import { threadTypes } from 'lib/types/thread-types-enum.js';
-import { threadStoreValidator } from 'lib/types/thread-types.js';
-import {
-  currentUserInfoValidator,
-  userInfosValidator,
-} from 'lib/types/user-types.js';
-import { currentDateInTimeZone } from 'lib/utils/date-utils.js';
-import { ServerError } from 'lib/utils/errors.js';
-import { promiseAll } from 'lib/utils/promises.js';
-import { defaultNotifPermissionAlertInfo } from 'lib/utils/push-alerts.js';
-import { infoFromURL, urlInfoValidator } from 'lib/utils/url-utils.js';
-import {
-  tBool,
-  tNumber,
-  tShape,
-  tString,
-  ashoatKeyserverID,
-} from 'lib/utils/validation-utils.js';
 import getTitle from 'web/title/getTitle.js';
-import { navInfoValidator } from 'web/types/nav-types.js';
-import { navInfoFromURL } from 'web/url-utils.js';
-
-import { fetchEntryInfos } from '../fetchers/entry-fetchers.js';
-import { fetchPrimaryInviteLinks } from '../fetchers/link-fetchers.js';
-import { fetchMessageInfos } from '../fetchers/message-fetchers.js';
-import { hasAnyNotAcknowledgedPolicies } from '../fetchers/policy-acknowledgment-fetchers.js';
-import { fetchThreadInfos } from '../fetchers/thread-fetchers.js';
-import {
-  fetchCurrentUserInfo,
-  fetchKnownUserInfos,
-  fetchUserInfos,
-} from '../fetchers/user-fetchers.js';
-import { getWebPushConfig } from '../push/providers.js';
-import { setNewSession } from '../session/cookies.js';
+
 import { Viewer } from '../session/viewer.js';
-import { streamJSON, waitForStream } from '../utils/json-stream.js';
+import { waitForStream } from '../utils/json-stream.js';
 import {
   getAppURLFactsFromRequestURL,
   getCommAppURLFacts,
 } from '../utils/urls.js';
-import { validateOutput, validateInput } from '../utils/validation-utils.js';
 
 const { renderToNodeStream } = ReactDOMServer;
 
@@ -170,347 +111,17 @@
   }
 }
 
-const initialReduxStateValidator = tShape({
-  navInfo: navInfoValidator,
-  deviceID: t.Nil,
-  currentUserInfo: currentUserInfoValidator,
-  draftStore: t.irreducible('default draftStore', _isEqual({ drafts: {} })),
-  entryStore: entryStoreValidator,
-  threadStore: threadStoreValidator,
-  userStore: tShape({
-    userInfos: userInfosValidator,
-    inconsistencyReports: t.irreducible(
-      'default inconsistencyReports',
-      _isEqual([]),
-    ),
-  }),
-  messageStore: messageStoreValidator,
-  loadingStatuses: t.irreducible('default loadingStatuses', _isEqual({})),
-  calendarFilters: t.irreducible(
-    'defaultCalendarFilters',
-    _isEqual(defaultCalendarFilters),
-  ),
-  communityPickerStore: t.irreducible(
-    'default communityPickerStore',
-    _isEqual({ chat: null, calendar: null }),
-  ),
-  windowDimensions: t.irreducible(
-    'default windowDimensions',
-    _isEqual({ width: 0, height: 0 }),
-  ),
-  notifPermissionAlertInfo: t.irreducible(
-    'default notifPermissionAlertInfo',
-    _isEqual(defaultNotifPermissionAlertInfo),
-  ),
-  actualizedCalendarQuery: tShape({
-    startDate: t.String,
-    endDate: t.String,
-    filters: t.irreducible('default filters', _isEqual(defaultCalendarFilters)),
-  }),
-  watchedThreadIDs: t.irreducible('default watchedThreadIDs', _isEqual([])),
-  lifecycleState: tString('active'),
-  enabledApps: t.irreducible(
-    'defaultWebEnabledApps',
-    _isEqual(defaultWebEnabledApps),
-  ),
-  reportStore: t.irreducible(
-    'default reportStore',
-    _isEqual({
-      enabledReports: defaultEnabledReports,
-      queuedReports: [],
-    }),
-  ),
-  nextLocalID: tNumber(0),
-  deviceToken: t.Nil,
-  dataLoaded: t.Boolean,
-  windowActive: tBool(true),
-  userPolicies: t.irreducible('default userPolicies', _isEqual({})),
-  cryptoStore: t.irreducible(
-    'default cryptoStore',
-    _isEqual({
-      primaryIdentityKeys: null,
-      notificationIdentityKeys: null,
-    }),
-  ),
-  pushApiPublicKey: t.maybe(t.String),
-  _persist: t.Nil,
-  commServicesAccessToken: t.Nil,
-  inviteLinksStore: inviteLinksStoreValidator,
-  keyserverStore: keyserverStoreValidator,
-  initialStateLoaded: tBool(false),
-});
-
 async function websiteResponder(
   viewer: Viewer,
   req: $Request,
   res: $Response,
 ): Promise<void> {
-  const appURLFacts = getAppURLFactsFromRequestURL(req.originalUrl);
-  const { basePath, baseDomain } = appURLFacts;
+  const { basePath } = getAppURLFactsFromRequestURL(req.originalUrl);
   const baseURL = basePath.replace(/\/$/, '');
-  const urlPrefix = baseDomain + baseURL;
 
   const loadingPromise = getWebpackCompiledRootComponentForSSR();
-  const hasNotAcknowledgedPoliciesPromise = hasAnyNotAcknowledgedPolicies(
-    viewer.id,
-    baseLegalPolicies,
-  );
-
-  const initialNavInfoPromise = (async () => {
-    try {
-      let urlInfo = infoFromURL(decodeURI(req.url));
-
-      try {
-        urlInfo = await validateInput(viewer, urlInfoValidator, urlInfo, true);
-      } catch (exc) {
-        // We should still be able to handle older links
-        if (exc.message !== 'invalid_client_id_prefix') {
-          throw exc;
-        }
-      }
-
-      let backupInfo = {
-        now: currentDateInTimeZone(viewer.timeZone),
-      };
-      // Some user ids in selectedUserList might not exist in the userStore
-      // (e.g. they were included in the results of the user search endpoint)
-      // Because of that we keep their userInfos inside the navInfo.
-      if (urlInfo.selectedUserList) {
-        const fetchedUserInfos = await fetchUserInfos(urlInfo.selectedUserList);
-        const userInfos = {};
-        for (const userID in fetchedUserInfos) {
-          const userInfo = fetchedUserInfos[userID];
-          if (userInfo.username) {
-            userInfos[userID] = userInfo;
-          }
-        }
-        backupInfo = { userInfos, ...backupInfo };
-      }
-      return navInfoFromURL(urlInfo, backupInfo);
-    } catch (e) {
-      throw new ServerError(e.message);
-    }
-  })();
-
-  const calendarQueryPromise = (async () => {
-    const initialNavInfo = await initialNavInfoPromise;
-    return {
-      startDate: initialNavInfo.startDate,
-      endDate: initialNavInfo.endDate,
-      filters: defaultCalendarFilters,
-    };
-  })();
-  const messageSelectionCriteria = { joinedThreads: true };
-  const initialTime = Date.now();
 
   const assetInfoPromise = getAssetInfo();
-  const threadInfoPromise = fetchThreadInfos(viewer);
-  const messageInfoPromise = fetchMessageInfos(
-    viewer,
-    messageSelectionCriteria,
-    defaultNumberPerThread,
-  );
-  const entryInfoPromise = (async () => {
-    const calendarQuery = await calendarQueryPromise;
-    return await fetchEntryInfos(viewer, [calendarQuery]);
-  })();
-  const currentUserInfoPromise = fetchCurrentUserInfo(viewer);
-  const userInfoPromise = fetchKnownUserInfos(viewer);
-
-  const sessionIDPromise = (async () => {
-    const calendarQuery = await calendarQueryPromise;
-    if (viewer.loggedIn) {
-      await setNewSession(viewer, calendarQuery, initialTime);
-    }
-    return viewer.sessionID;
-  })();
-
-  const threadStorePromise = (async () => {
-    const [{ threadInfos }, hasNotAcknowledgedPolicies] = await Promise.all([
-      threadInfoPromise,
-      hasNotAcknowledgedPoliciesPromise,
-    ]);
-    return { threadInfos: hasNotAcknowledgedPolicies ? {} : threadInfos };
-  })();
-  const messageStorePromise = (async () => {
-    const [
-      { threadInfos },
-      { rawMessageInfos, truncationStatuses },
-      hasNotAcknowledgedPolicies,
-    ] = await Promise.all([
-      threadInfoPromise,
-      messageInfoPromise,
-      hasNotAcknowledgedPoliciesPromise,
-    ]);
-    if (hasNotAcknowledgedPolicies) {
-      return {
-        messages: {},
-        threads: {},
-        local: {},
-        currentAsOf: { [ashoatKeyserverID]: 0 },
-      };
-    }
-    const { messageStore: freshStore } = freshMessageStore(
-      rawMessageInfos,
-      truncationStatuses,
-      mostRecentMessageTimestamp(rawMessageInfos, initialTime),
-      threadInfos,
-    );
-    return freshStore;
-  })();
-  const entryStorePromise = (async () => {
-    const [{ rawEntryInfos }, hasNotAcknowledgedPolicies] = await Promise.all([
-      entryInfoPromise,
-      hasNotAcknowledgedPoliciesPromise,
-    ]);
-    if (hasNotAcknowledgedPolicies) {
-      return {
-        entryInfos: {},
-        daysToEntries: {},
-        lastUserInteractionCalendar: 0,
-      };
-    }
-    return {
-      entryInfos: _keyBy('id')(rawEntryInfos),
-      daysToEntries: daysToEntriesFromEntryInfos(rawEntryInfos),
-      lastUserInteractionCalendar: initialTime,
-    };
-  })();
-  const userStorePromise = (async () => {
-    const [userInfos, hasNotAcknowledgedPolicies] = await Promise.all([
-      userInfoPromise,
-      hasNotAcknowledgedPoliciesPromise,
-    ]);
-    return {
-      userInfos: hasNotAcknowledgedPolicies ? {} : userInfos,
-      inconsistencyReports: [],
-    };
-  })();
-
-  const navInfoPromise = (async () => {
-    const [
-      { threadInfos },
-      messageStore,
-      currentUserInfo,
-      userStore,
-      finalNavInfo,
-    ] = await Promise.all([
-      threadInfoPromise,
-      messageStorePromise,
-      currentUserInfoPromise,
-      userStorePromise,
-      initialNavInfoPromise,
-    ]);
-
-    const requestedActiveChatThreadID = finalNavInfo.activeChatThreadID;
-    if (
-      requestedActiveChatThreadID &&
-      !threadIsPending(requestedActiveChatThreadID) &&
-      !threadHasPermission(
-        threadInfos[requestedActiveChatThreadID],
-        threadPermissions.VISIBLE,
-      )
-    ) {
-      finalNavInfo.activeChatThreadID = null;
-    }
-
-    if (!finalNavInfo.activeChatThreadID) {
-      const mostRecentThread = mostRecentlyReadThread(
-        messageStore,
-        threadInfos,
-      );
-      if (mostRecentThread) {
-        finalNavInfo.activeChatThreadID = mostRecentThread;
-      }
-    }
-
-    if (
-      finalNavInfo.activeChatThreadID &&
-      threadIsPending(finalNavInfo.activeChatThreadID) &&
-      finalNavInfo.pendingThread?.id !== finalNavInfo.activeChatThreadID
-    ) {
-      const pendingThreadData = parsePendingThreadID(
-        finalNavInfo.activeChatThreadID,
-      );
-      if (
-        pendingThreadData &&
-        pendingThreadData.threadType !== threadTypes.SIDEBAR &&
-        currentUserInfo.id
-      ) {
-        const { userInfos } = userStore;
-        const members = [...pendingThreadData.memberIDs, currentUserInfo.id]
-          .map(id => {
-            const userInfo = userInfos[id];
-            if (!userInfo || !userInfo.username) {
-              return undefined;
-            }
-            const { username } = userInfo;
-            return { id, username };
-          })
-          .filter(Boolean);
-        const newPendingThread = createPendingThread({
-          viewerID: currentUserInfo.id,
-          threadType: pendingThreadData.threadType,
-          members,
-        });
-        finalNavInfo.activeChatThreadID = newPendingThread.id;
-        finalNavInfo.pendingThread = newPendingThread;
-      }
-    }
-
-    return finalNavInfo;
-  })();
-  const currentAsOfPromise = (async () => {
-    const hasNotAcknowledgedPolicies = await hasNotAcknowledgedPoliciesPromise;
-    return hasNotAcknowledgedPolicies ? 0 : initialTime;
-  })();
-
-  const pushApiPublicKeyPromise = (async () => {
-    const pushConfig = await getWebPushConfig();
-    if (!pushConfig) {
-      if (process.env.NODE_ENV !== 'development') {
-        console.warn('keyserver/secrets/web_push_config.json should exist');
-      }
-      return null;
-    }
-    return pushConfig.publicKey;
-  })();
-
-  const inviteLinksStorePromise = (async () => {
-    const primaryInviteLinks = await fetchPrimaryInviteLinks(viewer);
-    const links = {};
-    for (const link of primaryInviteLinks) {
-      if (link.primary) {
-        links[link.communityID] = {
-          primaryLink: link,
-        };
-      }
-    }
-    return {
-      links,
-    };
-  })();
-
-  const keyserverStorePromise = (async () => {
-    const { sessionID, updatesCurrentAsOf } = await promiseAll({
-      sessionID: sessionIDPromise,
-      updatesCurrentAsOf: currentAsOfPromise,
-    });
-
-    return {
-      keyserverInfos: {
-        [ashoatKeyserverID]: {
-          cookie: undefined,
-          sessionID,
-          updatesCurrentAsOf,
-          urlPrefix,
-          connection: defaultConnectionInfo,
-          lastCommunicatedPlatformDetails: null,
-        },
-      },
-    };
-  })();
-
   const {
     jsURL,
     fontsURL,
@@ -562,61 +173,9 @@
   reactStream.pipe(res, { end: false });
 
   await waitForStream(reactStream);
-  res.write(html`
+  res.end(html`
     </div>
     <script>
-      var preloadedState =
-  `);
-
-  const initialReduxState = await promiseAll({
-    navInfo: navInfoPromise,
-    deviceID: null,
-    currentUserInfo: currentUserInfoPromise,
-    draftStore: { drafts: {} },
-    entryStore: entryStorePromise,
-    threadStore: threadStorePromise,
-    userStore: userStorePromise,
-    messageStore: messageStorePromise,
-    loadingStatuses: {},
-    calendarFilters: defaultCalendarFilters,
-    communityPickerStore: { chat: null, calendar: null },
-    windowDimensions: { width: 0, height: 0 },
-    notifPermissionAlertInfo: defaultNotifPermissionAlertInfo,
-    actualizedCalendarQuery: calendarQueryPromise,
-    watchedThreadIDs: [],
-    lifecycleState: 'active',
-    enabledApps: defaultWebEnabledApps,
-    reportStore: {
-      enabledReports: defaultEnabledReports,
-      queuedReports: [],
-    },
-    nextLocalID: 0,
-    deviceToken: null,
-    dataLoaded: viewer.loggedIn,
-    windowActive: true,
-    userPolicies: {},
-    cryptoStore: {
-      primaryIdentityKeys: null,
-      notificationIdentityKeys: null,
-    },
-    pushApiPublicKey: pushApiPublicKeyPromise,
-    _persist: null,
-    commServicesAccessToken: null,
-    inviteLinksStore: inviteLinksStorePromise,
-    keyserverStore: keyserverStorePromise,
-    initialStateLoaded: false,
-  });
-  const validatedInitialReduxState = validateOutput(
-    viewer.platformDetails,
-    initialReduxStateValidator,
-    initialReduxState,
-    true,
-  );
-  const jsonStream = streamJSON(res, validatedInitialReduxState);
-
-  await waitForStream(jsonStream);
-  res.end(html`
-    ;
           var baseURL = "${baseURL}";
           var olmFilename = "${olmFilename}";
           var commQueryExecutorFilename = "${commQueryExecutorFilename}";
diff --git a/web/redux/default-state.js b/web/redux/default-state.js
new file mode 100644
--- /dev/null
+++ b/web/redux/default-state.js
@@ -0,0 +1,93 @@
+// @flow
+
+import { defaultEnabledApps } from 'lib/types/enabled-apps.js';
+import { defaultCalendarFilters } from 'lib/types/filter-types.js';
+import { defaultConnectionInfo } from 'lib/types/socket-types.js';
+import { isDev } from 'lib/utils/dev-utils.js';
+import { defaultNotifPermissionAlertInfo } from 'lib/utils/push-alerts.js';
+import { ashoatKeyserverID } from 'lib/utils/validation-utils.js';
+
+import type { AppState } from './redux-setup.js';
+
+const defaultWebState: AppState = Object.freeze({
+  navInfo: {
+    activeChatThreadID: null,
+    startDate: '',
+    endDate: '',
+    tab: 'chat',
+  },
+  currentUserInfo: null,
+  draftStore: { drafts: {} },
+  entryStore: {
+    entryInfos: {},
+    daysToEntries: {},
+    lastUserInteractionCalendar: 0,
+  },
+  threadStore: {
+    threadInfos: {},
+  },
+  userStore: {
+    userInfos: {},
+    inconsistencyReports: [],
+  },
+  messageStore: {
+    messages: {},
+    threads: {},
+    local: {},
+    currentAsOf: { [ashoatKeyserverID]: 0 },
+  },
+  windowActive: true,
+  pushApiPublicKey: null,
+  cryptoStore: {
+    primaryAccount: null,
+    primaryIdentityKeys: null,
+    notificationAccount: null,
+    notificationIdentityKeys: null,
+  },
+  deviceID: null,
+  windowDimensions: { width: window.width, height: window.height },
+  loadingStatuses: {},
+  calendarFilters: defaultCalendarFilters,
+  deviceToken: null,
+  dataLoaded: false,
+  notifPermissionAlertInfo: defaultNotifPermissionAlertInfo,
+  watchedThreadIDs: [],
+  lifecycleState: 'active',
+  enabledApps: defaultEnabledApps,
+  reportStore: {
+    enabledReports: {
+      crashReports: false,
+      inconsistencyReports: false,
+      mediaReports: false,
+    },
+    queuedReports: [],
+  },
+  nextLocalID: 0,
+  _persist: null,
+  userPolicies: {},
+  commServicesAccessToken: null,
+  inviteLinksStore: {
+    links: {},
+  },
+  actualizedCalendarQuery: {
+    startDate: '',
+    endDate: '',
+    filters: defaultCalendarFilters,
+  },
+  communityPickerStore: { chat: null, calendar: null },
+  keyserverStore: {
+    keyserverInfos: {
+      [ashoatKeyserverID]: {
+        updatesCurrentAsOf: 0,
+        urlPrefix: isDev
+          ? 'http://localhost:3000/comm'
+          : 'https://web.comm.app',
+        connection: { ...defaultConnectionInfo },
+        lastCommunicatedPlatformDetails: null,
+      },
+    },
+  },
+  initialStateLoaded: false,
+});
+
+export { defaultWebState };
diff --git a/web/redux/persist.js b/web/redux/persist.js
--- a/web/redux/persist.js
+++ b/web/redux/persist.js
@@ -35,8 +35,6 @@
 import { isSQLiteSupported } from '../database/utils/db-utils.js';
 import { workerRequestMessageTypes } from '../types/worker-types.js';
 
-declare var preloadedState: AppState;
-
 const migrations = {
   [1]: async state => {
     const {
@@ -169,9 +167,7 @@
   // the transform might change in the future, but we need to treat
   // this code like migration code (it shouldn't change).
   if (oldStorage?._persist?.version === 4) {
-    const { connection, updatesCurrentAsOf, sessionID } =
-      preloadedState.keyserverStore.keyserverInfos[ashoatKeyserverID];
-
+    const defaultConnection = defaultConnectionInfo;
     return {
       ...oldStorage,
       keyserverStore: {
@@ -180,9 +176,9 @@
           ...oldStorage.keyserverStore.keyserverInfos,
           [ashoatKeyserverID]: {
             ...oldStorage.keyserverStore.keyserverInfos[ashoatKeyserverID],
-            connection,
-            updatesCurrentAsOf,
-            sessionID,
+            connection: { ...defaultConnection },
+            updatesCurrentAsOf: 0,
+            sessionID: null,
           },
         },
       },
@@ -223,9 +219,8 @@
       keyserverInfos[key] = {
         ...state.keyserverInfos[key],
         connection: { ...defaultConnection },
-        updatesCurrentAsOf:
-          preloadedState.keyserverStore.keyserverInfos[key].updatesCurrentAsOf,
-        sessionID: preloadedState.keyserverStore.keyserverInfos[key].sessionID,
+        updatesCurrentAsOf: 0,
+        sessionID: null,
       };
     }
     return {
diff --git a/web/root.js b/web/root.js
--- a/web/root.js
+++ b/web/root.js
@@ -15,6 +15,7 @@
 import { SQLiteDataHandler } from './database/sqlite-data-handler.js';
 import { localforageConfig } from './database/utils/constants.js';
 import ErrorBoundary from './error-boundary.react.js';
+import { defaultWebState } from './redux/default-state.js';
 import InitialReduxStateGate from './redux/initial-state-gate.js';
 import { persistConfig } from './redux/persist.js';
 import { type AppState, type Action, reducer } from './redux/redux-setup.js';
@@ -23,12 +24,10 @@
 
 localforage.config(localforageConfig);
 
-declare var preloadedState: AppState;
-
 const persistedReducer = persistReducer(persistConfig, reducer);
 const store: Store<AppState, Action> = createStore(
   persistedReducer,
-  preloadedState,
+  defaultWebState,
   composeWithDevTools({})(applyMiddleware(thunk, reduxLoggerMiddleware)),
 );
 const persistor = persistStore(store);