diff --git a/addons/website/__manifest__.py b/addons/website/__manifest__.py
index 3c86cc69a0e94701048b9e6a6f13c3a0dad591e6..d2017df93368493a3e830ddf1d5c4855b68c1c19 100644
--- a/addons/website/__manifest__.py
+++ b/addons/website/__manifest__.py
@@ -38,7 +38,11 @@
     'demo': [
         'data/website_demo.xml',
     ],
-    'qweb': ['static/src/xml/website.backend.xml'],
+    'qweb': [
+        'static/src/xml/website.backend.xml',
+        'static/src/xml/website_widget.xml',
+        'static/src/xml/theme_preview.xml',
+    ],
     'application': True,
     'uninstall_hook': 'uninstall_hook',
 }
diff --git a/addons/website/models/res_config_settings.py b/addons/website/models/res_config_settings.py
index 7b52294ddb1552376552dbe2c78b8025a16369a5..4d05f8436b9d24cc2b1a016c912f846d5eceae58 100644
--- a/addons/website/models/res_config_settings.py
+++ b/addons/website/models/res_config_settings.py
@@ -161,5 +161,6 @@ class ResConfigSettings(models.TransientModel):
 
     def install_theme_on_current_website(self):
         self.website_id._force()
-        action = self.env.ref('website.theme_install_kanban_action')
-        return action.read()[0]
+        action = self.env.ref('website.theme_install_kanban_action').read()[0]
+        action['target'] = 'main'
+        return action
diff --git a/addons/website/static/src/img/phone.png b/addons/website/static/src/img/phone.png
new file mode 100644
index 0000000000000000000000000000000000000000..0570c4d8fe27d837b829779dd665a6fbc89a4d5d
Binary files /dev/null and b/addons/website/static/src/img/phone.png differ
diff --git a/addons/website/static/src/js/theme_preview_form.js b/addons/website/static/src/js/theme_preview_form.js
new file mode 100644
index 0000000000000000000000000000000000000000..76ce0f3f9f83ca52ba44d6592280bdf4c0315dda
--- /dev/null
+++ b/addons/website/static/src/js/theme_preview_form.js
@@ -0,0 +1,111 @@
+odoo.define('website.theme_preview_form', function (require) {
+"use strict";
+
+var FormController = require('web.FormController');
+var FormView = require('web.FormView');
+var viewRegistry = require('web.view_registry');
+var core = require('web.core');
+var _t = core._t;
+var qweb = core.qweb;
+
+var ThemePreviewController = FormController.extend({
+    events: Object.assign({}, FormController.prototype.events, {
+        'click .o_use_theme': '_onUseThemeClick',
+        'click .o_switch_theme': '_onSwitchThemeClick',
+        'click .o_switch_mode_button': '_onSwitchButtonClick',
+    }),
+    /**
+     * @override
+     */
+    start: function () {
+        this.$el.addClass('o_view_form_theme_preview_controller');
+        return this._super.apply(this, arguments);
+    },
+
+    // -------------------------------------------------------------------------
+    // Public
+    // -------------------------------------------------------------------------
+    /**
+     * @override
+     */
+    autofocus: function () {
+        // force refresh label of button switch
+        this.$switchButton = this._renderSwitchButton();
+        $('.o_switch_mode_button').replaceWith(this.$switchButton);
+        this._super.apply(this, arguments);
+    },
+     /**
+     * @override
+     */
+    renderButtons: function ($node) {
+        var $previewButton = $(qweb.render('website.ThemePreview.Buttons'));
+        $node.html($previewButton);
+        this.$switchButton = this._renderSwitchButton();
+        $node.find('.o_switch_mode_button').replaceWith(this.$switchButton);
+    },
+
+    // -------------------------------------------------------------------------
+    // Private
+    // -------------------------------------------------------------------------
+     /**
+     * Return jQuery Element button 'Switch Mode' with correct labelling.
+     *
+     * @private
+     */
+    _renderSwitchButton: function () {
+        var isMobile = !!this.$('.is_mobile').length;
+        return $(qweb.render('website.ThemePreview.SwitchModeButton', {
+            'icon': isMobile ? 'fa-desktop' : 'fa-refresh',
+            'PreviewType': isMobile ? _t('Desktop') : _t('Mobile'),
+        }));
+    },
+    // -------------------------------------------------------------------------
+    // Handlers
+    // -------------------------------------------------------------------------
+    /**
+     * Handler called when user click on 'Desktop/Mobile preview' button in forw view.
+     *
+     * @private
+     */
+    _onSwitchButtonClick: function () {
+        this.$('.o_preview_frame').toggleClass('is_mobile');
+        const $switchButton = this.$switchButton;
+        this.$switchButton = this._renderSwitchButton();
+        $switchButton.replaceWith(this.$switchButton);
+    },
+    /**
+     * Handler called when user click on 'Choose another theme' button in forw view.
+     *
+     * @private
+     */
+    _onSwitchThemeClick: function () {
+        this.trigger_up('history_back');
+    },
+    /**
+     * Handler called when user click on 'Use this theme' button in forw view.
+     *
+     * @private
+     */
+    _onUseThemeClick: function () {
+        const $loader = $(qweb.render('website.ThemePreview.Loader'));
+        $('body').append($loader);
+        return this._rpc({
+            model: 'ir.module.module',
+            method: 'button_choose_theme',
+            args: [this.getSelectedIds()[0]],
+            context: this.initialState.context,
+        }, {shadow: true})
+            .then(result => this.do_action(result))
+            .guardedCatch(() => $loader.remove());
+    },
+});
+
+var ThemePreviewFormView = FormView.extend({
+    config: _.extend({}, FormView.prototype.config, {
+        Controller: ThemePreviewController
+    }),
+});
+
+viewRegistry.add('theme_preview_form', ThemePreviewFormView);
+
+});
diff --git a/addons/website/static/src/js/theme_preview_kanban.js b/addons/website/static/src/js/theme_preview_kanban.js
new file mode 100644
index 0000000000000000000000000000000000000000..570c75fba02ffd29d53805181adbe35f7e531671
--- /dev/null
+++ b/addons/website/static/src/js/theme_preview_kanban.js
@@ -0,0 +1,43 @@
+odoo.define('website.theme_preview_kanban', function (require) {
+"use strict";
+
+var KanbanController = require('web.KanbanController');
+var KanbanView = require('web.KanbanView');
+var ViewRegistry = require('web.view_registry');
+
+var ThemePreviewKanbanController = KanbanController.extend({
+    /**
+     * @override
+     */
+    start: function () {
+        this.$el.addClass('o_view_kanban_theme_preview_controller');
+        return this._super.apply(this, arguments);
+    },
+});
+
+var ThemePreviewKanbanView = KanbanView.extend({
+    searchMenuTypes: [],
+
+    config: _.extend({}, KanbanView.prototype.config, {
+        Controller: ThemePreviewKanbanController,
+    }),
+
+    // -------------------------------------------------------------------------
+    // Private
+    // -------------------------------------------------------------------------
+    /**
+     * @override
+     *
+     */
+    _createControlPanel: function (parent) {
+        return this._super.apply(this, arguments).then(controlPanel => {
+            var websiteLink = '<a class="btn btn-secondary ml-3" href="/"><i class="fa fa-close"></i></a>';
+            controlPanel.$('div.o_cp_searchview').after(websiteLink);
+            return controlPanel;
+        });
+    },
+});
+
+ViewRegistry.add('theme_preview_kanban', ThemePreviewKanbanView);
+
+});
diff --git a/addons/website/static/src/js/widget_iframe.js b/addons/website/static/src/js/widget_iframe.js
new file mode 100644
index 0000000000000000000000000000000000000000..8829ffa8684edfab9c7004ad69c00be16898dade
--- /dev/null
+++ b/addons/website/static/src/js/widget_iframe.js
@@ -0,0 +1,28 @@
+odoo.define('website.iframe_widget', function (require) {
+"use strict";
+
+
+var AbstractField = require('web.AbstractField');
+var core = require('web.core');
+var fieldRegistry = require('web.field_registry');
+
+var QWeb = core.qweb;
+
+/**
+ * Display iframe
+ */
+var FieldIframePreview = AbstractField.extend({
+    className: 'd-block o_field_iframe_preview m-0 h-100',
+
+    _render: function () {
+        this.$el.html(QWeb.render('website.iframeWidget', {
+            url: this.value,
+        }));
+    },
+});
+
+fieldRegistry.add('iframe', FieldIframePreview);
+
+return FieldIframePreview;
+
+});
diff --git a/addons/website/static/src/scss/website.backend.scss b/addons/website/static/src/scss/website.backend.scss
index 0fd875c784331fb3a85fec32e3054939b0d5e7e6..bd22cb6b29753ff2228226558f01a12d126e5008 100644
--- a/addons/website/static/src/scss/website.backend.scss
+++ b/addons/website/static/src/scss/website.backend.scss
@@ -373,3 +373,76 @@
         }
     }
 }
+
+.o_view_form_theme_preview_controller {
+    .o_control_panel > div:first-of-type {
+        display: none;
+    }
+    div.o_form_nosheet {
+        padding: 0px;
+        height:100%;
+        width:100%;
+    }
+
+    .is_mobile {
+        @include media-breakpoint-up(md) {
+            iframe {
+                // mobile frame is rounded
+                border-radius: 15px;
+                height: 735px;
+            }
+            .img_mobile {
+                pointer-events: none;
+                display: block !important;
+                position: absolute;
+                top: 16px;
+                left: calc(50% - 200px)
+            }
+            .o_field_iframe_preview {
+                margin: auto !important;
+                padding: 53px 11px 58px 28px;
+                width: 416px;
+            }
+        }
+    }
+
+}
+.o_view_kanban_theme_preview_controller {
+    .o_searchview_more, .o_control_panel > div:nth-child(2) {
+        display: none;
+    }
+}
+
+
+.o_theme_install_loader_container {
+  opacity: 0.85;
+  pointer-events: all;
+}
+.o_theme_install_loader {
+  display: inline-block;
+  position: relative;
+  width: 64px;
+  height: 64px;
+}
+.o_theme_install_loader:after {
+  content: " ";
+  display: block;
+  border-radius: 50%;
+  margin: 6px;
+  border: 26px solid $o-brand-primary;
+  border-color: $o-brand-primary transparent $o-brand-primary transparent;
+  animation: o_theme_install_loader 1.2s infinite;
+}
+@keyframes o_theme_install_loader {
+  0% {
+    transform: rotate(0);
+    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
+  }
+  50% {
+    transform: rotate(900deg);
+    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
+  }
+  100% {
+    transform: rotate(1800deg);
+  }
+}
diff --git a/addons/website/static/src/xml/theme_preview.xml b/addons/website/static/src/xml/theme_preview.xml
new file mode 100644
index 0000000000000000000000000000000000000000..87ef87507d02ef9bea30b190dc1b956470935ca1
--- /dev/null
+++ b/addons/website/static/src/xml/theme_preview.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<templates id="template" xml:space="preserve">
+    <t t-name="website.ThemePreview.Buttons">
+        <div>
+            <div class="o_form_buttons_view" role="toolbar" aria-label="Main actions">
+                <button type="object" name="button_choose_theme" class="btn btn-primary o_use_theme">
+                    Start Now
+                </button>
+                <button class="btn btn-link o_switch_theme">
+                    Choose another theme
+                </button>
+                <button class="o_switch_mode_button"></button>
+            </div>
+        </div>
+    </t>
+
+    <t t-name="website.ThemePreview.SwitchModeButton">
+        <button class="o_switch_mode_button btn btn-light d-none d-md-inline">
+            <i t-attf-class="fa #{icon or 'fa-refresh'} mr-1"></i>
+            <t t-esc="PreviewType"/> Preview
+        </button>
+    </t>
+    <t t-name="website.ThemePreview.Loader">
+        <div class="o_theme_install_loader_container position-fixed fixed-top fixed-left h-100 w-100 bg-white d-flex justify-content-center align-items-center">
+            <div class="o_theme_install_loader"></div>
+        </div>
+    </t>
+</templates>
diff --git a/addons/website/static/src/xml/website_widget.xml b/addons/website/static/src/xml/website_widget.xml
new file mode 100644
index 0000000000000000000000000000000000000000..48a6d7c5503c4a5353062dab5f18c92150d9fbda
--- /dev/null
+++ b/addons/website/static/src/xml/website_widget.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<templates xml:space="preserve">
+
+    <t t-name="website.iframeWidget">
+        <iframe
+            t-if="url"
+            height="100%"
+            width="100%"
+            frameBorder="0"
+            t-att-src="url"
+            class='d-block'
+        ></iframe>
+        <div t-else="">No Url</div>
+    </t>
+
+</templates>
diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml
index 01aab69e7f5a6685d084468cb9469e82633990bf..259aa6bc9b6f6a58ed2f89a29b08489afab5a6cf 100644
--- a/addons/website/views/website_templates.xml
+++ b/addons/website/views/website_templates.xml
@@ -36,6 +36,9 @@
         <script type="text/javascript" src="/website/static/src/js/backend/button.js"/>
         <script type="text/javascript" src="/website/static/src/js/backend/dashboard.js"/>
         <script type="text/javascript" src="/website/static/src/js/backend/res_config_settings.js"/>
+        <script type="text/javascript" src="/website/static/src/js/widget_iframe.js"/>
+        <script type="text/javascript" src="/website/static/src/js/theme_preview_kanban.js"/>
+        <script type="text/javascript" src="/website/static/src/js/theme_preview_form.js"/>
     </xpath>
 </template>
 
diff --git a/addons/website/views/website_views.xml b/addons/website/views/website_views.xml
index 6fe26f86379bde75866f187334999355b8bca1ba..51fefb5bfb4eb955c3fdfb9b957f6c660b7f3c4d 100644
--- a/addons/website/views/website_views.xml
+++ b/addons/website/views/website_views.xml
@@ -289,7 +289,7 @@
             <field name="name">Themes Kanban</field>
             <field name="model">ir.module.module</field>
             <field name="arch" type="xml">
-                <kanban create="false" class="o_theme_kanban" default_order="state,sequence,name">
+                <kanban create="false" class="o_theme_kanban" default_order="state,sequence,name" js_class="theme_preview_kanban">
                     <field name="icon"/>
                     <field name="name"/>
                     <field name="state"/>
@@ -314,7 +314,7 @@
                                 <div t-else="" class="o_button_area">
                                     <button type="object" name="button_choose_theme" class="btn btn-primary">Use this theme</button>
                                     <hr t-if="record.url.value"/>
-                                    <a role="button" t-if="record.url.value" class="btn btn-secondary" t-att-href="record.url.value" target="_blank">Live Preview</a>
+                                    <button role="button" type="edit" t-if="record.url.value" class="btn btn-secondary">Live Preview</button>
                                 </div>
                                 <i states="installed" t-if="record.is_installed_on_current_website.raw_value"
                                     class="fa fa-check position-absolute p-1 m-2 rounded-circle bg-primary shadow"
@@ -357,18 +357,6 @@
         </record>
 
         <!-- Actions to list themes with custom kanban (launched on module installation) -->
-        <record id="theme_install_kanban_action" model="ir.actions.act_window">
-            <field name="name">Choose a theme for your website</field>
-            <field name="res_model">ir.module.module</field>
-            <field name="view_mode">kanban</field>
-            <field name="view_id" ref="theme_view_kanban"/>
-            <field name="search_view_id" ref="theme_view_search"/>
-            <field name="domain" eval="[
-                ('category_id', 'not in', [ref('base.module_category_hidden', False), ref('base.module_category_theme_hidden', False)]),
-                '|', ('category_id', '=', ref('base.module_category_theme', False)), ('category_id.parent_id', '=', ref('base.module_category_theme', False))
-            ]"/>
-        </record>
-
         <record id="theme_install_todo_action" model="ir.actions.server">
             <field name="name">Config: Choose Your Theme</field>
             <field name="model_id" ref="model_ir_module_module"/>
@@ -387,6 +375,38 @@ action = {
             <field name="sequence">0</field>
         </record>
 
+        <record id="theme_view_form_preview" model="ir.ui.view">
+            <field name="name">website.form</field>
+            <field name="model">ir.module.module</field>
+            <field name="mode">primary</field>
+            <field name="arch" type="xml">
+                <form create="false" edit="false" delete="0" js_class="theme_preview_form">
+                  <div class="o_preview_frame h-100">
+                        <field name='url' widget='iframe'/>
+                        <img alt='' class='img_mobile' style='display:none' src="/website/static/src/img/phone.png"/>
+                  </div>
+
+                </form>
+            </field>
+        </record>
+
+        <record id="theme_install_kanban_action" model="ir.actions.act_window">
+            <field name="name">Choose a theme for your website</field>
+            <field name="res_model">ir.module.module</field>
+            <field name="view_mode">kanban,form</field>
+            <field name="view_id" ref="website.theme_view_kanban" />
+            <field name="target">fullscreen</field>
+            <field name="view_ids"
+                   eval="[(5, 0, 0),
+                          (0, 0, {'view_mode': 'kanban', 'view_id': ref('website.theme_view_kanban')}),
+                          (0, 0, {'view_mode': 'form', 'view_id': ref('website.theme_view_form_preview')})]"/>
+            <field name="search_view_id" ref="theme_view_search"/>
+            <field name="domain" eval="[
+                ('category_id', 'not in', [ref('base.module_category_hidden', False), ref('base.module_category_theme_hidden', False)]),
+                '|', ('category_id', '=', ref('base.module_category_theme', False)), ('category_id.parent_id', '=', ref('base.module_category_theme', False))
+            ]"/>
+        </record>
+
         <!-- ONBOARDING -->
         <template id="onboarding_website_theme_step">
             <t t-call="base.onboarding_step">