diff --git a/frappe/desk/page/desktop/__init__.py b/frappe/desk/page/desktop/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frappe/www/desktop.css b/frappe/desk/page/desktop/desktop.css
similarity index 100%
rename from frappe/www/desktop.css
rename to frappe/desk/page/desktop/desktop.css
diff --git a/frappe/desk/page/desktop/desktop.html b/frappe/desk/page/desktop/desktop.html
new file mode 100644
index 0000000000..986f9cbd98
--- /dev/null
+++ b/frappe/desk/page/desktop/desktop.html
@@ -0,0 +1,14 @@
+
+
+
+
+ {% for icon in icons %}
+
+
+ {% endfor %}
+
+
+
diff --git a/frappe/desk/page/desktop/desktop.js b/frappe/desk/page/desktop/desktop.js
new file mode 100644
index 0000000000..437c43bda4
--- /dev/null
+++ b/frappe/desk/page/desktop/desktop.js
@@ -0,0 +1,34 @@
+frappe.pages["desktop"].on_page_load = function (wrapper) {
+ var page = frappe.ui.make_app_page({
+ parent: wrapper,
+ title: "Desktop",
+ single_column: true,
+ });
+ page.page_head.hide();
+ $(frappe.render_template("desktop")).appendTo(page.body);
+ setup();
+};
+function setup() {
+ $(".desktop-icon").each((i, el) => {
+ let icon_name = $(el).attr("data-icon");
+ let icon_container = $(el.children[0]);
+ const svg = frappe.utils.icon(icon_name, "xl d-icon");
+ if (svg) {
+ icon_container.html(svg);
+ }
+ let color_name = icon_container.attr("data-color");
+ icon_container.css("background-color", color_name);
+ });
+ setup_click();
+}
+
+function setup_click() {
+ $(".desktop-icon").on("click", (ev) => {
+ let current = $(ev.currentTarget);
+ if (current.attr("data-type") == "workspace") {
+ window.location.href = window.location.origin + current.attr("data-route");
+ } else {
+ window.location.href = current.attr("data-route");
+ }
+ });
+}
diff --git a/frappe/desk/page/desktop/desktop.json b/frappe/desk/page/desktop/desktop.json
new file mode 100644
index 0000000000..8128a50518
--- /dev/null
+++ b/frappe/desk/page/desktop/desktop.json
@@ -0,0 +1,24 @@
+{
+ "content": null,
+ "creation": "2025-08-18 16:17:07.259326",
+ "docstatus": 0,
+ "doctype": "Page",
+ "icon": "",
+ "idx": 0,
+ "modified": "2025-08-18 16:17:19.559412",
+ "modified_by": "Administrator",
+ "module": "Desk",
+ "name": "desktop",
+ "owner": "Administrator",
+ "page_name": "desktop",
+ "roles": [
+ {
+ "role": "System Manager"
+ }
+ ],
+ "script": null,
+ "standard": "Yes",
+ "style": null,
+ "system_page": 1,
+ "title": "Desktop"
+}
diff --git a/frappe/www/desktop.py b/frappe/desk/page/desktop/desktop.py
similarity index 87%
rename from frappe/www/desktop.py
rename to frappe/desk/page/desktop/desktop.py
index 1a51ac7896..87c357b7ef 100644
--- a/frappe/www/desktop.py
+++ b/frappe/desk/page/desktop/desktop.py
@@ -7,4 +7,4 @@ def get_context(context):
frappe.local.flags.redirect_location = "/app"
raise frappe.Redirect
context.icons = get_desktop_icons()
- return context
+ return {"icons": get_desktop_icons()}
diff --git a/frappe/hooks.py b/frappe/hooks.py
index 08d561e172..b8c8901320 100644
--- a/frappe/hooks.py
+++ b/frappe/hooks.py
@@ -60,7 +60,7 @@ website_route_rules = [
]
website_redirects = [
- {"source": r"/desk", "target": r"/app\1"},
+ {"source": r"/desk(.*)", "target": r"/app\1"},
]
base_template = "templates/base.html"
diff --git a/frappe/public/js/frappe/ui/page.js b/frappe/public/js/frappe/ui/page.js
index c069f5974c..5f7fa749ca 100644
--- a/frappe/public/js/frappe/ui/page.js
+++ b/frappe/public/js/frappe/ui/page.js
@@ -136,7 +136,7 @@ frappe.ui.Page = class Page {
this.page_actions = this.wrapper.find(".page-actions");
this.filters = this.wrapper.find(".filters");
-
+ this.page_head = this.wrapper.find(".page-head");
this.btn_primary = this.page_actions.find(".primary-action");
this.btn_secondary = this.page_actions.find(".btn-secondary");
diff --git a/frappe/www/desktop.html b/frappe/www/desktop.html
deleted file mode 100644
index cc2a9ddea4..0000000000
--- a/frappe/www/desktop.html
+++ /dev/null
@@ -1,49 +0,0 @@
----
-base_template: "templates/base.html"
-no_cache: 1
----
-
-{%- block navbar -%} {% from "frappe/templates/includes/avatar_macro.html" import avatar %} {%-
-endblock -%} {%- block footer -%} {%- endblock -%} {% block content %}
-
-
-
- {% for icon in icons %}
-
-
- {% endfor %}
-
-
-
-
-{% endblock %} {% block script %}
-
-{% endblock %}