diff --git a/public/config.json b/public/config.json
index c6e0925f58f00099ca2d2adbd2758b250f429030..6bf7142ecbc58c5c71751a8ed0943c803dc04303 100644
--- a/public/config.json
+++ b/public/config.json
@@ -6,5 +6,6 @@
         "title": "Chatterbox Test Room",
         "avatar": "https://i.picsum.photos/id/907/200/200.jpg?hmac=SdeLZNONJ3CX-OB15hSXsCheWDC6yYac5N5VUJM7FIQ"
     },
-    "token": "k9SL1R~GcdbjiFjC"
+    "token": "k9SL1R~GcdbjiFjC",
+    "invite_user": "@midhun:matrix.midhun.dev"
 }
diff --git a/src/types/IChatterboxConfig.ts b/src/types/IChatterboxConfig.ts
index 789fcc58cdd0676a79d56539a13e3f5c8bcb3caa..8e0720216f1b0618386a9f49f3d779b90f7a2b38 100644
--- a/src/types/IChatterboxConfig.ts
+++ b/src/types/IChatterboxConfig.ts
@@ -1,9 +1,12 @@
 export interface IChatterboxConfig {
 	homeserver: string;
-    // internal room-id of the room to which chatterbox should join
+    // Internal room-id of the room to which chatterbox should join
 	auto_join_room: string;
-    // string that is to be prepended to the generated random usernames
+    // String that is to be prepended to the generated random usernames
     username_prefix: string;
+    // If specified, chatterbox will create a dm with this user
+    // This option takes precedence over 'auto_join_room'
+    invite_user: string;
     // Configurations for header on chatterbox (containing title, avatar, minimize button)
     header: IHeader;
     // Token needed for token-authenticated registration
diff --git a/src/viewmodels/ChatterboxViewModel.ts b/src/viewmodels/ChatterboxViewModel.ts
index afb36fea89d57864954dda75d612548503677b5c..caefff1c392b0850f35572a3b283bb0a7c469037 100644
--- a/src/viewmodels/ChatterboxViewModel.ts
+++ b/src/viewmodels/ChatterboxViewModel.ts
@@ -11,11 +11,18 @@ export class ChatterboxViewModel extends ViewModel {
         this._loginPromise = options.loginPromise;
     }
 
-    async loadRoom() {
+    async load() {
         // 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);
+        let room;
+        if (this._options.config["invite_user"]) {
+            room = await this.createRoomWithUserSpecifiedInConfig();
+        } else if(this._options.config["auto_join_room"]) {
+            room = await this.joinRoomSpecifiedInConfig();
+        }
+        else {
+            throw new Error("ConfigError: You must either specify 'invite_user' or 'auto_join_room'");
+        }
         this._roomViewModel = new RoomViewModel({
             room,
             ownUserId: this._session.userId,
@@ -28,12 +35,38 @@ export class ChatterboxViewModel extends ViewModel {
         this.emitChange("timelineViewModel");
     }
 
-    private async _joinRoom(roomId: string): Promise<any> {
-        await this._session.joinRoom(roomId);
-        // even though we've joined the room, we need to wait till the next sync to get the room
-        await this._waitForRoomFromSync(roomId);
-        return this._session.rooms.get(roomId);
+    private async createRoomWithUserSpecifiedInConfig() {
+        const roomBeingCreated = this._session.createRoom({
+            type: 1,
+            name: this._name ?? undefined,
+            topic: this._topic ?? undefined,
+            isEncrypted: false,
+            isFederationDisabled: false,
+            alias: undefined,
+            avatar: undefined,
+            invites: [this._options.config["invite_user"]],
+        });
+        await this._waitForRoomCreation(roomBeingCreated);
+        const roomId = roomBeingCreated.roomId;
+        let room = this._session.rooms.get(roomId);
+        if (!room) {
+            await this._waitForRoomFromSync(roomId);
+            room = this._session.rooms.get(roomId);
+        }
+        return room;
+    }
 
+    private async joinRoomSpecifiedInConfig() {
+        const roomId = this._options.config["auto_join_room"];
+        let room = this._session.rooms.get(roomId);
+        if (!room) {
+            // user is not in specified room, so join it
+            await this._session.joinRoom(roomId);
+            // even though we've joined the room, we need to wait till the next sync to get the room
+            await this._waitForRoomFromSync(roomId);
+            room = this._session.rooms.get(roomId); 
+        }
+        return room;
     }
 
     private _waitForRoomFromSync(roomId: string): Promise<void> {
@@ -46,11 +79,24 @@ export class ChatterboxViewModel extends ViewModel {
                     resolve();
                 }
             },
+            onUpdate: () => undefined,
+            onRemove: () => undefined,
         };
         this._session.rooms.subscribe(subscription);
         return promise;
     }
 
+    private _waitForRoomCreation(roomBeingCreated): Promise<void> {
+        let resolve: () => void;
+        const promise: Promise<void> = new Promise(r => { resolve = r; })
+        roomBeingCreated.on("change", () => {
+            if (roomBeingCreated.roomId) {
+                resolve();
+            }
+        });
+        return promise;
+    }
+
     get timelineViewModel() {
         return this._roomViewModel?.timelineViewModel;
     }
diff --git a/src/viewmodels/RootViewModel.ts b/src/viewmodels/RootViewModel.ts
index 120714830478aee8eeb1541591c4a88ae208f906..b4f5484c6fd5058fcbc1622dade8ad366c3f5412 100644
--- a/src/viewmodels/RootViewModel.ts
+++ b/src/viewmodels/RootViewModel.ts
@@ -45,7 +45,7 @@ export class RootViewModel extends ViewModel {
                     loginPromise,
                 })
             ));
-            this._chatterBoxViewModel.loadRoom();
+            this._chatterBoxViewModel.load();
         }
         this.emitChange("activeSection");
     }