diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml
new file mode 100644
index 0000000000..9186c4b086
--- /dev/null
+++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml
@@ -0,0 +1,26 @@
+import QtQuick 2.0
+
+Item {
+    id: tabletRoot
+    objectName: "tabletRoot"
+
+    function loadSource(url) {
+        loader.source = url;
+    }
+
+    function loadWebUrl(url) {
+        loader.item.url = url;
+    }
+
+    Loader {
+        id: loader
+        objectName: "loader"
+        asynchronous: false
+
+        width: parent.width
+        height: parent.height
+    }
+
+    width: 480
+    height: 720
+}
diff --git a/interface/resources/qml/hifi/tablet/TabletWebView.qml b/interface/resources/qml/hifi/tablet/TabletWebView.qml
new file mode 100644
index 0000000000..1bdba0ad22
--- /dev/null
+++ b/interface/resources/qml/hifi/tablet/TabletWebView.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+import QtWebEngine 1.2
+
+WebEngineView {
+    id: webEngineView
+    height: parent.height
+    width: parent.width
+}
+
diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
index 8e95a22560..7bd32aa99e 100644
--- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
@@ -260,12 +260,8 @@ void RenderableWebEntityItem::loadSourceURL() {
 
         // TABLET_UI_HACK: move this to overlays as well!
         if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") {
-            auto loader = _webSurface->getRootItem()->findChild<QQuickItem*>("loader");
-            if (loader) {
-                auto tablet = loader->findChild<QQuickItem*>("tablet");
-                auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
-                tabletScriptingInterface->setQmlTablet("com.highfidelity.interface.tablet.system", tablet);
-            }
+            auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
+            tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface->getRootItem());
         }
     }
 }
@@ -369,7 +365,7 @@ void RenderableWebEntityItem::destroyWebSurface() {
         // TABLET_UI_HACK: move this to overlays as well!
         if (rootItem && rootItem->objectName() == "tabletRoot") {
             auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
-            tabletScriptingInterface->setQmlTablet("com.highfidelity.interface.tablet.system", nullptr);
+            tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", nullptr);
         }
 
         if (rootItem) {
diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp
index d77c60e9e7..86ee706e0f 100644
--- a/libraries/script-engine/src/TabletScriptingInterface.cpp
+++ b/libraries/script-engine/src/TabletScriptingInterface.cpp
@@ -27,10 +27,10 @@ QObject* TabletScriptingInterface::getTablet(const QString& tabletId) {
     }
 }
 
-void TabletScriptingInterface::setQmlTablet(QString tabletId, QQuickItem* qmlTablet) {
+void TabletScriptingInterface::setQmlTabletRoot(QString tabletId, QQuickItem* qmlTabletRoot) {
     TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet(tabletId));
     if (tablet) {
-        tablet->setQmlTablet(qmlTablet);
+        tablet->setQmlTabletRoot(qmlTabletRoot);
     } else {
         qWarning() << "TabletScriptingInterface::setupTablet() bad tablet object";
     }
@@ -40,6 +40,10 @@ void TabletScriptingInterface::setQmlTablet(QString tabletId, QQuickItem* qmlTab
 // TabletProxy
 //
 
+static const char* TABLET_SOURCE_URL = "Tablet.qml";
+static const char* WEB_VIEW_SOURCE_URL = "TabletWebView.qml";
+static const char* LOADER_SOURCE_PROPERTY_NAME = "loaderSource";
+
 TabletProxy::TabletProxy(QString name) : _name(name) {
     ;
 }
@@ -66,18 +70,35 @@ static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy*
     buttonProxy->setQmlButton(qobject_cast<QQuickItem*>(qmlButton));
 }
 
-void TabletProxy::setQmlTablet(QQuickItem* qmlTablet) {
+void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot) {
     std::lock_guard<std::mutex> guard(_mutex);
-    if (qmlTablet) {
-        _qmlTablet = qmlTablet;
-        for (auto& buttonProxy : _tabletButtonProxies) {
-            addButtonProxyToQmlTablet(_qmlTablet, buttonProxy.data());
-        }
+    _qmlTabletRoot = qmlTabletRoot;
+    if (_qmlTabletRoot) {
+        gotoHomeScreen();
     } else {
-        for (auto& buttonProxy : _tabletButtonProxies) {
-            buttonProxy->setQmlButton(nullptr);
+        removeButtonsFromHomeScreen();
+    }
+}
+
+void TabletProxy::gotoHomeScreen() {
+    if (_qmlTabletRoot) {
+        QString tabletSource = _qmlTabletRoot->property(LOADER_SOURCE_PROPERTY_NAME).toString();
+        if (tabletSource != TABLET_SOURCE_URL) {
+            QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL)));
+            addButtonsToHomeScreen();
         }
-        _qmlTablet = nullptr;
+    }
+}
+
+void TabletProxy::gotoWebScreen(const QString& url) {
+    if (_qmlTabletRoot) {
+        removeButtonsFromHomeScreen();
+        QString tabletSource = _qmlTabletRoot->property(LOADER_SOURCE_PROPERTY_NAME).toString();
+        if (tabletSource != WEB_VIEW_SOURCE_URL) {
+            QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(WEB_VIEW_SOURCE_URL)));
+            // TABLET_UI_HACK: TODO: addEventBridge to tablet....
+        }
+        QMetaObject::invokeMethod(_qmlTabletRoot, "loadWebUrl", Q_ARG(const QVariant&, QVariant(url)));
     }
 }
 
@@ -85,8 +106,8 @@ QObject* TabletProxy::addButton(const QVariant& properties) {
     auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap()));
     std::lock_guard<std::mutex> guard(_mutex);
     _tabletButtonProxies.push_back(tabletButtonProxy);
-    if (_qmlTablet) {
-        addButtonProxyToQmlTablet(_qmlTablet, tabletButtonProxy.data());
+    if (_qmlTabletRoot) {
+        addButtonProxyToQmlTablet(_qmlTabletRoot, tabletButtonProxy.data());
     }
     return tabletButtonProxy.data();
 }
@@ -95,9 +116,9 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) {
     std::lock_guard<std::mutex> guard(_mutex);
     auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy);
     if (iter != _tabletButtonProxies.end()) {
-        if (_qmlTablet) {
+        if (_qmlTabletRoot) {
             (*iter)->setQmlButton(nullptr);
-            QMetaObject::invokeMethod(_qmlTablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getProperties()));
+            QMetaObject::invokeMethod(_qmlTabletRoot, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getProperties()));
         }
         _tabletButtonProxies.erase(iter);
     } else {
@@ -105,6 +126,34 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) {
     }
 }
 
+void TabletProxy::addButtonsToHomeScreen() {
+    if (!_qmlTabletRoot) {
+        return;
+    }
+
+    auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
+    if (!loader) {
+        return;
+    }
+
+    auto tablet = loader->findChild<QQuickItem*>("tablet");
+    if (!tablet) {
+        return;
+    }
+
+    auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
+    for (auto& buttonProxy : _tabletButtonProxies) {
+        addButtonProxyToQmlTablet(tablet, buttonProxy.data());
+    }
+}
+
+void TabletProxy::removeButtonsFromHomeScreen() {
+    auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
+    for (auto& buttonProxy : _tabletButtonProxies) {
+        buttonProxy->setQmlButton(nullptr);
+    }
+}
+
 //
 // TabletButtonProxy
 //
diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h
index da796be174..b9482ca8a4 100644
--- a/libraries/script-engine/src/TabletScriptingInterface.h
+++ b/libraries/script-engine/src/TabletScriptingInterface.h
@@ -37,7 +37,7 @@ public:
      */
     Q_INVOKABLE QObject* getTablet(const QString& tabletId);
 
-    void setQmlTablet(QString tabletId, QQuickItem* qmlTablet);
+    void setQmlTabletRoot(QString tabletId, QQuickItem* qmlTabletRoot);
 
 protected:
     std::mutex _mutex;
@@ -54,7 +54,20 @@ class TabletProxy : public QObject {
 public:
     TabletProxy(QString name);
 
-    void setQmlTablet(QQuickItem* qmlTablet);
+    void setQmlTabletRoot(QQuickItem* qmlTabletRoot);
+
+    /**jsdoc
+     * @function TabletProxy#gotoHomeScreen
+     * transition to the home screen
+     */
+    Q_INVOKABLE void gotoHomeScreen();
+
+    /**jsdoc
+     * @function TabletProxy#gotoWebScreen
+     * show the specified web url on the tablet.
+     * @param url {string}
+     */
+    Q_INVOKABLE void gotoWebScreen(const QString& url);
 
     /**jsdoc
      * @function TabletProxy#addButton
@@ -73,10 +86,14 @@ public:
 
     QString getName() const { return _name; }
 protected:
+
+    void addButtonsToHomeScreen();
+    void removeButtonsFromHomeScreen();
+
     QString _name;
     std::mutex _mutex;
     std::vector<QSharedPointer<TabletButtonProxy>> _tabletButtonProxies;
-    QQuickItem* _qmlTablet { nullptr };
+    QQuickItem* _qmlTabletRoot { nullptr };
 };
 
 /**jsdoc
diff --git a/scripts/developer/tests/tabletTest.js b/scripts/developer/tests/tabletTest.js
index 9920ff30b8..9eba7e53d7 100644
--- a/scripts/developer/tests/tabletTest.js
+++ b/scripts/developer/tests/tabletTest.js
@@ -28,6 +28,8 @@ Script.setInterval(function () {
 
 button.clicked.connect(function () {
     print("AJT: BAM!!! CLICK from JS!");
+    var url = "https://news.ycombinator.com/";
+    tablet.gotoWebScreen(url);
 });
 
 Script.scriptEnding.connect(function () {
diff --git a/scripts/system/help.js b/scripts/system/help.js
index c8e14a80a6..b95ccbb529 100644
--- a/scripts/system/help.js
+++ b/scripts/system/help.js
@@ -10,6 +10,7 @@
 //  Distributed under the Apache License, Version 2.0.
 //  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
 //
+/* globals Tablet */
 
 (function() { // BEGIN LOCAL_SCOPE
 
@@ -18,9 +19,25 @@
         text: "HELP"
     });
 
-    // TODO: make button state reflect whether the window is opened or closed (independently from us).
-    function onClicked(){
-        Menu.triggerOption('Help...')
+    function onClicked() {
+        var HELP_URL = Script.resourcesPath() + "html/help.html";
+
+        // Similar logic to Application::showHelp()
+        var defaultTab = "kbm";
+        var handControllerName = "vive";
+        if (HMD.active) {
+            if ("Vive" in Controller.Hardware) {
+                defaultTab = "handControllers";
+                handControllerName = "vive";
+            } else if ("OculusTouch" in Controller.Hardware) {
+                defaultTab = "handControllers";
+                handControllerName = "oculus";
+            }
+        } else if ("SDL2" in Controller.Hardware) {
+            defaultTab = "gamepad";
+        }
+        var queryParameters = "handControllerName=" + handControllerName + "&defaultTab=" + defaultTab;
+        tablet.gotoWebScreen(HELP_URL + "?" + queryParameters);
     }
 
     button.clicked.connect(onClicked);