diff --git a/bookmarks/templates/bookmarks/head.html b/bookmarks/templates/bookmarks/head.html
index 1f64e9d..94beb5f 100644
--- a/bookmarks/templates/bookmarks/head.html
+++ b/bookmarks/templates/bookmarks/head.html
@@ -7,6 +7,7 @@
+
diff --git a/bookmarks/templates/opensearch.xml b/bookmarks/templates/opensearch.xml
new file mode 100644
index 0000000..850adde
--- /dev/null
+++ b/bookmarks/templates/opensearch.xml
@@ -0,0 +1,7 @@
+
+ Linkding
+ Linkding
+ UTF-8
+ {{base_url}}static/favicon.ico
+
+
diff --git a/bookmarks/tests/test_opensearch_view.py b/bookmarks/tests/test_opensearch_view.py
new file mode 100644
index 0000000..3693d06
--- /dev/null
+++ b/bookmarks/tests/test_opensearch_view.py
@@ -0,0 +1,25 @@
+from django.test import TestCase
+from django.urls import reverse
+
+
+class OpenSearchViewTestCase(TestCase):
+
+ def test_opensearch_configuration(self):
+ response = self.client.get(reverse("linkding:opensearch"))
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(
+ response["content-type"], "application/opensearchdescription+xml"
+ )
+
+ base_url = "http://testserver"
+ expected_content = f"""
+
+ Linkding
+ Linkding
+ UTF-8
+ {base_url}/static/favicon.ico
+
+
+ """
+ content = response.content.decode()
+ self.assertXMLEqual(content, expected_content)
diff --git a/bookmarks/urls.py b/bookmarks/urls.py
index 611a73f..be0273a 100644
--- a/bookmarks/urls.py
+++ b/bookmarks/urls.py
@@ -80,6 +80,8 @@ urlpatterns = [
path("manifest.json", views.manifest, name="manifest"),
# Custom CSS
path("custom_css", views.custom_css, name="custom_css"),
+ # OpenSearch
+ path("opensearch.xml", views.opensearch, name="opensearch"),
]
# Put all linkding URLs into a linkding namespace
diff --git a/bookmarks/views/__init__.py b/bookmarks/views/__init__.py
index 1fbe567..802057b 100644
--- a/bookmarks/views/__init__.py
+++ b/bookmarks/views/__init__.py
@@ -7,3 +7,4 @@ from .health import health
from .manifest import manifest
from .custom_css import custom_css
from .root import root
+from .opensearch import opensearch
diff --git a/bookmarks/views/opensearch.py b/bookmarks/views/opensearch.py
new file mode 100644
index 0000000..d8b55ae
--- /dev/null
+++ b/bookmarks/views/opensearch.py
@@ -0,0 +1,18 @@
+from django.urls import reverse
+from django.shortcuts import render
+
+
+def opensearch(request):
+ base_url = request.build_absolute_uri(reverse("linkding:root"))
+ bookmarks_url = request.build_absolute_uri(reverse("linkding:bookmarks.index"))
+
+ return render(
+ request,
+ "opensearch.xml",
+ {
+ "base_url": base_url,
+ "bookmarks_url": bookmarks_url,
+ },
+ content_type="application/opensearchdescription+xml",
+ status=200,
+ )