diff --git a/invenio_previewer/assets/bootstrap3/js/invenio_previewer/csv_previewer/csv_d3js.js b/invenio_previewer/assets/bootstrap3/js/invenio_previewer/csv_previewer/csv_d3js.js
deleted file mode 100644
index 8c6e7d4f0afa04790547f47413bda9a8769013ca..0000000000000000000000000000000000000000
--- a/invenio_previewer/assets/bootstrap3/js/invenio_previewer/csv_previewer/csv_d3js.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * This file is part of Invenio.
- * Copyright (C) 2015-2019 CERN.
- *
- * Invenio is free software; you can redistribute it and/or modify it
- * under the terms of the MIT License; see LICENSE file for more details.
- */
-
-import d3 from "d3";
-import flight from "flightjs";
-
-function CSV_D3JS() {
-  var CSV_D3JS;
-
-  this.tabulate = function(data, target, columns) {
-    var table = d3
-      .select(target)
-      .append("table")
-      .classed({
-        table: true,
-        "table-hover": true,
-        "table-bordered": true,
-      });
-    CSV_D3JS.thead = table.append("thead");
-    CSV_D3JS.tbody = table.append("tbody");
-    CSV_D3JS.columns = columns;
-    CSV_D3JS.data = data;
-
-    // append the header row
-    CSV_D3JS.thead
-      .append("tr")
-      .selectAll("th")
-      .data(CSV_D3JS.columns)
-      .enter()
-      .append("th")
-      .text(function(column) {
-        return column;
-      });
-
-    CSV_D3JS.next = 1;
-    CSV_D3JS.chunk_size = 500;
-    CSV_D3JS.chunks = Math.ceil(CSV_D3JS.data.length / CSV_D3JS.chunk_size);
-
-    CSV_D3JS.loadNext(undefined, {
-      id: CSV_D3JS.id,
-    });
-    if (CSV_D3JS.chunks > 1) {
-      CSV_D3JS.trigger(document, "showLoader", {
-        id: CSV_D3JS.id,
-      });
-    }
-
-    return true;
-  };
-
-  this.loadNext = function(ev, data) {
-    if (data.id === CSV_D3JS.id && CSV_D3JS.next <= CSV_D3JS.chunks) {
-      // create a row for each object in the data chunk
-      CSV_D3JS.tbody
-        .selectAll("tr")
-        .data(CSV_D3JS.data.slice(0, CSV_D3JS.next * CSV_D3JS.chunk_size))
-        .enter()
-        .append("tr")
-        .selectAll("td")
-        .data(function(row) {
-          return CSV_D3JS.columns.map(function(column) {
-            return { column: column, value: row[column] };
-          });
-        })
-        .enter()
-        .append("td")
-        .text(function(d) {
-          return d.value;
-        });
-
-      if (CSV_D3JS.next === CSV_D3JS.chunks) {
-        CSV_D3JS.trigger(document, "hideLoader", {
-          id: CSV_D3JS.id,
-        });
-      }
-      CSV_D3JS.next += 1;
-    }
-  };
-
-  this.after("initialize", function() {
-    CSV_D3JS = this;
-    CSV_D3JS.id = CSV_D3JS.node.id;
-
-    var delimiter = CSV_D3JS.$node.data("csv-delimiter"),
-      encoding = CSV_D3JS.$node.data("csv-encoding"),
-      resource = CSV_D3JS.$node.data("csv-source"),
-      dsv = d3.dsv(delimiter, "text/csv; charset=" + encoding);
-
-    dsv(resource, function(data) {
-      var col = Object.keys(data[0]);
-      CSV_D3JS.tabulate(data, CSV_D3JS.node, col);
-    });
-
-    this.on(document, "loadNext", this.loadNext);
-  });
-}
-
-export default flight.component(CSV_D3JS);
diff --git a/invenio_previewer/assets/bootstrap3/js/invenio_previewer/csv_previewer/init.js b/invenio_previewer/assets/bootstrap3/js/invenio_previewer/csv_previewer/init.js
index 66f042dc341b53574120baaf476e6accfa773115..6f04dffb43953bb087b6e9e73370618c1b466d98 100644
--- a/invenio_previewer/assets/bootstrap3/js/invenio_previewer/csv_previewer/init.js
+++ b/invenio_previewer/assets/bootstrap3/js/invenio_previewer/csv_previewer/init.js
@@ -1,20 +1,80 @@
 /*
  * This file is part of Invenio.
- * Copyright (C) 2015-2019 CERN.
+ * Copyright (C) 2015-2023 CERN.
  *
  * Invenio is free software; you can redistribute it and/or modify it
  * under the terms of the MIT License; see LICENSE file for more details.
  */
 
-import $ from 'jquery';
-import CSV_D3JS from './csv_d3js';
-import Loader from './loader.js';
-
-$(function () {
-  $("[data-csv-source]").each(function () {
-    CSV_D3JS.attachTo($(this));
-  })
-  $("[data-csv-target]").each(function () {
-    Loader.attachTo($(this));
-  })
-})
+import $ from "jquery";
+import Papa from "papaparse";
+
+(function ($, Papa) {
+  function createDataElement(htmlTag, innerText) {
+    const node = document.createElement(htmlTag);
+    const textNode = document.createTextNode(innerText);
+    node.appendChild(textNode);
+    return node;
+  }
+
+  const URL = $("#app").attr("data-csv-source");
+  const maxRowsPerChunk = 50;
+  const $tableHeader = $("#table-header");
+  const $tableBody = $("#table-body");
+  const $showMore = $("#show-more");
+
+  let isFirst = true;
+  let currentStep = 0;
+  let papaParser = null;
+
+  $showMore.hide(); // hide it when init
+  $showMore.on("click", function () {
+    currentStep = 0;
+    papaParser.resume();
+  });
+
+  Papa.parse(URL, {
+    download: true,
+    skipEmptyLines: true,
+    step: function (results, parser) {
+      papaParser = papaParser || parser;
+      currentStep++;
+      console.debug("CSV previewer: rendering step", results);
+      const row = results.data || [];
+
+      const tableRowEl = document.createElement("tr");
+      let tableColEl;
+      if (isFirst) {
+        $tableHeader.append(tableRowEl);
+        tableColEl = "th";
+        isFirst = false;
+      } else {
+        $tableBody.append(tableRowEl);
+        tableColEl = "td";
+      }
+
+      row.forEach((col) => {
+        const node = createDataElement(tableColEl, col);
+        tableRowEl.appendChild(node);
+      });
+
+      if (currentStep >= maxRowsPerChunk) {
+        parser.pause();
+        $showMore.show();
+      }
+    },
+    error: function (err, file, inputElem, reason) {
+      console.error(
+        "CSV previewer: error rendering CSV file: ",
+        err,
+        file,
+        inputElem,
+        reason
+      );
+    },
+    complete: function (results, file) {
+      console.debug("CSV previewer: rendering completed", results, file);
+      $showMore.hide();
+    },
+  });
+})($, Papa);
diff --git a/invenio_previewer/assets/bootstrap3/js/invenio_previewer/csv_previewer/loader.js b/invenio_previewer/assets/bootstrap3/js/invenio_previewer/csv_previewer/loader.js
deleted file mode 100644
index f14f4b437a32d4e75f1cecfdbc699e60a9e36c63..0000000000000000000000000000000000000000
--- a/invenio_previewer/assets/bootstrap3/js/invenio_previewer/csv_previewer/loader.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This file is part of Invenio.
- * Copyright (C) 2015-2019 CERN.
- *
- * Invenio is free software; you can redistribute it and/or modify it
- * under the terms of the MIT License; see LICENSE file for more details.
- */
-
-import flight from "flightjs";
-
-function Loader() {
-  var Loader;
-
-  this.handleShowLoader = function(ev, data) {
-    if (data.id === Loader.id) {
-      this.$node.show();
-    }
-  };
-
-  this.handleHideLoader = function(ev, data) {
-    if (data.id === Loader.id) {
-      this.$node.hide();
-    }
-  };
-
-  this.after("initialize", function() {
-    Loader = this;
-    Loader.id = Loader.$node.data("csv-target");
-
-    Loader.on(document, "showLoader", Loader.handleShowLoader);
-    Loader.on(document, "hideLoader", Loader.handleHideLoader);
-    Loader.on("click", function(ev) {
-      ev.preventDefault();
-      Loader.trigger(document, "loadNext", {
-        id: Loader.id,
-      });
-    });
-
-    Loader.$node.hide();
-  });
-}
-
-export default flight.component(Loader);
diff --git a/invenio_previewer/assets/semantic-ui/js/invenio_previewer/csv_previewer/init.js b/invenio_previewer/assets/semantic-ui/js/invenio_previewer/csv_previewer/init.js
index b84e99020aeb2f12573e0100a685902b5350b866..6f04dffb43953bb087b6e9e73370618c1b466d98 100644
--- a/invenio_previewer/assets/semantic-ui/js/invenio_previewer/csv_previewer/init.js
+++ b/invenio_previewer/assets/semantic-ui/js/invenio_previewer/csv_previewer/init.js
@@ -1,59 +1,80 @@
 /*
  * This file is part of Invenio.
- * Copyright (C) 2015-2020 CERN.
+ * Copyright (C) 2015-2023 CERN.
  *
  * Invenio is free software; you can redistribute it and/or modify it
  * under the terms of the MIT License; see LICENSE file for more details.
  */
 
 import $ from "jquery";
-import Papa from 'papaparse';
-
-function createDataElement(htmlTag, innerText, parentNode) {
-    let node = document.createElement(htmlTag);
-    let textnode = document.createTextNode(innerText);
-    node.appendChild(textnode);
-    parentNode.appendChild(node);
-}
-
-var link = "https://" + window.location.host + $("[data-csv-source]").attr('data-csv-source');
-var header = true;
-var limit = 50;
-var step = 0;
-var global_parser ;
-$("#more_data").click(function () {
-  step = 0;
-  global_parser.resume();
-});
-
-
-var results = Papa.parse(link, {
-  download: true,
-  skipEmptyLines: true,
-  step: function(row, parser) {
-     var element;
-     var node = document.createElement("tr");
-     if (header) {
-        header = false;
-        element ="th";
-        $("#tableHeader").append(node);
-     } else {
-        element = "td";
-        $("#tableBody").append(node);
-     }
-
-     for(let j = 0; j < row.data.length; j++) {
-        createDataElement(element, row.data[j], node);
-     }
-     step++;
-     if (step >= limit) {
-       parser.pause();
-       global_parser = parser;
-     }
-  },
-  complete: function(results) {
-     $("#more_data").hide();
+import Papa from "papaparse";
+
+(function ($, Papa) {
+  function createDataElement(htmlTag, innerText) {
+    const node = document.createElement(htmlTag);
+    const textNode = document.createTextNode(innerText);
+    node.appendChild(textNode);
+    return node;
   }
 
-});
+  const URL = $("#app").attr("data-csv-source");
+  const maxRowsPerChunk = 50;
+  const $tableHeader = $("#table-header");
+  const $tableBody = $("#table-body");
+  const $showMore = $("#show-more");
+
+  let isFirst = true;
+  let currentStep = 0;
+  let papaParser = null;
+
+  $showMore.hide(); // hide it when init
+  $showMore.on("click", function () {
+    currentStep = 0;
+    papaParser.resume();
+  });
+
+  Papa.parse(URL, {
+    download: true,
+    skipEmptyLines: true,
+    step: function (results, parser) {
+      papaParser = papaParser || parser;
+      currentStep++;
+      console.debug("CSV previewer: rendering step", results);
+      const row = results.data || [];
+
+      const tableRowEl = document.createElement("tr");
+      let tableColEl;
+      if (isFirst) {
+        $tableHeader.append(tableRowEl);
+        tableColEl = "th";
+        isFirst = false;
+      } else {
+        $tableBody.append(tableRowEl);
+        tableColEl = "td";
+      }
+
+      row.forEach((col) => {
+        const node = createDataElement(tableColEl, col);
+        tableRowEl.appendChild(node);
+      });
 
+      if (currentStep >= maxRowsPerChunk) {
+        parser.pause();
+        $showMore.show();
+      }
+    },
+    error: function (err, file, inputElem, reason) {
+      console.error(
+        "CSV previewer: error rendering CSV file: ",
+        err,
+        file,
+        inputElem,
+        reason
+      );
+    },
+    complete: function (results, file) {
+      console.debug("CSV previewer: rendering completed", results, file);
+      $showMore.hide();
+    },
+  });
+})($, Papa);
diff --git a/invenio_previewer/extensions/__init__.py b/invenio_previewer/extensions/__init__.py
index c7e18d2345236a72f034f4be07efa7927f197b71..fa47ed5ab10ae5bfe6079eb257dcba67d8e1c393 100644
--- a/invenio_previewer/extensions/__init__.py
+++ b/invenio_previewer/extensions/__init__.py
@@ -7,5 +7,3 @@
 # under the terms of the MIT License; see LICENSE file for more details.
 
 """Implementations of different viewers."""
-
-from __future__ import absolute_import, print_function
diff --git a/invenio_previewer/extensions/ipynb.py b/invenio_previewer/extensions/ipynb.py
index 06cd5880a427edc8a09293c301be7d773ee9edcc..64e87a19e40adb9b412089e6874fd084ca371017 100644
--- a/invenio_previewer/extensions/ipynb.py
+++ b/invenio_previewer/extensions/ipynb.py
@@ -9,7 +9,7 @@
 
 """Jupyter Notebook previewer."""
 
-from __future__ import absolute_import, unicode_literals
+import os
 
 import nbformat
 from flask import render_template
@@ -20,6 +20,12 @@ from ..proxies import current_previewer
 
 previewable_extensions = ["ipynb"]
 
+# relative paths to the extra CSS of the default `lab` theme
+NBCONVERT_THEME_LAB_EXTRA_CSS = [
+    os.path.join("nbconvert", "templates", "lab", "static", "index.css"),
+    os.path.join("nbconvert", "templates", "lab", "static", "theme-light.css"),
+]
+
 
 def render(file):
     """Generate the result HTML."""
@@ -28,11 +34,11 @@ def render(file):
     try:
         notebook = nbformat.reads(content.decode("utf-8"), as_version=4)
     except nbformat.reader.NotJSONError:
-        return _("Error: Not a json file"), {}
+        return _("Error: Not a ipynb/json file"), {}
 
-    html_exporter = HTMLExporter(template="lab", embed_images=True)
+    html_exporter = HTMLExporter(embed_images=True, sanitize_html=True)
     html_exporter.template_file = "base"
-    (body, resources) = html_exporter.from_notebook_node(notebook)
+    body, resources = html_exporter.from_notebook_node(notebook)
     return body, resources
 
 
@@ -44,10 +50,14 @@ def can_preview(file):
 def preview(file):
     """Render the IPython Notebook."""
     body, resources = render(file)
+    default_jupyter_nb_style = ""
     if "inlining" in resources:
-        default_jupyter_nb_style = resources["inlining"]["css"][0]
-    else:
-        default_jupyter_nb_style = ""
+        default_jupyter_nb_style += resources["inlining"]["css"][0]
+    # the include_css func will load extra CSS from disk
+    if "include_css" in resources:
+        fn = resources["include_css"]
+        for extra_css_path in NBCONVERT_THEME_LAB_EXTRA_CSS:
+            default_jupyter_nb_style += fn(extra_css_path)
     return render_template(
         "invenio_previewer/ipynb.html",
         file=file,
diff --git a/invenio_previewer/extensions/mistune.py b/invenio_previewer/extensions/mistune.py
index 20e9d9c148b42d24bb361cd2d98e90e4ece6b31d..0cd60d2c2bb2159e700abd25a6b4bbfbdecfe882 100644
--- a/invenio_previewer/extensions/mistune.py
+++ b/invenio_previewer/extensions/mistune.py
@@ -8,8 +8,6 @@
 
 """Markdown rendering using mistune library."""
 
-from __future__ import absolute_import, unicode_literals
-
 import bleach
 import mistune
 from flask import render_template
diff --git a/invenio_previewer/static/css/prismjs/simple.css b/invenio_previewer/static/css/prismjs/simple.css
deleted file mode 100644
index 195ce1ba304cd6688ecba601d80ceec45afd52bb..0000000000000000000000000000000000000000
--- a/invenio_previewer/static/css/prismjs/simple.css
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * This file is part of Invenio.
- * Copyright (C) 2016-2019 CERN.
- *
- * Invenio is free software; you can redistribute it and/or modify it
- * under the terms of the MIT License; see LICENSE file for more details.
- */
-
-code[class*="language-"],
-pre[class*="language-"] {
-  line-height: 1.0;
-}
-
-:not(pre) > code[class*="language-"],
-pre[class*="language-"] {
-  background: white;
-}
diff --git a/invenio_previewer/static/js/csv_previewer/csv_d3js.js b/invenio_previewer/static/js/csv_previewer/csv_d3js.js
deleted file mode 100644
index 6d12258d080a35053f0127efb78fca171c6d1be0..0000000000000000000000000000000000000000
--- a/invenio_previewer/static/js/csv_previewer/csv_d3js.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * This file is part of Invenio.
- * Copyright (C) 2015-2019 CERN.
- *
- * Invenio is free software; you can redistribute it and/or modify it
- * under the terms of the MIT License; see LICENSE file for more details.
- */
-'use strict';
-
-define(function(require) {
-
-  var $ = require('node_modules/jquery/dist/jquery'),
-      d3 = require('node_modules/d3/d3');
-
-  return require('node_modules/flightjs/build/flight').component(CSV_D3JS);
-
-  function CSV_D3JS() {
-
-    var CSV_D3JS;
-
-    this.tabulate = function (data, target, columns) {
-
-      var table = d3.select(target).append("table").classed({
-        'table': true,
-        'table-hover': true,
-        'table-bordered': true,
-      });
-      CSV_D3JS.thead = table.append("thead");
-      CSV_D3JS.tbody = table.append("tbody");
-      CSV_D3JS.columns = columns;
-      CSV_D3JS.data = data;
-
-      // append the header row
-      CSV_D3JS.thead.append("tr")
-      .selectAll("th")
-      .data(CSV_D3JS.columns)
-      .enter()
-      .append("th")
-      .text(function(column) { return column; });
-
-      CSV_D3JS.next = 1;
-      CSV_D3JS.chunk_size = 500;
-      CSV_D3JS.chunks = Math.ceil(CSV_D3JS.data.length/CSV_D3JS.chunk_size);
-
-      CSV_D3JS.loadNext(undefined, {
-        id: CSV_D3JS.id
-      });
-      if (CSV_D3JS.chunks > 1) {
-        CSV_D3JS.trigger(document, "showLoader", {
-          id: CSV_D3JS.id
-        });
-      }
-
-      return true;
-    }
-
-    this.loadNext = function (ev, data) {
-      if (data.id===CSV_D3JS.id && CSV_D3JS.next <= CSV_D3JS.chunks) {
-        // create a row for each object in the data chunk
-        var rows = CSV_D3JS.tbody.selectAll("tr")
-        .data(CSV_D3JS.data.slice(0,CSV_D3JS.next*CSV_D3JS.chunk_size))
-        .enter()
-        .append("tr");
-        // create a cell in each row for each column
-        var cells = rows.selectAll("td")
-        .data(function(row) {
-          return CSV_D3JS.columns.map(function(column) {
-            return {column: column, value: row[column]};
-          });
-        })
-        .enter()
-        .append("td")
-        .text(function(d) { return d.value; });
-
-        if (CSV_D3JS.next === CSV_D3JS.chunks) {
-          CSV_D3JS.trigger(document, "hideLoader", {
-            id: CSV_D3JS.id
-          });
-        }
-        CSV_D3JS.next+=1;
-      }
-    }
-
-    this.after('initialize', function () {
-      CSV_D3JS = this;
-      CSV_D3JS.id = CSV_D3JS.node.id;
-
-      var delimiter = CSV_D3JS.$node.data("csv-delimiter"),
-          encoding = CSV_D3JS.$node.data("csv-encoding"),
-          resource = CSV_D3JS.$node.data("csv-source"),
-          dsv = d3.dsv(delimiter, "text/csv; charset=" + encoding);
-
-      dsv(resource, function(data) {
-        var col = Object.keys(data[0]);
-        CSV_D3JS.tabulate(data, CSV_D3JS.node, col);
-      });
-
-      this.on(document, 'loadNext', this.loadNext)
-    });
-
-  }
-
-});
diff --git a/invenio_previewer/static/js/csv_previewer/init.js b/invenio_previewer/static/js/csv_previewer/init.js
deleted file mode 100644
index 00ee84917533bab640853e9fed93f424eaa7c3da..0000000000000000000000000000000000000000
--- a/invenio_previewer/static/js/csv_previewer/init.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * This file is part of Invenio.
- * Copyright (C) 2015-2019 CERN.
- *
- * Invenio is free software; you can redistribute it and/or modify it
- * under the terms of the MIT License; see LICENSE file for more details.
- */
-
-requirejs(['js/csv_previewer/csv_d3js', 'js/csv_previewer/loader'], function(CSV_D3JS, Loader) {
-  $(function () {
-    $("[data-csv-source]").each(function () {
-      CSV_D3JS.attachTo($(this));
-    });
-    $("[data-csv-target]").each(function () {
-      Loader.attachTo($(this));
-    });
-  });
-})
diff --git a/invenio_previewer/static/js/csv_previewer/loader.js b/invenio_previewer/static/js/csv_previewer/loader.js
deleted file mode 100644
index f1669539aab070c4f7cef80627b17148dc50311b..0000000000000000000000000000000000000000
--- a/invenio_previewer/static/js/csv_previewer/loader.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * This file is part of Invenio.
- * Copyright (C) 2015-2019 CERN.
- *
- * Invenio is free software; you can redistribute it and/or modify it
- * under the terms of the MIT License; see LICENSE file for more details.
- */
-'use strict';
-
-define(function(require) {
-
-  var $ = require('node_modules/jquery/dist/jquery'),
-      d3 = require('node_modules/d3/d3');
-
-  return require('node_modules/flightjs/build/flight').component(Loader);
-
-  function Loader() {
-    var Loader;
-
-    this.handleShowLoader = function (ev, data) {
-      if (data.id === Loader.id){
-        this.$node.show();
-      }
-    };
-
-    this.handleHideLoader = function (ev, data) {
-      if (data.id === Loader.id){
-        this.$node.hide();
-      }
-    };
-
-    this.after('initialize', function () {
-      Loader = this;
-      Loader.id = Loader.$node.data('csv-target');
-
-      Loader.on(document, 'showLoader', Loader.handleShowLoader);
-      Loader.on(document, 'hideLoader', Loader.handleHideLoader);
-      Loader.on('click', function (ev) {
-        ev.preventDefault();
-        Loader.trigger(document, 'loadNext', {
-          id: Loader.id
-        });
-      });
-
-      Loader.$node.hide();
-    });
-  }
-
-});
diff --git a/invenio_previewer/static/js/zip/fullscreen.js b/invenio_previewer/static/js/zip/fullscreen.js
deleted file mode 100644
index 59af756a9def08665b66507969eac9d365601f2b..0000000000000000000000000000000000000000
--- a/invenio_previewer/static/js/zip/fullscreen.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This file is part of Invenio.
- * Copyright (C) 2015-2019 CERN.
- *
- * Invenio is free software; you can redistribute it and/or modify it
- * under the terms of the MIT License; see LICENSE file for more details.
- */
-
-var f = parent.document.getElementById('preview-iframe');
-if (f) {
-  var handleFullScreenClick = (function () {
-    var isFullScreen = false;
-
-    var pos = f.style.position,
-        zIndex = f.style.zIndex,
-        height = f.style.height,
-        width = f.style.width,
-        top = f.style.top,
-        left = f.style.left,
-        backgroundColor = f.style.backgroundColor;
-
-    return function () {
-      if (isFullScreen) {
-        isFullScreen = false;
-        f.style.position = pos;
-        f.style.zIndex = zIndex;
-        f.style.height = height;
-        f.style.width = width;
-        f.style.top = top;
-        f.style.left = left;
-        f.style.backgroundColor = backgroundColor;
-
-        parent.document.body.style.overflow = "";
-      } else {
-        isFullScreen = true;
-        f.style.position = "fixed";
-        f.style.zIndex = 9999;
-        f.style.height = "100%";
-        f.style.width = "100%";
-        f.style.top = 0;
-        f.style.left = 0;
-        f.style.backgroundColor="white";
-
-        parent.document.body.style.overflow = "hidden";
-      }
-    };
-  }());
-
-  var fsbtn = f.contentDocument.getElementById('fullScreenMode');
-  var secfsbtn = f.contentDocument.getElementById('secondaryFullScreenMode');
-  if (fsbtn) fsbtn.addEventListener('click', handleFullScreenClick);
-  if (secfsbtn) secfsbtn.addEventListener('click', handleFullScreenClick);
-} else {
-  var fsbtn = document.getElementById('fullScreenMode');
-  var secfsbtn = document.getElementById('secondaryFullScreenMode');
-
-  if (fsbtn) fsbtn.remove();
-  if (secfsbtn) secfsbtn.remove();
-}
diff --git a/invenio_previewer/templates/invenio_previewer/csv_bar.html b/invenio_previewer/templates/invenio_previewer/csv_bar.html
index d56dd71742729ffecf87f4a0410cf78babfa1d93..a898cb96f084b57b4f2602bf81275a7d8a876a62 100644
--- a/invenio_previewer/templates/invenio_previewer/csv_bar.html
+++ b/invenio_previewer/templates/invenio_previewer/csv_bar.html
@@ -1,18 +1,22 @@
 {# -*- coding: utf-8 -*-
 
   This file is part of Invenio.
-  Copyright (C) 2015-2019 CERN.
+  Copyright (C) 2015-2023 CERN.
 
   Invenio is free software; you can redistribute it and/or modify it
   under the terms of the MIT License; see LICENSE file for more details.
 #}
 
-{#- D3 view for viewing csv files -#}
-
 {%- extends config.PREVIEWER_ABSTRACT_TEMPLATE %}
 
 {% block panel %}
-  <div id="d3_csv_previewer" data-csv-source="{{ file.uri }}"
-       data-csv-delimiter="{{ delimiter }}" data-csv-encoding="{{ encoding }}"></div>
-  <a data-csv-target="d3_csv_previewer" href="">{{ _('Show more') }}</a>
+<div id="app" data-csv-source="{{ file.uri }}">
+  <table class="ui selectable celled table unstackable">
+    <thead id="table-header">
+    </thead>
+    <tbody id="table-body">
+    </tbody>
+  </table>
+  <button id="show-more" class="btn" >{{_('Show more')}}</button>
+</div>
 {% endblock %}
diff --git a/invenio_previewer/templates/invenio_previewer/ipynb.html b/invenio_previewer/templates/invenio_previewer/ipynb.html
index df2ecaa9d14781e65f6a54cd10f30fc254c5c27f..58c1de28710c07252220fd2b7015ecb2da567984 100644
--- a/invenio_previewer/templates/invenio_previewer/ipynb.html
+++ b/invenio_previewer/templates/invenio_previewer/ipynb.html
@@ -1,7 +1,7 @@
 {# -*- coding: utf-8 -*-
 
   This file is part of Invenio.
-  Copyright (C) 2015-2019 CERN.
+  Copyright (C) 2015-2020 CERN.
 
   Invenio is free software; you can redistribute it and/or modify it
   under the terms of the MIT License; see LICENSE file for more details.
@@ -17,11 +17,5 @@
 {% endblock %}
 
 {% block panel %}
-<div class="container">
-    <div class="row">
-        <div class="col-md-12">
-            {{ content | sanitize_html() | safe }}
-        </div>
-    </div>
-</div>
+  {{ content | safe }}
 {% endblock %}
diff --git a/invenio_previewer/templates/semantic-ui/invenio_previewer/csv_bar.html b/invenio_previewer/templates/semantic-ui/invenio_previewer/csv_bar.html
index e7e62e331899bccd944dcc54c1f714112a4f7090..7bba22c29ba7500874a37e479d80b59bade7c3e3 100644
--- a/invenio_previewer/templates/semantic-ui/invenio_previewer/csv_bar.html
+++ b/invenio_previewer/templates/semantic-ui/invenio_previewer/csv_bar.html
@@ -1,25 +1,22 @@
 {# -*- coding: utf-8 -*-
 
   This file is part of Invenio.
-  Copyright (C) 2015-2020 CERN.
+  Copyright (C) 2015-2023 CERN.
 
   Invenio is free software; you can redistribute it and/or modify it
   under the terms of the MIT License; see LICENSE file for more details.
 #}
 
-{#- D3 view for viewing csv files -#}
-
 {%- extends config.PREVIEWER_ABSTRACT_TEMPLATE %}
 
 {% block panel %}
 <div id="app" data-csv-source="{{ file.uri }}">
-
   <table class="ui selectable celled table unstackable">
-    <thead id="tableHeader">
+    <thead id="table-header">
     </thead>
-    <tbody id="tableBody">
+    <tbody id="table-body">
     </tbody>
   </table>
-  <button id="more_data" class="ui button" >{{_('Show more')}}</button>
+  <button id="show-more" class="ui button m-10" >{{_('Show more')}}</button>
 </div>
 {% endblock %}
diff --git a/invenio_previewer/templates/semantic-ui/invenio_previewer/ipynb.html b/invenio_previewer/templates/semantic-ui/invenio_previewer/ipynb.html
index 335ffe4e8a6db6680ac1e8e835b08e50a4284fe3..58c1de28710c07252220fd2b7015ecb2da567984 100644
--- a/invenio_previewer/templates/semantic-ui/invenio_previewer/ipynb.html
+++ b/invenio_previewer/templates/semantic-ui/invenio_previewer/ipynb.html
@@ -14,10 +14,8 @@
     <style>
         {{ inline_style | safe }}
     </style>
-{{ webpack["nbconvert_index_css.css"] }}
-{{ webpack["nbconvert_theme_light_css.css"] }}
 {% endblock %}
 
 {% block panel %}
-            {{ content | sanitize_html() | safe }}
+  {{ content | safe }}
 {% endblock %}
diff --git a/invenio_previewer/webpack.py b/invenio_previewer/webpack.py
index de48dc36a017dc4e453dd6c9da2c10877a2cbef8..f7618db3a7ac665321863ef764d1ebc13878ac93 100644
--- a/invenio_previewer/webpack.py
+++ b/invenio_previewer/webpack.py
@@ -25,17 +25,8 @@
 
 """JS/CSS bundles for Previewer."""
 
-from os import path
-
-# This seems like a hack... there must be a better way of doing it
-import nbconvert
 from invenio_assets.webpack import WebpackThemeBundle
 
-nbconvert_path = (
-    path.dirname(nbconvert.__file__)
-    + "/../../../../share/jupyter/nbconvert/templates/lab/static/"
-)
-
 previewer = WebpackThemeBundle(
     __name__,
     "assets",
@@ -81,8 +72,6 @@ previewer = WebpackThemeBundle(
                 "bottom_css": "./scss/invenio_previewer/bottom.scss",
                 "simple_image_css": "./scss/invenio_previewer/simple_image.scss",
                 "txt_css": "./scss/invenio_previewer/txt.scss",
-                "nbconvert_index_css": nbconvert_path + "index.css",
-                "nbconvert_theme_light_css": nbconvert_path + "theme-light.css",
             },
             dependencies={
                 "flightjs": "~1.5.1",
diff --git a/setup.cfg b/setup.cfg
index ddaf1512a3cb9c153fe6a90f8922996d641cb1c6..b0f09dc47be70115f40f83091c18c18f54bb5928 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -34,12 +34,9 @@ install_requires =
     invenio-i18n>=1.3.1
     invenio-pidstore>=1.2.3
     invenio-records-ui>=1.2.0
-    ipython>=4.1.0
     mistune>=0.8.1
-    nbconvert>=6.0,<7.0
-    nbclient>=0.5,<1.0
+    nbconvert>=7,<8
     nbformat>=5.1,<6.0
-    tornado>=6.1,<7.0
 
 [options.extras_require]
 tests =
diff --git a/tests/test_macros.py b/tests/test_macros.py
index 875ff3b1fd2a718f169796f557c8255c12ba9cb1..7c222a6c282d02f286b24ce54493e098aa354fba 100644
--- a/tests/test_macros.py
+++ b/tests/test_macros.py
@@ -192,7 +192,7 @@ def test_ipynb_extension(testapp, webassets, record):
       "cell_type": "markdown",
       "metadata": {},
       "source": [
-        "This is an example notebook."
+        "This is an example notebook.<script>alert();</script>"
       ]
     }
   ],
@@ -223,7 +223,10 @@ def test_ipynb_extension(testapp, webassets, record):
 
     with testapp.test_client() as client:
         res = client.get(preview_url(record["control_number"], "test.ipynb"))
-        assert "This is an example notebook." in res.get_data(as_text=True)
+        as_text = res.get_data(as_text=True)
+        assert "This is an example notebook." in as_text
+        # test HTML tag sanitize
+        assert "<script>alert();</script>" not in as_text
 
 
 def test_simple_image_extension(testapp, webassets, record):
@@ -232,8 +235,9 @@ def test_simple_image_extension(testapp, webassets, record):
 
     with testapp.test_client() as client:
         res = client.get(preview_url(record["control_number"], "test.png"))
-        assert '<img src="' in res.get_data(as_text=True)
-        assert 'class="previewer-simple-image"' in res.get_data(as_text=True)
+        as_text = res.get_data(as_text=True)
+        assert '<img src="' in as_text
+        assert 'class="previewer-simple-image"' in as_text
 
 
 def test_txt_extension_valid_file(testapp, webassets, record):