diff --git a/dist/bundle.js b/dist/bundle.js
index fb3297d914302c64035d83b819a8fbe1c07cc7f2..3785a2fc7d3de9ca669519fe181a2c19ba80e8e4 100644
--- a/dist/bundle.js
+++ b/dist/bundle.js
@@ -6234,7 +6234,7 @@ eval("var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn th
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ConfigView\", function() { return ConfigView; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.js\");\n/* harmony import */ var vue_class_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vue-class-component */ \"./node_modules/vue-class-component/dist/vue-class-component.common.js\");\n/* harmony import */ var vue_class_component__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(vue_class_component__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _render__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./render */ \"./src/render.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n    var extendStatics = Object.setPrototypeOf ||\n        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n    return function (d, b) {\n        extendStatics(d, b);\n        function __() { this.constructor = d; }\n        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n    };\n})();\nvar __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n    if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n    return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n\n\n\n\nvar ConfigView = /** @class */ (function (_super) {\n    __extends(ConfigView, _super);\n    function ConfigView() {\n        var _this = _super.call(this) || this;\n        console.log(\"a new config view was placed\");\n        return _this;\n    }\n    ConfigView.prototype.create = function () {\n        Object(_render__WEBPACK_IMPORTED_MODULE_2__[\"create\"])(this.config);\n        Object(_render__WEBPACK_IMPORTED_MODULE_2__[\"render\"])();\n        this.config.created = true;\n    };\n    ConfigView.prototype.toggleTimer = function () {\n        if (this.config.started && this.intervalId !== undefined) {\n            clearInterval(this.intervalId);\n            this.config.started = false;\n        }\n        else {\n            this.intervalId = setInterval(function () {\n                var l = Object(_render__WEBPACK_IMPORTED_MODULE_2__[\"getLife\"])();\n                if (l)\n                    l.stepGame();\n                Object(_render__WEBPACK_IMPORTED_MODULE_2__[\"render\"])();\n            }, this.config.period);\n            this.config.started = true;\n        }\n    };\n    ConfigView = __decorate([\n        vue_class_component__WEBPACK_IMPORTED_MODULE_1___default()({\n            props: {\n                config: Object\n            },\n            template: \"\\n      <div>\\n        <div class=\\\"form-row align-items-center\\\">\\n          <div class=\\\"col\\\">\\n            <div class=\\\"input-group\\\">        \\n                <div class=\\\"input-group-prepend\\\">\\n                  <span class=\\\"input-group-text\\\" >Cols</span>\\n                </div>\\n                <input type=\\\"number\\\" class=\\\"form-control\\\" v-model:value=\\\"config.w\\\" />\\n            </div>  \\n          </div>\\n          <div class=\\\"col\\\">\\n            <div class=\\\"input-group\\\">        \\n                <div class=\\\"input-group-prepend\\\">\\n                  <span class=\\\"input-group-text\\\" >Rows</span>\\n                </div>\\n                <input type=\\\"number\\\" class=\\\"form-control\\\" v-model:value=\\\"config.h\\\" />\\n            </div>  \\n          </div>\\n          <div class=\\\"col\\\">\\n            <button class=\\\"btn btn-primary mb-2\\\" v-bind:disabled=\\\"config.created\\\" v-on:click=\\\"create\\\">Create</button>\\n          </div>\\n          <div class=\\\"col\\\">\\n            <div class=\\\"input-group\\\">        \\n                <div class=\\\"input-group-prepend\\\">\\n                  <span class=\\\"input-group-text\\\" >ms</span>\\n                </div>\\n                <input type=\\\"number\\\" class=\\\"form-control\\\" v-model:value=\\\"config.period\\\" />\\n            </div>  \\n          </div>\\n          <div class=\\\"col\\\">\\n            <button class=\\\"btn btn-primary mb-2\\\" v-bind:disabled=\\\"!config.created\\\" v-on:click=\\\"toggleTimer\\\">\\n            {{ config.started ? \\\"Stop\\\" : \\\"Start\\\" }}\\n            </button>\\n          </div>          \\n        </div>\\n      </div>\\n    \"\n        })\n    ], ConfigView);\n    return ConfigView;\n}(vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]));\n\n\n//# sourceURL=webpack:///./src/gameConfig.ts?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ConfigView\", function() { return ConfigView; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.js\");\n/* harmony import */ var vue_class_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vue-class-component */ \"./node_modules/vue-class-component/dist/vue-class-component.common.js\");\n/* harmony import */ var vue_class_component__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(vue_class_component__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _render__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./render */ \"./src/render.ts\");\n/* harmony import */ var _index__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./index */ \"./src/index.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n    var extendStatics = Object.setPrototypeOf ||\n        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n    return function (d, b) {\n        extendStatics(d, b);\n        function __() { this.constructor = d; }\n        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n    };\n})();\nvar __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n    if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n    return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n\n\n\n\n\nvar ConfigView = /** @class */ (function (_super) {\n    __extends(ConfigView, _super);\n    function ConfigView() {\n        var _this = _super.call(this) || this;\n        console.log(\"a new config view was placed\");\n        return _this;\n    }\n    ConfigView.prototype.create = function () {\n        Object(_index__WEBPACK_IMPORTED_MODULE_3__[\"create\"])(this.config);\n        this.config.created = true;\n    };\n    ConfigView.prototype.toggleTimer = function () {\n        if (this.config.started && this.intervalId !== undefined) {\n            clearInterval(this.intervalId);\n            this.config.started = false;\n        }\n        else {\n            this.intervalId = setInterval(function () {\n                var l = Object(_render__WEBPACK_IMPORTED_MODULE_2__[\"getLife\"])();\n                if (l)\n                    l.stepGame();\n                Object(_render__WEBPACK_IMPORTED_MODULE_2__[\"render\"])();\n            }, this.config.period);\n            this.config.started = true;\n        }\n    };\n    ConfigView = __decorate([\n        vue_class_component__WEBPACK_IMPORTED_MODULE_1___default()({\n            props: {\n                config: Object\n            },\n            template: \"\\n      <div>\\n        <div class=\\\"form-row align-items-center\\\">\\n          <div class=\\\"col\\\">\\n            <div class=\\\"input-group\\\">        \\n                <div class=\\\"input-group-prepend\\\">\\n                  <span class=\\\"input-group-text\\\" >Cols</span>\\n                </div>\\n                <input type=\\\"number\\\" class=\\\"form-control\\\" v-model:value=\\\"config.w\\\" />\\n            </div>  \\n          </div>\\n          <div class=\\\"col\\\">\\n            <div class=\\\"input-group\\\">        \\n                <div class=\\\"input-group-prepend\\\">\\n                  <span class=\\\"input-group-text\\\" >Rows</span>\\n                </div>\\n                <input type=\\\"number\\\" class=\\\"form-control\\\" v-model:value=\\\"config.h\\\" />\\n            </div>  \\n          </div>\\n          <div class=\\\"col\\\">\\n            <button class=\\\"btn btn-primary mb-2\\\" v-bind:disabled=\\\"config.created\\\" v-on:click=\\\"create\\\">Create</button>\\n          </div>\\n          <div class=\\\"col\\\">\\n            <div class=\\\"input-group\\\">        \\n                <div class=\\\"input-group-prepend\\\">\\n                  <span class=\\\"input-group-text\\\" >ms</span>\\n                </div>\\n                <input type=\\\"number\\\" class=\\\"form-control\\\" v-model:value=\\\"config.period\\\" />\\n            </div>  \\n          </div>\\n          <div class=\\\"col\\\">\\n            <button class=\\\"btn btn-primary mb-2\\\" v-bind:disabled=\\\"!config.created\\\" v-on:click=\\\"toggleTimer\\\">\\n            {{ config.started ? \\\"Stop\\\" : \\\"Start\\\" }}\\n            </button>\\n          </div>          \\n        </div>\\n      </div>\\n    \"\n        })\n    ], ConfigView);\n    return ConfigView;\n}(vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]));\n\n\n//# sourceURL=webpack:///./src/gameConfig.ts?");
 
 /***/ }),
 
@@ -6246,7 +6246,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
-eval("__webpack_require__.r(__webpack_exports__);\nvar Life = /** @class */ (function () {\n    function Life(w, h) {\n        if (w === void 0) { w = 40; }\n        if (h === void 0) { h = 20; }\n        this.w = w;\n        this.h = h;\n        this.board = this.emptyBoard();\n    }\n    Life.prototype.boardIndex = function (x, y) {\n        return y * this.w + x;\n    };\n    Life.prototype.x = function (index) {\n        return index % this.w;\n    };\n    Life.prototype.y = function (index) {\n        return Math.floor(index / this.w);\n    };\n    Life.prototype.emptyBoard = function () {\n        var arr = [];\n        for (var i = 0; i < this.h * this.w; i++) {\n            arr.push(0);\n        }\n        return arr;\n    };\n    /**\n     *  If the cell is dead, set it to p, otherwise set it to zero\n     */\n    Life.prototype.toggleCell = function (x, y, p) {\n        var b = this.boardIndex(x, y);\n        if (this.isAlive(x, y)) {\n            this.board[b] = 0;\n        }\n        else {\n            this.board[b] = p;\n        }\n    };\n    /**\n     * Returns 1 if blue, -1 if red, 0 if dead\n     */\n    Life.prototype.isAlive = function (x, y) {\n        var b = this.boardIndex(x, y);\n        if ((x >= 0) && (y >= 0) && (x < this.w) && (y < this.h)) {\n            return this.board[b];\n        }\n        else {\n            return 0;\n        }\n    };\n    Life.prototype.blueNeighbours = function (x, y) {\n        var live = 0;\n        for (var _i = 0, _a = [x - 1, x, x + 1]; _i < _a.length; _i++) {\n            var i = _a[_i];\n            for (var _b = 0, _c = [y - 1, y, y + 1]; _b < _c.length; _b++) {\n                var j = _c[_b];\n                if (this.isAlive(i, j) > 0 && (i != x || j != y)) {\n                    live++;\n                }\n            }\n        }\n        return live;\n    };\n    Life.prototype.redNeighbours = function (x, y) {\n        var live = 0;\n        for (var _i = 0, _a = [x - 1, x, x + 1]; _i < _a.length; _i++) {\n            var i = _a[_i];\n            for (var _b = 0, _c = [y - 1, y, y + 1]; _b < _c.length; _b++) {\n                var j = _c[_b];\n                if (this.isAlive(i, j) < 0 && (i != x || j != y)) {\n                    live++;\n                }\n            }\n        }\n        return live;\n    };\n    /**\n     * Performs the game rule for what the next state of a cell should be\n     */\n    Life.nextCellState = function (state, redNeighbours, blueNeighbours) {\n        var neighbours = redNeighbours + blueNeighbours;\n        if (state == 0) {\n            if (neighbours == 3) {\n                if (redNeighbours > blueNeighbours) {\n                    return -1;\n                }\n                else {\n                    return 0;\n                }\n            }\n            else {\n                return state;\n            }\n        }\n        else {\n            if (neighbours == 2 || neighbours == 3) {\n                return state;\n            }\n            else {\n                return 0;\n            }\n        }\n    };\n    Life.prototype.stepGame = function () {\n        var nextBoard = this.emptyBoard();\n        for (var x = 0; x < this.w; x++) {\n            for (var y = 0; y < this.h; y++) {\n                var index = this.boardIndex(x, y);\n                var alive = this.isAlive(x, y);\n                var redNeighbours = this.redNeighbours(x, y);\n                var blueNeighbours = this.blueNeighbours(x, y);\n                nextBoard[this.boardIndex(x, y)] = Life.nextCellState(alive, redNeighbours, blueNeighbours);\n            }\n        }\n        this.board = nextBoard;\n    };\n    return Life;\n}());\n/* harmony default export */ __webpack_exports__[\"default\"] = (Life);\n\n\n//# sourceURL=webpack:///./src/gameOfLife.ts?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./index */ \"./src/index.ts\");\n\nvar Life = /** @class */ (function () {\n    function Life(w, h) {\n        if (w === void 0) { w = 40; }\n        if (h === void 0) { h = 20; }\n        this.w = w;\n        this.h = h;\n        this.board = this.emptyBoard();\n    }\n    Life.prototype.boardIndex = function (x, y) {\n        return y * this.w + x;\n    };\n    Life.prototype.x = function (index) {\n        return index % this.w;\n    };\n    Life.prototype.y = function (index) {\n        return Math.floor(index / this.w);\n    };\n    Life.prototype.emptyBoard = function () {\n        var arr = [];\n        for (var i = 0; i < this.h * this.w; i++) {\n            arr.push(0);\n        }\n        return arr;\n    };\n    /**\n     *  If the cell is dead, set it to p, otherwise set it to zero\n     */\n    Life.prototype.toggleCell = function (x, y, p) {\n        var b = this.boardIndex(x, y);\n        if (this.isAlive(x, y)) {\n            this.board[b] = 0;\n        }\n        else {\n            this.board[b] = p;\n        }\n    };\n    /**\n     * Returns 1 if blue, -1 if red, 0 if dead\n     */\n    Life.prototype.isAlive = function (x, y) {\n        var b = this.boardIndex(x, y);\n        if ((x >= 0) && (y >= 0) && (x < this.w) && (y < this.h)) {\n            return this.board[b];\n        }\n        else {\n            return 0;\n        }\n    };\n    Life.prototype.blueNeighbours = function (x, y) {\n        var live = 0;\n        for (var _i = 0, _a = [x - 1, x, x + 1]; _i < _a.length; _i++) {\n            var i = _a[_i];\n            for (var _b = 0, _c = [y - 1, y, y + 1]; _b < _c.length; _b++) {\n                var j = _c[_b];\n                if (this.isAlive(i, j) > 0 && (i != x || j != y)) {\n                    live++;\n                }\n            }\n        }\n        return live;\n    };\n    Life.prototype.redNeighbours = function (x, y) {\n        var live = 0;\n        for (var _i = 0, _a = [x - 1, x, x + 1]; _i < _a.length; _i++) {\n            var i = _a[_i];\n            for (var _b = 0, _c = [y - 1, y, y + 1]; _b < _c.length; _b++) {\n                var j = _c[_b];\n                if (this.isAlive(i, j) < 0 && (i != x || j != y)) {\n                    live++;\n                }\n            }\n        }\n        return live;\n    };\n    /**\n     * Performs the game rule for what the next state of a cell should be\n     */\n    Life.nextCellState = function (state, redNeighbours, blueNeighbours) {\n        var neighbours = redNeighbours + blueNeighbours;\n        if (state == 0) {\n            if (neighbours == 3) {\n                if (redNeighbours > blueNeighbours) {\n                    return -1;\n                }\n                else {\n                    return 0;\n                }\n            }\n            else {\n                return state;\n            }\n        }\n        else {\n            if (neighbours == 2 || neighbours == 3) {\n                return state;\n            }\n            else {\n                return 0;\n            }\n        }\n    };\n    Life.prototype.stepGame = function () {\n        var nextBoard = this.emptyBoard();\n        for (var x = 0; x < this.w; x++) {\n            for (var y = 0; y < this.h; y++) {\n                var index = this.boardIndex(x, y);\n                var alive = this.isAlive(x, y);\n                var redNeighbours = this.redNeighbours(x, y);\n                var blueNeighbours = this.blueNeighbours(x, y);\n                nextBoard[this.boardIndex(x, y)] = Life.nextCellState(alive, redNeighbours, blueNeighbours);\n            }\n        }\n        this.board = nextBoard;\n    };\n    Life.jsStartGame = function (w, h) {\n        return {\n            kind: \"startGame\", w: w, h: h\n        };\n    };\n    Life.jsConnected = function () {\n        return { kind: \"connected\" };\n    };\n    Life.jsGameState = function (w, h, board) {\n        return {\n            kind: \"gameState\", w: w, h: h, board: board\n        };\n    };\n    Life.jsPlayerNumber = function (p) {\n        return {\n            kind: \"playerNumber\", p: p\n        };\n    };\n    Life.jsToggle = function (x, y, p) {\n        return {\n            kind: \"toggle\", x: x, y: y, p: p\n        };\n    };\n    Life.handleMessage = function (message) {\n        switch (message.kind) {\n            case \"startGame\":\n                var g = new Life(message.w, message.h);\n                var msg = Life.jsGameState(g.w, g.h, g.board);\n                Object(_index__WEBPACK_IMPORTED_MODULE_0__[\"sendMessage\"])(msg);\n                break;\n            case \"gameState\":\n                if (Life.game !== undefined && Life.game.w == message.w && Life.game.h == message.h) {\n                    Life.game.board = message.board;\n                    // TODO: re-render the board\n                }\n                else {\n                    Life.game = new Life(message.w, message.h);\n                    Life.game.board = message.board;\n                }\n                break;\n            case \"playerNumber\":\n                if (Life.player === undefined) {\n                    Life.player = -message.p;\n                    // TODO: send back my player number\n                }\n                else {\n                    // do nothing, the other player is just telling me their number, but I've got mine\n                }\n                break;\n            case \"toggle\":\n                if (Life.game !== undefined) {\n                    Life.game.toggleCell(message.x, message.y, message.p);\n                    // TODO: broadcast the new game-state?\n                }\n        }\n    };\n    Life.game = undefined;\n    Life.player = undefined;\n    return Life;\n}());\n/* harmony default export */ __webpack_exports__[\"default\"] = (Life);\n\n\n//# sourceURL=webpack:///./src/gameOfLife.ts?");
 
 /***/ }),
 
@@ -6254,11 +6254,11 @@ eval("__webpack_require__.r(__webpack_exports__);\nvar Life = /** @class */ (fun
 /*!**********************!*\
   !*** ./src/index.ts ***!
   \**********************/
-/*! no exports provided */
+/*! exports provided: sendMessage, create */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.js\");\n/* harmony import */ var _render__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./render */ \"./src/render.ts\");\n/* harmony import */ var _gameConfig__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./gameConfig */ \"./src/gameConfig.ts\");\n\n\n\n//\nvar gameId = (new URL(document.location.toString())).searchParams.get(\"gameId\");\nfunction getGame(gameId) {\n    fetch(\"/life/getGame?gameId=\" + gameId)\n        .then(function (data) { return data.json(); })\n        .then(function (arr) {\n        /*\n             {\n               player: 1\n               board: [.....]\n              }\n         */\n    });\n}\nfunction openSocket(gameId) {\n    var wsUrl = \"ws\" + window.location.origin.slice(4) + \"/life/gameSocket?gameId=\" + gameId;\n    var ws = new WebSocket(wsUrl);\n    ws.onmessage = function (evt) { console.log(evt); };\n    ws.onopen = function (evt) { ws.send(\"Connected, this message is from the client\"); };\n}\nif (gameId != null) {\n    openSocket(gameId);\n}\nelse {\n    console.log(\"We had no game Id\");\n}\n/**\n * This is (for now) going to trigger getting everything set up\n */\nif (gameId !== null) {\n    getGame(gameId);\n}\nvar config = {\n    w: 40,\n    h: 20,\n    started: false,\n    created: false,\n    period: 500\n};\nvar v = new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]({\n    el: \"#app\",\n    template: \"\\n      <div>\\n        <ConfigView :config=\\\"config\\\"></ConfigView>    \\n      </div>\\n    \",\n    data: {\n        config: config\n    },\n    components: {\n        ConfigView: _gameConfig__WEBPACK_IMPORTED_MODULE_2__[\"ConfigView\"]\n    }\n});\nconsole.log(\"loaded vue\");\nconsole.log(v);\ndocument.getElementById(\"step\").addEventListener(\"click\", function () {\n    var l = Object(_render__WEBPACK_IMPORTED_MODULE_1__[\"getLife\"])();\n    if (l)\n        l.stepGame();\n    Object(_render__WEBPACK_IMPORTED_MODULE_1__[\"render\"])();\n});\n\n\n//# sourceURL=webpack:///./src/index.ts?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sendMessage\", function() { return sendMessage; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"create\", function() { return create; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.js\");\n/* harmony import */ var _render__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./render */ \"./src/render.ts\");\n/* harmony import */ var _gameConfig__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./gameConfig */ \"./src/gameConfig.ts\");\n/* harmony import */ var _gameOfLife__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./gameOfLife */ \"./src/gameOfLife.ts\");\n\n\n\n\n//\nvar gameId = (new URL(document.location.toString())).searchParams.get(\"gameId\");\nvar ws = undefined;\nfunction getGame(gameId) {\n    fetch(\"/life/getGame?gameId=\" + gameId)\n        .then(function (data) { return data.json(); })\n        .then(function (arr) {\n        /*\n             {\n               player: 1\n               board: [.....]\n              }\n         */\n    });\n}\nfunction openSocket(gameId) {\n    var wsUrl = \"ws\" + window.location.origin.slice(4) + \"/life/gameSocket?gameId=\" + gameId;\n    ws = new WebSocket(wsUrl);\n    ws.onmessage = function (evt) {\n        console.log(evt);\n        _gameOfLife__WEBPACK_IMPORTED_MODULE_3__[\"default\"].handleMessage(JSON.parse(evt.data));\n        if (_gameOfLife__WEBPACK_IMPORTED_MODULE_3__[\"default\"].game !== undefined) {\n            Object(_render__WEBPACK_IMPORTED_MODULE_1__[\"render\"])();\n        }\n    };\n    ws.onopen = function (evt) { ws.send(\"Connected, this message is from the client\"); };\n    ws.onclose = function (evt) { openSocket(gameId); };\n}\nfunction sendMessage(msg) {\n    console.log(\"sending \" + msg);\n    if (ws !== undefined) {\n        ws.send(JSON.stringify(msg));\n    }\n}\nif (gameId != null) {\n    openSocket(gameId);\n}\nelse {\n    console.log(\"We had no game Id\");\n}\n/**\n * This is (for now) going to trigger getting everything set up\n */\nif (gameId !== null) {\n    getGame(gameId);\n}\nvar config = {\n    w: 40,\n    h: 20,\n    started: false,\n    created: false,\n    period: 500\n};\nfunction create(config) {\n    console.log(\"create!\");\n    sendMessage(_gameOfLife__WEBPACK_IMPORTED_MODULE_3__[\"default\"].jsStartGame(config.w, config.h));\n}\nvar v = new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]({\n    el: \"#app\",\n    template: \"\\n      <div>\\n        <ConfigView :config=\\\"config\\\"></ConfigView>    \\n      </div>\\n    \",\n    data: {\n        config: config\n    },\n    components: {\n        ConfigView: _gameConfig__WEBPACK_IMPORTED_MODULE_2__[\"ConfigView\"]\n    }\n});\nconsole.log(\"loaded vue\");\nconsole.log(v);\ndocument.getElementById(\"step\").addEventListener(\"click\", function () {\n    var l = Object(_render__WEBPACK_IMPORTED_MODULE_1__[\"getLife\"])();\n    if (l)\n        l.stepGame();\n    Object(_render__WEBPACK_IMPORTED_MODULE_1__[\"render\"])();\n});\n\n\n//# sourceURL=webpack:///./src/index.ts?");
 
 /***/ }),
 
@@ -6266,11 +6266,11 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue_
 /*!***********************!*\
   !*** ./src/render.ts ***!
   \***********************/
-/*! exports provided: getLife, create, render */
+/*! exports provided: getLife, render */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getLife\", function() { return getLife; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"create\", function() { return create; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony import */ var _gameOfLife__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./gameOfLife */ \"./src/gameOfLife.ts\");\n/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! d3 */ \"./node_modules/d3/index.js\");\n\n\nvar foo = \"bar\";\nvar life = new _gameOfLife__WEBPACK_IMPORTED_MODULE_0__[\"default\"](0, 0);\nfunction create(config) {\n    console.log(config.w);\n    life = new _gameOfLife__WEBPACK_IMPORTED_MODULE_0__[\"default\"](config.w, config.h);\n    render();\n}\nvar game = d3__WEBPACK_IMPORTED_MODULE_1__[\"select\"](\"#game\").append(\"g\");\nvar cellSize = 20;\n\nfunction getLife() {\n    return life;\n}\n// TODO: Update this depending on which player we are\nvar player = -1;\nfunction render() {\n    console.log(\"rendering\");\n    var update = game.selectAll(\"rect\").data(life.board);\n    update.attr(\"class\", function (d) {\n        if (d == 0) {\n            return \"cell\";\n        }\n        else if (d > 0) {\n            return \"cell alive blue\";\n        }\n        else {\n            return \"cell alive red\";\n        }\n    });\n    update.enter()\n        .append(\"rect\")\n        .attr(\"class\", function (d) {\n        return d ? \"cell alive\" : \"cell\";\n    })\n        .attr(\"x\", function (val, i) {\n        return life.x(i) * cellSize;\n    })\n        .attr(\"y\", function (val, i) {\n        return life.y(i) * cellSize;\n    })\n        .attr(\"width\", cellSize)\n        .attr(\"height\", cellSize)\n        .on(\"click\", function (d, i) {\n        var x = life.x(i);\n        var y = life.y(i);\n        life.toggleCell(x, y, player);\n        render();\n    });\n}\n\n\n//# sourceURL=webpack:///./src/render.ts?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getLife\", function() { return getLife; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony import */ var _gameOfLife__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./gameOfLife */ \"./src/gameOfLife.ts\");\n/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! d3 */ \"./node_modules/d3/index.js\");\n\n\nvar foo = \"bar\";\nvar game = d3__WEBPACK_IMPORTED_MODULE_1__[\"select\"](\"#game\").append(\"g\");\nvar cellSize = 20;\n\nfunction getLife() {\n    return _gameOfLife__WEBPACK_IMPORTED_MODULE_0__[\"default\"].game;\n}\n// TODO: Update this depending on which player we are\nvar player = -1;\nfunction render() {\n    console.log(\"rendering\");\n    var life = _gameOfLife__WEBPACK_IMPORTED_MODULE_0__[\"default\"].game;\n    var update = game.selectAll(\"rect\").data(life.board);\n    update.attr(\"class\", function (d) {\n        if (d == 0) {\n            return \"cell\";\n        }\n        else if (d > 0) {\n            return \"cell alive blue\";\n        }\n        else {\n            return \"cell alive red\";\n        }\n    });\n    update.enter()\n        .append(\"rect\")\n        .attr(\"class\", function (d) {\n        return d ? \"cell alive\" : \"cell\";\n    })\n        .attr(\"x\", function (val, i) {\n        return life.x(i) * cellSize;\n    })\n        .attr(\"y\", function (val, i) {\n        return life.y(i) * cellSize;\n    })\n        .attr(\"width\", cellSize)\n        .attr(\"height\", cellSize)\n        .on(\"click\", function (d, i) {\n        var x = life.x(i);\n        var y = life.y(i);\n        life.toggleCell(x, y, player);\n        render();\n    });\n}\n\n\n//# sourceURL=webpack:///./src/render.ts?");
 
 /***/ })
 
diff --git a/src/gameConfig.ts b/src/gameConfig.ts
index 03456ec0574ad4c063f35db9e20c4e70408dabe5..96e28b052aeaac1be5d524ced4263f3f830e779e 100644
--- a/src/gameConfig.ts
+++ b/src/gameConfig.ts
@@ -1,6 +1,8 @@
 import Vue from "vue"
 import Component from 'vue-class-component'
-import { create, render, getLife } from './render'
+import { render, getLife } from './render'
+
+import { create } from "./index"
 
 export { 
     GameConfig as GameConfig,
@@ -69,7 +71,6 @@ class ConfigView extends Vue {
 
     create() {
         create(this.config!)
-        render()
         this.config!.created = true
     }
 
diff --git a/src/gameOfLife.ts b/src/gameOfLife.ts
index c7d912b3d1f4d7701dd0f52c440c8d0e57a08190..330cff52308fecb2ca909b7b389b6b75dd6aa7af 100644
--- a/src/gameOfLife.ts
+++ b/src/gameOfLife.ts
@@ -1,4 +1,6 @@
 
+import { sendMessage } from "./index"
+
 export default class Life {
 
     board: Array<number>
@@ -117,6 +119,78 @@ export default class Life {
         this.board = nextBoard
     }
 
+    static jsStartGame(w:number, h:number):any {
+        return {
+            kind:"startGame", w:w, h:h
+        }
+    }
+
+    static jsConnected():any {
+        return { kind: "connected" }
+    }
+
+    static jsGameState(w:number, h:number, board:Array<number>):any {
+        return {
+            kind:"gameState", w:w, h:h, board:board
+        }
+    }
+
+    static jsPlayerNumber(p:number):any {
+        return {
+            kind:"playerNumber", p:p
+        }
+    }
+
+    static jsToggle(x:number, y:number, p:number):any {
+        return {
+            kind:"toggle", x:x, y:y, p:p
+        }
+    }
+
+    static game: Life | undefined = undefined;
+
+    static player: number | undefined = undefined;
+
+    static handleMessage(message:any) {
+        switch (message.kind) {
+            case "startGame":
+                let g = new Life(message.w, message.h);
+                let msg = Life.jsGameState(g.w, g.h, g.board);
+                sendMessage(msg);
+
+                break;
+
+            case "gameState":
+                if (Life.game !== undefined && Life.game.w == message.w && Life.game.h == message.h) {
+                    Life.game.board = message.board
+                    // TODO: re-render the board
+                } else {
+                    Life.game = new Life(message.w, message.h)
+                    Life.game.board = message.board
+                }
+
+                break;
+
+            case "playerNumber":
+                if (Life.player === undefined) {
+                    Life.player = -message.p
+                    // TODO: send back my player number
+                } else {
+                    // do nothing, the other player is just telling me their number, but I've got mine
+                }
+
+                break;
+
+            case "toggle":
+                if (Life.game !== undefined) {
+                    Life.game.toggleCell(message.x, message.y, message.p)
+                    // TODO: broadcast the new game-state?
+                }
+        }
+
+
+    }
+
 }
 
 
diff --git a/src/index.ts b/src/index.ts
index b87d984d30a0bb86e7af1cc52222c2a3ad0c704f..ac3bb5b5ad631db6c92b63e33f4049f5beaca0cb 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,10 +1,12 @@
 import Vue from "vue";
 import { render, getLife } from "./render"
 import { ConfigView, GameConfig } from "./gameConfig"
-
+import Life from "./gameOfLife";
 
 //
 let gameId = (new URL(document.location.toString())).searchParams.get("gameId");
+let ws: WebSocket | undefined = undefined;
+
 
 function getGame(gameId:string) {
     fetch("/life/getGame?gameId=" + gameId)
@@ -21,11 +23,27 @@ function getGame(gameId:string) {
 
 function openSocket(gameId:string) {
     let wsUrl = "ws" + window.location.origin.slice(4) + "/life/gameSocket?gameId=" + gameId
-    let ws = new WebSocket(wsUrl)
-    ws.onmessage = (evt) => { console.log(evt) }
-    ws.onopen = (evt) => { ws.send("Connected, this message is from the client") }
+    ws = new WebSocket(wsUrl)
+    ws.onmessage = (evt) => {
+        console.log(evt)
+        Life.handleMessage(JSON.parse(evt.data))
+        if (Life.game !== undefined) {
+            render()
+        }
+    }
+    ws.onopen = (evt) => { ws!.send("Connected, this message is from the client") }
+    ws.onclose = (evt) => { openSocket(gameId) }
+}
+
+
+export function sendMessage(msg:any) {
+    console.log("sending " + msg)
+    if (ws !== undefined) {
+        ws.send(JSON.stringify(msg))
+    }
 }
 
+
 if (gameId != null) {
     openSocket(gameId)
 } else {
@@ -48,6 +66,11 @@ let config:GameConfig = {
     period: 500
 }
 
+export function create(config:GameConfig) {
+    console.log("create!")
+    sendMessage(Life.jsStartGame(config.w, config.h))
+}
+
 let v = new Vue({
     el: "#app",
     template: `
diff --git a/src/render.ts b/src/render.ts
index cad4d5f8812c812d3f9137e6f82116d165d0ede2..01dd1ed2a7439b7f94818d02653f9a2cf881b5ca 100644
--- a/src/render.ts
+++ b/src/render.ts
@@ -4,25 +4,16 @@ import * as d3 from "d3"
 
 let foo = "bar"
 
-let life:Life = new Life(0,0)
-
-function create(config:GameConfig) {
-    console.log(config.w)
-    life = new Life(config.w, config.h)
-    render()
-}
-
 const game = d3.select("#game").append("g")
 const cellSize = 20
 
 export {
     getLife as getLife,
-    create as create,
     render as render
 }
 
 function getLife() {
-    return life
+    return Life.game
 }
 
 // TODO: Update this depending on which player we are
@@ -30,6 +21,8 @@ let player = -1;
 
 function render() {
     console.log("rendering")
+
+    let life = Life.game!
     
     let update = game.selectAll("rect").data(life.board)