diff --git a/skins/base/css/molecules/voip/CallView.css b/skins/base/css/molecules/voip/CallView.css
new file mode 100644
index 00000000..01cdb45a
--- /dev/null
+++ b/skins/base/css/molecules/voip/CallView.css
@@ -0,0 +1,15 @@
+/*
+Copyright 2015 OpenMarket Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
\ No newline at end of file
diff --git a/skins/base/css/molecules/voip/IncomingCallbox.css b/skins/base/css/molecules/voip/IncomingCallbox.css
new file mode 100644
index 00000000..fd88ee27
--- /dev/null
+++ b/skins/base/css/molecules/voip/IncomingCallbox.css
@@ -0,0 +1,15 @@
+/*
+Copyright 2015 OpenMarket Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
diff --git a/skins/base/css/molecules/voip/VideoView.css b/skins/base/css/molecules/voip/VideoView.css
new file mode 100644
index 00000000..fd88ee27
--- /dev/null
+++ b/skins/base/css/molecules/voip/VideoView.css
@@ -0,0 +1,15 @@
+/*
+Copyright 2015 OpenMarket Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
diff --git a/skins/base/views/organisms/MemberList.js b/skins/base/views/organisms/MemberList.js
index eed695cf..590ebb55 100644
--- a/skins/base/views/organisms/MemberList.js
+++ b/skins/base/views/organisms/MemberList.js
@@ -30,9 +30,9 @@ module.exports = React.createClass({
     mixins: [MemberListController],
 
     makeMemberTiles: function() {
-        var that = this;
-        return Object.keys(that.state.memberDict).map(function(userId) {
-            var m = that.state.memberDict[userId];
+        var self = this;
+        return Object.keys(self.state.memberDict).map(function(userId) {
+            var m = self.state.memberDict[userId];
             return (
                 <MemberTile key={userId} member={m} />
             );
diff --git a/src/controllers/atoms/EnableNotificationsButton.js b/src/controllers/atoms/EnableNotificationsButton.js
index c600f330..fc285806 100644
--- a/src/controllers/atoms/EnableNotificationsButton.js
+++ b/src/controllers/atoms/EnableNotificationsButton.js
@@ -43,9 +43,9 @@ module.exports = {
 
     enable: function() {
         if (!this.havePermission()) {
-            var that = this;
+            var self = this;
             global.Notification.requestPermission(function() {
-                that.forceUpdate();
+                self.forceUpdate();
             });
         }
 
diff --git a/src/controllers/organisms/MemberList.js b/src/controllers/organisms/MemberList.js
index 1213db9b..fb5c0028 100644
--- a/src/controllers/organisms/MemberList.js
+++ b/src/controllers/organisms/MemberList.js
@@ -41,11 +41,11 @@ module.exports = {
     },
 
     componentDidMount: function() {
-        var that = this;
+        var self = this;
         setTimeout(function() {
-            if (!that.isMounted()) return;
-            that.setState({
-                memberDict: that.roomMembers()
+            if (!self.isMounted()) return;
+            self.setState({
+                memberDict: self.roomMembers()
             });
         }, 50);
     },
diff --git a/src/controllers/organisms/RoomList.js b/src/controllers/organisms/RoomList.js
index 03e18547..4adeaf2e 100644
--- a/src/controllers/organisms/RoomList.js
+++ b/src/controllers/organisms/RoomList.js
@@ -100,16 +100,16 @@ module.exports = {
     },
 
     makeRoomTiles: function() {
-        var that = this;
+        var self = this;
         return this.state.roomList.map(function(room) {
-            var selected = room.roomId == that.props.selectedRoom;
+            var selected = room.roomId == self.props.selectedRoom;
             return (
                 <RoomTile
                     room={room}
                     key={room.roomId}
                     selected={selected}
-                    unread={that.state.activityMap[room.roomId] === 1}
-                    highlight={that.state.activityMap[room.roomId] === 2}
+                    unread={self.state.activityMap[room.roomId] === 1}
+                    highlight={self.state.activityMap[room.roomId] === 2}
                 />
             );
         });
diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js
index 4ab239d9..f73b5c8f 100644
--- a/src/controllers/organisms/RoomView.js
+++ b/src/controllers/organisms/RoomView.js
@@ -163,12 +163,12 @@ module.exports = {
                 this.waiting_for_paginate = true;
                 var cap = this.state.messageCap + PAGINATE_SIZE;
                 this.setState({messageCap: cap, paginating: true});
-                var that = this;
+                var self = this;
                 MatrixClientPeg.get().scrollback(this.state.room, PAGINATE_SIZE).finally(function() {
-                    that.waiting_for_paginate = false;
-                    if (that.isMounted()) {
-                        that.setState({
-                            room: MatrixClientPeg.get().getRoom(that.props.roomId)
+                    self.waiting_for_paginate = false;
+                    if (self.isMounted()) {
+                        self.setState({
+                            room: MatrixClientPeg.get().getRoom(self.props.roomId)
                         });
                     }
                     // wait and set paginating to false when the component updates
@@ -181,14 +181,14 @@ module.exports = {
     },
 
     onJoinButtonClicked: function(ev) {
-        var that = this;
+        var self = this;
         MatrixClientPeg.get().joinRoom(this.props.roomId).then(function() {
-            that.setState({
+            self.setState({
                 joining: false,
-                room: MatrixClientPeg.get().getRoom(that.props.roomId)
+                room: MatrixClientPeg.get().getRoom(self.props.roomId)
             });
         }, function(error) {
-            that.setState({
+            self.setState({
                 joining: false,
                 joinError: error
             });
diff --git a/src/controllers/pages/MatrixChat.js b/src/controllers/pages/MatrixChat.js
index 44df71a1..48c55fe0 100644
--- a/src/controllers/pages/MatrixChat.js
+++ b/src/controllers/pages/MatrixChat.js
@@ -169,7 +169,7 @@ module.exports = {
 
     startMatrixClient: function() {
         var cli = MatrixClientPeg.get();
-        var that = this;
+        var self = this;
         cli.on('syncComplete', function() {
             var firstRoom = null;
             if (cli.getRooms() && cli.getRooms().length) {
@@ -177,7 +177,7 @@ module.exports = {
                     cli.getRooms()
                 )[0].roomId;
             }
-            that.setState({ready: true, currentRoom: firstRoom});
+            self.setState({ready: true, currentRoom: firstRoom});
             dis.dispatch({action: 'focus_composer'});
         });
         cli.on('Call.incoming', function(call) {
diff --git a/src/controllers/templates/Login.js b/src/controllers/templates/Login.js
index 3d25a910..27669271 100644
--- a/src/controllers/templates/Login.js
+++ b/src/controllers/templates/Login.js
@@ -50,24 +50,24 @@ module.exports = {
         this.setStep("fetch_stages");
         var cli = MatrixClientPeg.get();
         this.setState({busy: true});
-        var that = this;
+        var self = this;
         cli.loginFlows().done(function(result) {
-            that.setState({
+            self.setState({
                 flows: result.flows,
                 currentStep: 1,
                 totalSteps: result.flows.length+1
             });
-            that.setStep('stage_'+result.flows[0].type);
+            self.setStep('stage_'+result.flows[0].type);
         }, function(error) {
-            that.setStep("choose_hs");
-            that.setState({errorText: 'Unable to contact the given Home Server'});
+            self.setStep("choose_hs");
+            self.setState({errorText: 'Unable to contact the given Home Server'});
         });
     },
 
     onUserPassEntered: function(ev) {
         ev.preventDefault();
         this.setState({busy: true});
-        var that = this;
+        var self = this;
 
         var formVals = this.getFormVals();
 
@@ -77,8 +77,8 @@ module.exports = {
         }).done(function(data) {
             // XXX: we assume this means we're logged in, but there could be a next stage
             MatrixClientPeg.replace(Matrix.createClient({
-                baseUrl: that.state.hs_url,
-                idBaseUrl: that.state.is_url,
+                baseUrl: self.state.hs_url,
+                idBaseUrl: self.state.is_url,
                 userId: data.user_id,
                 accessToken: data.access_token
             }));
@@ -86,8 +86,8 @@ module.exports = {
             if (localStorage) {
                 try {
                     localStorage.clear();
-                    localStorage.setItem("mx_hs_url", that.state.hs_url);
-                    localStorage.setItem("mx_is_url", that.state.is_url);
+                    localStorage.setItem("mx_hs_url", self.state.hs_url);
+                    localStorage.setItem("mx_is_url", self.state.is_url);
                     localStorage.setItem("mx_user_id", data.user_id);
                     localStorage.setItem("mx_access_token", data.access_token);
                 } catch (e) {
@@ -96,12 +96,12 @@ module.exports = {
             } else {
                 console.warn("No local storage available: can't persist session!");
             }
-            if (that.props.onLoggedIn) {
-                that.props.onLoggedIn();
+            if (self.props.onLoggedIn) {
+                self.props.onLoggedIn();
             }
         }, function(error) {
-            that.setStep("stage_m.login.password");
-            that.setState({errorText: 'Login failed.'});
+            self.setStep("stage_m.login.password");
+            self.setState({errorText: 'Login failed.'});
         });
     },