diff --git a/app.js b/app.js
index 8514f46d6d72bf2d3e3c94269bac0622c7c2608a..7674a025f9b79d2d841ce0d30d975a6b6268a9f4 100644
--- a/app.js
+++ b/app.js
@@ -10,12 +10,24 @@ webserver.get("/", (_, res) => {
 });
 
 webserver.get("/public_games", (_, res) => {
-  let ids = Object.keys(games);
+  let ids = sockServer.getGameIds();
   res.json({ ids: ids });
 });
 
-webserver.get("/join_game/:gameId", (req, res) => {
-  let { gameId } = req.params;
+webserver.get("/join_game/:gameId/:gameType", (req, res) => {
+  let { gameId, gameType } = req.params;
+  if (gameType === "private") {
+    if (!sockServer.hasGame(gameId)) {
+      sockServer.createGame(gameId, gameType);
+    } else {
+      console.log("Game already exists");
+      if (sockServer.games[gameId].type === "public") {
+        // TODO: THIS IS A HACK
+        return res.sendFile("public/index.html", { root: __dirname });
+      }
+    }
+    return res.sendFile("public/game.html", { root: __dirname });
+  }
   if (!sockServer.hasGame(gameId)) {
     return res.status(404).send();
   }
diff --git a/public/gameClient.js b/public/gameClient.js
index e8060c75318cc29bb86b5b5830812697e148135e..2f37c9492da3ed383aa303c638ba68281a587536 100644
--- a/public/gameClient.js
+++ b/public/gameClient.js
@@ -1,5 +1,5 @@
 let pathParts = window.location.pathname.split("/");
-let roomId = pathParts[pathParts.length - 1];
+let roomId = pathParts[pathParts.length - 2];
 
 const joinMessage = { type: "join", data: `${roomId}`, pid: 0 };
 let moveMessage = { type: "move", data: "up", pid: 0 };
diff --git a/public/index.html b/public/index.html
index 155b83b9fce20a8d6e729e89260099022a1926dd..44ee57eecb223edf4f42ae1f39af091862509668 100644
--- a/public/index.html
+++ b/public/index.html
@@ -75,7 +75,16 @@
           aria-labelledby="headingTwo"
           data-parent="#accordion"
         >
-          <div class="card-body">Test2</div>
+          <div class="card-body">
+            <input type="text" id="gameId" placeholder="Game ID" />
+            <button
+              id="privButton"
+              class="btn btn-primary"
+              onclick="window.location = `/join_game/${document.getElementById('gameId').value}/private`"
+            >
+              Join Game
+            </button>
+          </div>
         </div>
       </div>
     </div>
@@ -87,6 +96,12 @@
 
       publicBody.textContent = "Loading...";
 
+      let privButton = document.getElementById("privButton");
+      privButton.addEventListener("click", () => {
+        console.log("Joining game " + document.getElementById("gameId").value);
+        window.location = `/join_game/${document.getElementById("gameId").value}/private`;
+      });
+
       fetch("/public_games")
         .then((response) => {
           return response.json();
@@ -103,7 +118,7 @@
             button.addEventListener("click", () => {
               // will redirect to new chatroom immediately
               console.log("Joining game " + data.ids[i]);
-              window.location = `/join_game/${data.ids[i]}`;
+              window.location = `/join_game/${data.ids[i]}/public`;
             });
             publicBody.appendChild(button);
           }
diff --git a/src/models/WebSocketModel.js b/src/models/WebSocketModel.js
index 7408c97f53695e2514432d2c7b6997a2f0868ce1..348144b15315e2c7307b30f214f5130452b81c31 100644
--- a/src/models/WebSocketModel.js
+++ b/src/models/WebSocketModel.js
@@ -8,18 +8,21 @@ class WebSocketModel {
     this.games["game1"] = {
       gameBoard: gameModule.createGameBoard(10, 10),
       players: [],
+      type: "public",
       started: false,
       readyPlayers: 0,
     };
     this.games["game2"] = {
       gameBoard: gameModule.createGameBoard(10, 10),
       players: [],
+      type: "public",
       started: false,
       readyPlayers: 0,
     };
     this.games["game3"] = {
       gameBoard: gameModule.createGameBoard(10, 10),
       players: [],
+      type: "public",
       started: false,
       readyPlayers: 0,
     };
@@ -50,6 +53,24 @@ class WebSocketModel {
     return this.games.hasOwnProperty(gameId);
   }
 
+  getGameIds() {
+    let publicGames = [];
+    publicGames = Object.keys(this.games).filter(
+      (game) => this.games[game].type === "public",
+    );
+    return publicGames;
+  }
+
+  createGame(gameId, gameType) {
+    this.games[gameId] = {
+      gameBoard: gameModule.createGameBoard(10, 10),
+      players: [],
+      type: gameType,
+      started: false,
+      readyPlayers: 0,
+    };
+  }
+
   moveHandler(connection, message) {
     console.log("Received move: " + message.data);
     let movement = message.data;
@@ -91,11 +112,15 @@ class WebSocketModel {
 
       let roomId = connection.protocol;
 
-      this.games[roomId].players.push(connection);
-      this.games[roomId].gameBoard = gameModule.addPlayer(
-        this.games[roomId].gameBoard,
-        this.games[roomId].players.length,
-      );
+      if (!this.games[roomId].started) {
+        this.games[roomId].players.push(connection);
+        this.games[roomId].gameBoard = gameModule.addPlayer(
+          this.games[roomId].gameBoard,
+          this.games[roomId].players.length,
+        );
+      } else {
+        this.games[roomId].players.push(connection);
+      }
 
       connection.send(
         JSON.stringify({