diff --git a/config/plugins/visualizations/common/templates/observable_entry_point.mako b/config/plugins/visualizations/common/templates/observable_entry_point.mako
new file mode 100644
index 000000000000..cf22c37dac30
--- /dev/null
+++ b/config/plugins/visualizations/common/templates/observable_entry_point.mako
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+<%inherit file="visualization_base.mako"/>
+
+## Create a container, attach data and import script file
+<%def name="get_body()">
+ <%
+ from markupsafe import escape
+
+ ## Collect incoming data
+ data_incoming = {
+ "root": h.url_for("/"),
+ "visualization_id": visualization_id,
+ "visualization_name": visualization_name,
+ "visualization_plugin": visualization_plugin,
+ "visualization_title": escape(title),
+ "visualization_config": config }
+
+ ## Load script source
+ script_src = script_attributes.get("src")
+ %>
+
+ ## Create container and initialize notebook
+
+
+
+%def>
diff --git a/config/plugins/visualizations/example_observable/config/example_observable.xml b/config/plugins/visualizations/example_observable/config/example_observable.xml
new file mode 100644
index 000000000000..c904e6b0af75
--- /dev/null
+++ b/config/plugins/visualizations/example_observable/config/example_observable.xml
@@ -0,0 +1,16 @@
+
+
+
+ Welcome to the Observable Example Plugin.
+
+
+ HistoryDatasetAssociation
+ csv
+ dataset_id
+
+
+
+ dataset_id
+
+
+
diff --git a/config/plugins/visualizations/example_observable/static/logo.png b/config/plugins/visualizations/example_observable/static/logo.png
new file mode 100644
index 000000000000..0c13459935bb
Binary files /dev/null and b/config/plugins/visualizations/example_observable/static/logo.png differ
diff --git a/lib/galaxy/visualization/plugins/config_parser.py b/lib/galaxy/visualization/plugins/config_parser.py
index 2e784abda7bc..bca286bf7d78 100644
--- a/lib/galaxy/visualization/plugins/config_parser.py
+++ b/lib/galaxy/visualization/plugins/config_parser.py
@@ -33,7 +33,7 @@ class VisualizationsConfigParser:
"""
#: what are the allowed 'entry_point_type' for entry_point elements
- ALLOWED_ENTRY_POINT_TYPES = ["mako", "html", "script", "chart"]
+ ALLOWED_ENTRY_POINT_TYPES = ["mako", "html", "script", "chart", "observable"]
#: what are the allowed href targets when clicking on a visualization anchor
VALID_RENDER_TARGETS = ["galaxy_main", "_top", "_blank"]
diff --git a/lib/galaxy/visualization/plugins/plugin.py b/lib/galaxy/visualization/plugins/plugin.py
index e3bdf0e03d3c..6f17454d783f 100644
--- a/lib/galaxy/visualization/plugins/plugin.py
+++ b/lib/galaxy/visualization/plugins/plugin.py
@@ -267,6 +267,9 @@ class ChartVisualizationPlugin(ScriptVisualizationPlugin):
MAKO_TEMPLATE = "chart_entry_point.mako"
+class ObservableVisualizationPlugin(ScriptVisualizationPlugin):
+ MAKO_TEMPLATE = "observable_entry_point.mako"
+
class StaticFileVisualizationPlugin(VisualizationPlugin):
"""
A visualization plugin that starts by loading a static html file defined in
diff --git a/lib/galaxy/visualization/plugins/registry.py b/lib/galaxy/visualization/plugins/registry.py
index efc32e3f42c0..1786c390bd7f 100644
--- a/lib/galaxy/visualization/plugins/registry.py
+++ b/lib/galaxy/visualization/plugins/registry.py
@@ -201,6 +201,9 @@ def _build_plugin(self, plugin_name, plugin_path, config):
# from a static file (html, etc)
elif config["entry_point"]["type"] == "html":
plugin_class = vis_plugins.StaticFileVisualizationPlugin
+ # from an observable notebook
+ elif config["entry_point"]["type"] == "observable":
+ plugin_class = vis_plugins.ObservableVisualizationPlugin
return plugin_class(
self.app(),
plugin_path,