diff --git a/src/style.css b/src/style.css
index a079c506f16bb033d5a9c596b19f25315c861d9f..ffaf7aa92366ba722c5413260da655eaff0b3222 100644
--- a/src/style.css
+++ b/src/style.css
@@ -65,6 +65,11 @@ todo: this style should actually be in hydrogen-web
     width: 100%;
 }
 
+.ChatterboxView {
+    width: 375px;
+    height: 570px;
+}
+
 .hydrogen {
     background-color: transparent !important;
 }
diff --git a/src/ui/views/ChatterboxView.ts b/src/ui/views/ChatterboxView.ts
index c8be32f057b20aa4d7c1ce0ac2cc46df57f72bae..632bd0b4bf0b60712d941d068452abeb45f8fb89 100644
--- a/src/ui/views/ChatterboxView.ts
+++ b/src/ui/views/ChatterboxView.ts
@@ -1,12 +1,12 @@
-import { TemplateView, TimelineView } from "hydrogen-view-sdk";
+import { TemplateView, TimelineView, LoadingView } from "hydrogen-view-sdk";
 import { Builder } from "hydrogen-view-sdk/types/platform/web/ui/general/TemplateView";
 import { MessageComposer } from "hydrogen-view-sdk";
 import { ChatterboxViewModel } from "../../viewmodels/ChatterboxViewModel";
 
 export class ChatterboxView extends TemplateView<ChatterboxViewModel> {
     render(t: Builder<ChatterboxViewModel>) {
-        return t.div([
-            t.mapView(vm => vm.timelineViewModel, vm => vm ? new TimelineView(vm) : null),
+        return t.div({className: "ChatterboxView"}, [
+            t.mapView(vm => vm.timelineViewModel, vm => vm ? new TimelineView(vm) : new LoadingView()),
             t.mapView(vm => vm.messageComposerViewModel, vm => vm ? new MessageComposer(vm) : null)
         ]);
     }
diff --git a/src/viewmodels/AccountSetupViewModel.ts b/src/viewmodels/AccountSetupViewModel.ts
index 39a750bffafa8cb76bec5a23cd1f481b69a599ff..448b79a9b904d80cead20df2a2d956ca3752549d 100644
--- a/src/viewmodels/AccountSetupViewModel.ts
+++ b/src/viewmodels/AccountSetupViewModel.ts
@@ -34,13 +34,13 @@ export class AccountSetupViewModel extends ViewModel {
             stage = await stage.complete();
         }
         // stage is username when registration is completed
-        await this.login(stage, this._password);
+        const loginPromise = this.login(stage, this._password);
+        this._applySegment("timeline", loginPromise);
     }
 
     async login(username: string, password: string): Promise<void> {
         const loginOptions = await this._client.queryLogin(this._homeserver).result;
         this._client.startWithLogin(loginOptions.password(username, password));
-
         await this._client.loadStatus.waitFor((status: string) => {
             return status === LoadStatus.Ready ||
                 status === LoadStatus.Error ||
@@ -52,8 +52,6 @@ export class AccountSetupViewModel extends ViewModel {
         } else if (this._client.loadError) {
             throw new Error("load failed: " + this._client.loadError.message);
         }
-
-        this._applySegment("timeline");
     }
 
     dismiss() {
diff --git a/src/viewmodels/ChatterboxViewModel.ts b/src/viewmodels/ChatterboxViewModel.ts
index c62f6fe76b2f59c3fd9341e2f381b20a46f193a5..b3c3d36945bd49cdf3765bf0904ae9012a8f4a2e 100644
--- a/src/viewmodels/ChatterboxViewModel.ts
+++ b/src/viewmodels/ChatterboxViewModel.ts
@@ -1,16 +1,19 @@
 import { RoomViewModel, ViewModel, TimelineViewModel, ComposerViewModel} from "hydrogen-view-sdk";
 
 export class ChatterboxViewModel extends ViewModel {
-    private readonly _session: any;
     private _timelineViewModel?: TimelineViewModel;
     private _messageComposerViewModel?: ComposerViewModel;
+    private _loginPromise: Promise<void>;
 
     constructor(options) {
         super(options);
-        this._session = options.session; 
+        this._client = options.client;
+        this._loginPromise = options.loginPromise;
     }
 
     async loadRoom() {
+        // wait until login is completed
+        await this._loginPromise;
         const roomId = this._options.config["auto_join_room"];
         const room = this._session.rooms.get(roomId) ?? await this._joinRoom(roomId);
         const roomVm = new RoomViewModel({
@@ -23,6 +26,7 @@ export class ChatterboxViewModel extends ViewModel {
         await roomVm.load();
         this._timelineViewModel = roomVm.timelineViewModel;
         this._messageComposerViewModel = new ComposerViewModel(roomVm);
+        this.emitChange("timelineViewModel");
     }
 
     private async _joinRoom(roomId: string): Promise<any> {
@@ -55,4 +59,8 @@ export class ChatterboxViewModel extends ViewModel {
     get messageComposerViewModel() {
         return this._messageComposerViewModel;
     }
+
+    private get _session() {
+        return this._client.session;
+    }
 }
diff --git a/src/viewmodels/RootViewModel.ts b/src/viewmodels/RootViewModel.ts
index 4ec090bbaf11882470444b2909b06920f5070409..795794950fdc62e5fd50d13c4436d0b1c0eb33fe 100644
--- a/src/viewmodels/RootViewModel.ts
+++ b/src/viewmodels/RootViewModel.ts
@@ -24,7 +24,7 @@ export class RootViewModel extends ViewModel {
 
     private _setupNavigation() {
         this.navigation.observe("account-setup").subscribe(() => this._showAccountSetup());
-        this.navigation.observe("timeline").subscribe(() => this._showTimeline());
+        this.navigation.observe("timeline").subscribe((loginPromise) => this._showTimeline(loginPromise));
         this.navigation.observe("start").subscribe(() => this._showStartButton());
     }
 
@@ -37,17 +37,18 @@ export class RootViewModel extends ViewModel {
         this._applySegment("account-setup");
     }
 
-    private async _showTimeline() {
+    private async _showTimeline(loginPromise: Promise<void>) {
         this._activeSection = "timeline";
         this._chatterBoxViewModel = new ChatterboxViewModel(
             this.childOptions({
-                session: this._client.session,
+                client: this._client,
                 config: this._config,
                 state: this._state,
                 applySegment: this._applySegment,
+                loginPromise,
             })
         );
-        await this._chatterBoxViewModel.loadRoom();
+        this._chatterBoxViewModel.loadRoom();
         this.emitChange("activeSection");
     }