diff --git a/gui/backend.go b/gui/backend.go
index d4f5738d8ace65427c0f47e68b328e6a35b4396e..38f40a84491d429410a727b050628ba4e25dc65c 100644
--- a/gui/backend.go
+++ b/gui/backend.go
@@ -48,6 +48,11 @@ func UseTransport(transport string) {
 	backend.UseTransport(transport)
 }
 
+//export GetTransport
+func GetTransport() *C.char {
+	return (*C.char)(backend.GetTransport())
+}
+
 //export Quit
 func Quit() {
 	backend.Quit()
diff --git a/gui/gui.qrc b/gui/gui.qrc
index 22b3b738d1b7635c842ccf3063e99d16f71233a1..be0d3e9909fa29f51fcbdf4022ac915d4847a051 100644
--- a/gui/gui.qrc
+++ b/gui/gui.qrc
@@ -22,6 +22,7 @@
         <file>assets/icon/png/white/vpn_wait_1.png</file>
         <file>assets/icon/png/white/vpn_wait_2.png</file>
         <file>assets/icon/png/white/vpn_wait_3.png</file>
+        <file>assets/img/bird.jpg</file>
 
         <file alias="providers.json">providers/providers.json</file>
     </qresource>
diff --git a/gui/handlers.cpp b/gui/handlers.cpp
index 9f68834d58c3bcb5ddd0bd65718d1c88773170a8..cec43cabb5ddb116966d65cade1fff050008ebda 100644
--- a/gui/handlers.cpp
+++ b/gui/handlers.cpp
@@ -52,6 +52,16 @@ void Backend::useAutomaticGateway()
     UseAutomaticGateway();
 }
 
+void Backend::useTransport(QString transport)
+{
+    UseTransport(toGoStr(transport));
+}
+
+QString Backend::getTransport()
+{
+    return QString(GetTransport());
+}
+
 void Backend::login(QString username, QString password)
 {
     Login(toGoStr(username), toGoStr(password));
diff --git a/gui/handlers.h b/gui/handlers.h
index 3415b7edd9fcede3644c5ad226e0b91627f9a01d..9c11b60abd5a146662928eaa06e412cce3457f6d 100644
--- a/gui/handlers.h
+++ b/gui/handlers.h
@@ -38,6 +38,8 @@ public slots:
     void donateSeen();
     void useLocation(QString username);
     void useAutomaticGateway();
+    void useTransport(QString transport);
+    QString getTransport();
     void login(QString username, QString password);
     void resetError(QString errlabel);
     void resetNotification(QString label);
diff --git a/gui/qml/main.qml b/gui/qml/main.qml
index 1399f0f31103ab396809228c40daf3c5587811b8..7048a8108d2f33cc68d639495e0cd6b5755d5b9b 100644
--- a/gui/qml/main.qml
+++ b/gui/qml/main.qml
@@ -8,9 +8,9 @@ import Qt.labs.platform 1.0
 ApplicationWindow {
     id: app
     visible: true
-    width: 500
+    width: 300
     height: 600
-    maximumWidth: 600
+    maximumWidth: 300
     minimumWidth: 300
     maximumHeight: 500
     minimumHeight: 300
@@ -24,17 +24,20 @@ ApplicationWindow {
         console.debug(msg)
     }
 
-    // TODO get a nice background color for this mainwindow. It should be customizable.
-    // TODO refactorize all this mess into discrete components.
+    // TODO refactor into discrete components.
+
     TabBar {
         id: bar
         width: parent.width
         TabButton {
-            text: qsTr("Info")
+            text: qsTr("Status")
         }
         TabButton {
             text: qsTr("Location")
         }
+        TabButton {
+            text: qsTr("Bridges")
+        }
     }
 
     StackLayout {
@@ -47,93 +50,121 @@ ApplicationWindow {
             id: infoTab
             anchors.centerIn: parent
 
-            Column {
+            Rectangle {
+                id: background
+                anchors.fill: parent;
+                anchors.topMargin: 40;
 
+                Image {
+                    source: "qrc:/assets/img/bird.jpg";
+                    fillMode: Image.PreserveAspectCrop;
+                    anchors.fill: parent; 
+                    opacity: 0.8;
+                }
+            }
+
+            Item {
+                id: connBox
                 anchors.centerIn: parent
-                spacing: 5
 
-                Text {
-                    id: mainStatus
-                    text: "off"
-                    font.pixelSize: 26
-                    anchors.horizontalCenter: parent.horizontalCenter
-                }
+                width: 300
+                height: 300
 
-                Text {
-                    id: mainCurrentGateway
-                    text: ""
-                    font.pixelSize: 20
-                    anchors.horizontalCenter: parent.horizontalCenter
+                Rectangle {
+                    anchors.fill: parent
+                    color: "white"
+                    opacity: 0.3
+                    layer.enabled: true
                 }
 
-                SwitchDelegate {
+                Column {
 
-                    id: vpntoggle
+                    anchors.centerIn: parent
+                    spacing: 5
 
-                    text: qsTr("")
-                    checked: false
-                    anchors.horizontalCenter: parent.horizontalCenter
+                    Text {
+                        id: mainStatus
+                        text: "off"
+                        font.pixelSize: 26
+                        anchors.horizontalCenter: parent.horizontalCenter
+                    }
 
-                    Connections {
-                        function onCheckedChanged() {
-                            if (vpntoggle.checked == true
-                                    && ctx.status == "off") {
-                                backend.switchOn()
-                            }
-                            if (vpntoggle.checked === false
-                                    && ctx.status == "on") {
-                                backend.switchOff()
+                    Text {
+                        id: mainCurrentGateway
+                        text: ""
+                        font.pixelSize: 20
+                        anchors.horizontalCenter: parent.horizontalCenter
+                    }
+
+                    SwitchDelegate {
+
+                        id: vpntoggle
+
+                        text: qsTr("")
+                        checked: false
+                        anchors.horizontalCenter: parent.horizontalCenter
+
+                        Connections {
+                            function onCheckedChanged() {
+                                if (vpntoggle.checked == true
+                                        && ctx.status == "off") {
+                                    backend.switchOn()
+                                }
+                                if (vpntoggle.checked === false
+                                        && ctx.status == "on") {
+                                    backend.switchOff()
+                                }
                             }
                         }
-                    }
 
-                    contentItem: Text {
-                        rightPadding: vpntoggle.indicator.width + vpntoggle.spacing
-                        text: vpntoggle.text
-                        font: vpntoggle.font
-                        opacity: enabled ? 1.0 : 0.3
-                        color: vpntoggle.down ? "#17a81a" : "#21be2b"
-                        elide: Text.ElideRight
-                        verticalAlignment: Text.AlignVCenter
-                    }
+                        contentItem: Text {
+                            rightPadding: vpntoggle.indicator.width + vpntoggle.spacing
+                            text: vpntoggle.text
+                            font: vpntoggle.font
+                            opacity: enabled ? 1.0 : 0.5
+                            color: vpntoggle.down ? "#17a81a" : "#21be2b"
+                            elide: Text.ElideRight
+                            verticalAlignment: Text.AlignVCenter
+                        }
 
-                    indicator: Rectangle {
-                        implicitWidth: 48
-                        implicitHeight: 26
-                        x: vpntoggle.width - width - vpntoggle.rightPadding
-                        y: parent.height / 2 - height / 2
-                        radius: 13
-                        color: vpntoggle.checked ? "#17a81a" : "transparent"
-                        border.color: vpntoggle.checked ? "#17a81a" : "#cccccc"
-
-                        Rectangle {
-                            x: vpntoggle.checked ? parent.width - width : 0
-                            width: 26
-                            height: 26
+                        indicator: Rectangle {
+                            implicitWidth: 48
+                            implicitHeight: 26
+                            x: vpntoggle.width - width - vpntoggle.rightPadding
+                            y: parent.height / 2 - height / 2
                             radius: 13
-                            color: vpntoggle.down ? "#cccccc" : "#ffffff"
-                            border.color: vpntoggle.checked ? (vpntoggle.down ? "#17a81a" : "#21be2b") : "#999999"
+                            color: vpntoggle.checked ? "#17a81a" : "transparent"
+                            border.color: vpntoggle.checked ? "#17a81a" : "#cccccc"
+
+                            Rectangle {
+                                x: vpntoggle.checked ? parent.width - width : 0
+                                width: 26
+                                height: 26
+                                radius: 13
+                                color: vpntoggle.down ? "#cccccc" : "#ffffff"
+                                border.color: vpntoggle.checked ? (vpntoggle.down ? "#17a81a" : "#21be2b") : "#999999"
+                            }
                         }
-                    }
 
-                    background: Rectangle {
-                        implicitWidth: 100
-                        implicitHeight: 40
-                        visible: vpntoggle.down || vpntoggle.highlighted
-                        color: vpntoggle.down ? "#bdbebf" : "#eeeeee"
+                        background: Rectangle {
+                            implicitWidth: 100
+                            implicitHeight: 40
+                            visible: vpntoggle.down || vpntoggle.highlighted
+                            color: vpntoggle.down ? "#17a81a" : "#eeeeee"
+                        }
+                    } // end switchdelegate
+
+                    Text {
+                        id: manualOverrideWarning
+                        font.pixelSize: 10
+                        color: "grey"
+                        text: qsTr("Location has been manually set.")
+                        anchors.horizontalCenter: parent.horizontalCenter
+                        visible: isManualLocation()
                     }
-                } // end switchdelegate
-
-                Text {
-                    id: manualOverrideWarning
-                    font.pixelSize: 10
-                    color: "grey"
-                    text: qsTr("Location has been manually set.")
-                    anchors.horizontalCenter: parent.horizontalCenter
-                    visible: isManualLocation()
-                }
-            }
-        }
+                } // end column
+            } // end inner item
+        } // end outer item
 
         Item {
 
@@ -148,7 +179,7 @@ ApplicationWindow {
                 RadioButton {
                     id: autoSelectionButton
                     checked: !isManualLocation()
-                    text: qsTr("Best")
+                    text: qsTr("Recommended")
                     onClicked: backend.useAutomaticGateway()
                 }
                 RadioButton {
@@ -163,7 +194,7 @@ ApplicationWindow {
                     visible: manualSelectionButton.checked
                     anchors.horizontalCenter: parent.horizontalCenter
 
-                    model: [qsTr("Best")]
+                    model: [qsTr("Recommended")]
                     onActivated: {
                         console.debug("Selected gateway:", currentText)
                         backend.useLocation(currentText.toString())
@@ -200,6 +231,45 @@ ApplicationWindow {
                 }
             } // end column
         } // end item
+
+        Item {
+
+            id: bridgesTab
+            anchors.centerIn: parent
+            width: parent.width
+
+            Column {
+
+                anchors.centerIn: parent
+                spacing: 10
+                width: parent.width
+
+                CheckBox {
+                    checked: false
+                    text: qsTr("Use obfs4 bridges")
+                    font.pixelSize: 14
+                    anchors.horizontalCenter: parent.horizontalCenter
+                }
+                Text {
+                    id: bridgesInfo
+                    width: 250
+                    color: "grey"
+                    text: qsTr("Select a bridge only if you know that you need it to evade censorship in your country or local network.")
+                    anchors.horizontalCenter: parent.horizontalCenter
+                    wrapMode: Text.WordWrap 
+                }
+                Text {
+                    id: bridgeReconnect
+                    width: 250
+                    font.pixelSize: 12
+                    color: "red"
+                    text: qsTr("The change will take effect next time you connect to the VPN.")
+                    anchors.horizontalCenter: parent.horizontalCenter
+                    wrapMode: Text.WordWrap 
+                    visible: true
+                }
+            } // end column
+        } // end item
     } // end stacklayout
 
     Connections {
diff --git a/pkg/backend/api.go b/pkg/backend/api.go
index 0db26aeb4243540fabe19ab58fae8961e08e8c28..e96c65b7315f01588327812541fb134905bb9052 100644
--- a/pkg/backend/api.go
+++ b/pkg/backend/api.go
@@ -83,6 +83,10 @@ func UseTransport(label string) {
 	ctx.bm.UseTransport(label)
 }
 
+func GetTransport() *C.char {
+	return C.CString(ctx.bm.GetTransport())
+}
+
 func Quit() {
 	if ctx.autostart != nil {
 		ctx.autostart.Disable()
diff --git a/pkg/backend/status.go b/pkg/backend/status.go
index bdbdd3510f498582ca7cd55262a33050e49469b2..1ec5c4fee4cd426ed5134f965e0dd18243687df1 100644
--- a/pkg/backend/status.go
+++ b/pkg/backend/status.go
@@ -57,7 +57,8 @@ type connectionCtx struct {
 func (c *connectionCtx) toJson() ([]byte, error) {
 	statusMutex.Lock()
 	if c.bm != nil {
-		c.Locations = c.bm.ListLocationFullness("openvpn")
+		transport := c.bm.GetTransport()
+		c.Locations = c.bm.ListLocationFullness(transport)
 		c.CurrentGateway = c.bm.GetCurrentGateway()
 		c.CurrentLocation = c.bm.GetCurrentLocation()
 		c.CurrentCountry = c.bm.GetCurrentCountry()
diff --git a/pkg/backend/webapi.go b/pkg/backend/webapi.go
index 903112e49e1f792a7a69f481f282ffe1cefbfd95..a14974e7314e7aaeb0de22010acbfc8cb4e79481 100644
--- a/pkg/backend/webapi.go
+++ b/pkg/backend/webapi.go
@@ -49,7 +49,7 @@ func webGatewaySet(w http.ResponseWriter, r *http.Request) {
 			fmt.Fprintf(w, "ParseForm() err: %v", err)
 			return
 		}
-		gwLabel := r.FormValue("gw")
+		gwLabel := r.FormValue("transport")
 		fmt.Fprintf(w, "selected gateway: %s\n", gwLabel)
 		ctx.bm.UseGateway(gwLabel)
 		// TODO make sure we don't tear the fw down on reconnect...
@@ -63,23 +63,48 @@ func webGatewaySet(w http.ResponseWriter, r *http.Request) {
 }
 
 func webGatewayList(w http.ResponseWriter, r *http.Request) {
-	locationJson, err := json.Marshal(ctx.bm.ListLocationFullness("openvpn"))
+	transport := ctx.bm.GetTransport()
+	locationJson, err := json.Marshal(ctx.bm.ListLocationFullness(transport))
 	if err != nil {
 		fmt.Fprintf(w, "Error converting json: %v", err)
 	}
 	fmt.Fprintf(w, string(locationJson))
 }
 
-// TODO
 func webTransportGet(w http.ResponseWriter, r *http.Request) {
+	t, err := json.Marshal(ctx.bm.GetTransport())
+	if err != nil {
+		fmt.Fprintf(w, "Error converting json: %v", err)
+	}
+	fmt.Fprintf(w, string(t))
+
 }
 
-// TODO
 func webTransportSet(w http.ResponseWriter, r *http.Request) {
+	switch r.Method {
+	case "POST":
+		if err := r.ParseForm(); err != nil {
+			fmt.Fprintf(w, "ParseForm() err: %v", err)
+			return
+		}
+		t := r.FormValue("transport")
+		if isValidTransport(t) {
+			fmt.Fprintf(w, "Selected transport: %s\n", t)
+			go ctx.bm.SetTransport(string(t))
+		} else {
+			fmt.Fprintf(w, "Unknown transport: %s\n", t)
+		}
+	default:
+		fmt.Fprintf(w, "Only POST supported.")
+	}
 }
 
-// TODO
 func webTransportList(w http.ResponseWriter, r *http.Request) {
+	t, err := json.Marshal([]string{"openvpn", "obfs4"})
+	if err != nil {
+		fmt.Fprintf(w, "Error converting json: %v", err)
+	}
+	fmt.Fprintf(w, string(t))
 }
 
 func webQuit(w http.ResponseWriter, r *http.Request) {
@@ -97,10 +122,19 @@ func enableWebAPI(port int) {
 	http.Handle("/vpn/gw/get", CheckAuth(http.HandlerFunc(webGatewayGet), token))
 	http.Handle("/vpn/gw/set", CheckAuth(http.HandlerFunc(webGatewaySet), token))
 	http.Handle("/vpn/gw/list", CheckAuth(http.HandlerFunc(webGatewayList), token))
-	//http.Handle("/vpn/transport/get", CheckAuth(http.HandlerFunc(webTransportGet), token))
-	//http.Handle("/vpn/transport/set", CheckAuth(http.HandlerFunc(webTransportSet), token))
-	//http.Handle("/vpn/transport/list", CheckAuth(http.HandlerFunc(webTransportList), token))
+	http.Handle("/vpn/transport/get", CheckAuth(http.HandlerFunc(webTransportGet), token))
+	http.Handle("/vpn/transport/set", CheckAuth(http.HandlerFunc(webTransportSet), token))
+	http.Handle("/vpn/transport/list", CheckAuth(http.HandlerFunc(webTransportList), token))
 	http.Handle("/vpn/status", CheckAuth(http.HandlerFunc(webStatus), token))
 	http.Handle("/vpn/quit", CheckAuth(http.HandlerFunc(webQuit), token))
 	http.ListenAndServe(":"+strconv.Itoa(port), nil)
 }
+
+func isValidTransport(t string) bool {
+	for _, b := range []string{"openvpn", "obfs4"} {
+		if b == t {
+			return true
+		}
+	}
+	return false
+}
diff --git a/pkg/bitmask/bitmask.go b/pkg/bitmask/bitmask.go
index 3f484e8ac8fe443a089fb88ee5da5afdb2f53cef..b4308089a82254e5d570c444b220038664b3f6d6 100644
--- a/pkg/bitmask/bitmask.go
+++ b/pkg/bitmask/bitmask.go
@@ -30,6 +30,8 @@ type Bitmask interface {
 	ListLocationFullness(protocol string) map[string]float64
 	UseGateway(name string)
 	UseAutomaticGateway()
+	GetTransport() string
+	SetTransport(string) error
 	GetCurrentGateway() string
 	GetCurrentLocation() string
 	GetCurrentCountry() string
diff --git a/pkg/vpn/openvpn.go b/pkg/vpn/openvpn.go
index 244195bd11ec2796b850988f953462cff4fd2fbb..d69f4e64acb2419e51113ced934707ecc1cc5f08 100644
--- a/pkg/vpn/openvpn.go
+++ b/pkg/vpn/openvpn.go
@@ -121,26 +121,8 @@ func (b *Bitmask) listenShapeErr() {
 
 func (b *Bitmask) startOpenVPN() error {
 	arg := []string{}
-	// Empty transport means we get only the openvpn gateways
-	if b.transport == "" {
-		arg = b.openvpnArgs
-		gateways, err := b.bonafide.GetGateways("openvpn")
-		if err != nil {
-			return err
-		}
-		err = b.launch.firewallStart(gateways)
-		if err != nil {
-			return err
-		}
-
-		for _, gw := range gateways {
-			for _, port := range gw.Ports {
-				arg = append(arg, "--remote", gw.IPAddress, port, "tcp4")
-			}
-		}
-	} else {
-		// For now, obf4 is the only supported Pluggable Transport
-		gateways, err := b.bonafide.GetGateways(b.transport)
+	if b.GetTransport() == "obfs4" {
+		gateways, err := b.bonafide.GetGateways("obfs4")
 		if err != nil {
 			return err
 		}
@@ -164,6 +146,22 @@ func (b *Bitmask) startOpenVPN() error {
 		proxyArgs := strings.Split(proxy, ":")
 		arg = append(arg, "--remote", proxyArgs[0], proxyArgs[1], "tcp4")
 		arg = append(arg, "--route", gw.IPAddress, "255.255.255.255", "net_gateway")
+	} else {
+		arg = b.openvpnArgs
+		gateways, err := b.bonafide.GetGateways("openvpn")
+		if err != nil {
+			return err
+		}
+		err = b.launch.firewallStart(gateways)
+		if err != nil {
+			return err
+		}
+
+		for _, gw := range gateways {
+			for _, port := range gw.Ports {
+				arg = append(arg, "--remote", gw.IPAddress, port, "tcp4")
+			}
+		}
 	}
 	arg = append(arg,
 		"--verb", "3",
@@ -171,8 +169,8 @@ func (b *Bitmask) startOpenVPN() error {
 		"--management", openvpnManagementAddr, openvpnManagementPort,
 		"--ca", b.getTempCaCertPath(),
 		"--cert", b.certPemPath,
-		"--key", b.certPemPath,
-		"--persist-tun")
+		"--key", b.certPemPath)
+	//"--persist-tun")
 	return b.launch.openvpnStart(arg...)
 }
 
@@ -330,6 +328,23 @@ func (b *Bitmask) UseTransport(transport string) error {
 	return nil
 }
 
+func (b *Bitmask) GetTransport() string {
+	if b.transport == "obfs4" {
+		return "obfs4"
+	} else {
+		return "openvpn"
+	}
+}
+
+func (b *Bitmask) SetTransport(t string) error {
+	if t != "openvpn" && t != "obfs4" {
+		return errors.New("Transport not supported: " + t)
+	}
+	log.Println("Setting transport to", t)
+	b.transport = t
+	return nil
+}
+
 func (b *Bitmask) getTempCertPemPath() string {
 	return path.Join(b.tempdir, "openvpn.pem")
 }